diff --git a/cesm/share_wrappers/wtracers_mod.F90 b/cesm/share_wrappers/wtracers_mod.F90 new file mode 100644 index 000000000..860640720 --- /dev/null +++ b/cesm/share_wrappers/wtracers_mod.F90 @@ -0,0 +1,18 @@ +module wtracers_mod + + !----------------------------------------------------------------------------- + ! This module wraps shr_wtracers_mod from the CESM_share repository to avoid direct + ! dependencies on this share code from CMEPS. + ! + ! See also the version of wtracers_mod in the ufs directory for when we do not have + ! access to the CESM_share library. + !----------------------------------------------------------------------------- + + use shr_wtracers_mod, only : wtracers_is_wtracer_field => shr_wtracers_is_wtracer_field + + implicit none + private + + public :: wtracers_is_wtracer_field ! return true if the given field name is a water tracer field + +end module wtracers_mod diff --git a/cime_config/buildexe b/cime_config/buildexe index 4923f016d..c8664d705 100755 --- a/cime_config/buildexe +++ b/cime_config/buildexe @@ -94,6 +94,7 @@ def _main_func(): if not skip_mediator: out.write(os.path.join(cmeps_dir, "mediator") + "\n") out.write(os.path.join(cmeps_dir, "cesm", "flux_atmocn") + "\n") + out.write(os.path.join(cmeps_dir, "cesm", "share_wrappers") + "\n") out.write(os.path.join(cmeps_dir, "cesm", "driver") + "\n") # build model executable diff --git a/mediator/CMakeLists.txt b/mediator/CMakeLists.txt index 80be3d2e8..b65004c37 100644 --- a/mediator/CMakeLists.txt +++ b/mediator/CMakeLists.txt @@ -1,6 +1,7 @@ project(cmeps Fortran) set(SRCFILES esmFldsExchange_cesm_mod.F90 med_fraction_mod.F90 + med_field_info_mod.F90 med_methods_mod.F90 med_phases_prep_ice_mod.F90 med_phases_restart_mod.F90 esmFldsExchange_hafs_mod.F90 med_internalstate_mod.F90 med_phases_aofluxes_mod.F90 diff --git a/mediator/med.F90 b/mediator/med.F90 index d7e0d20f5..81909d012 100644 --- a/mediator/med.F90 +++ b/mediator/med.F90 @@ -37,6 +37,8 @@ module MED use med_methods_mod , only : FB_diagnose => med_methods_FB_diagnose use med_methods_mod , only : FB_getFieldN => med_methods_FB_getFieldN use med_methods_mod , only : clock_timeprint => med_methods_clock_timeprint + use med_field_info_mod , only : med_field_info_type + use med_field_info_mod , only : med_field_info_array_from_names_wtracers, med_field_info_array_from_state use med_utils_mod , only : memcheck => med_memcheck use med_internalstate_mod , only : InternalState, med_internalstate_init, med_internalstate_coupling use med_internalstate_mod , only : med_internalstate_defaultmasks, logunit, maintask @@ -1636,6 +1638,7 @@ subroutine DataInitialize(gcomp, rc) ! local variables type(InternalState) :: is_local + type(med_field_info_type), allocatable :: field_info_array(:) type(ESMF_Clock) :: clock type(ESMF_State) :: importState, exportState type(ESMF_Time) :: time @@ -1749,19 +1752,25 @@ subroutine DataInitialize(gcomp, rc) trim(compname(n1))//'_'//trim(compname(n2)) end if + call med_field_info_array_from_state( & + state = is_local%wrap%NStateImp(n1), & + field_info_array = field_info_array, & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + ! Check import FB, if there is no field in it then use export FB ! to provide mesh information call State_GetNumFields(is_local%wrap%NStateImp(n2), fieldCount, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (fieldCount == 0) then call FB_init(is_local%wrap%FBImp(n1,n2), is_local%wrap%flds_scalar_name, & + field_info_array=field_info_array, & STgeom=is_local%wrap%NStateExp(n2), & - STflds=is_local%wrap%NStateImp(n1), & name='FBImp'//trim(compname(n1))//'_'//trim(compname(n2)), rc=rc) else call FB_init(is_local%wrap%FBImp(n1,n2), is_local%wrap%flds_scalar_name, & + field_info_array=field_info_array, & STgeom=is_local%wrap%NStateImp(n2), & - STflds=is_local%wrap%NStateImp(n1), & name='FBImp'//trim(compname(n1))//'_'//trim(compname(n2)), rc=rc) end if if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -1789,14 +1798,19 @@ subroutine DataInitialize(gcomp, rc) allocate(fldnames(fieldCount)) call med_fldList_getfldnames(fldListMed_ocnalb%fields, fldnames, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + call med_field_info_array_from_names_wtracers( & + field_names = fldnames, & + field_info_array = field_info_array, & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call FB_init(is_local%wrap%FBMed_ocnalb_a, is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateImp(compatm), fieldnamelist=fldnames, name='FBMed_ocnalb_a', rc=rc) + field_info_array=field_info_array, STgeom=is_local%wrap%NStateImp(compatm), name='FBMed_ocnalb_a', rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (maintask) then write(logunit,'(a)') trim(subname)//' initializing FB FBMed_ocnalb_a' end if call FB_init(is_local%wrap%FBMed_ocnalb_o, is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateImp(compocn), fieldnamelist=fldnames, name='FBMed_ocnalb_o', rc=rc) + field_info_array = field_info_array, STgeom=is_local%wrap%NStateImp(compocn), name='FBMed_ocnalb_o', rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (maintask) then write(logunit,'(a)') trim(subname)//' initializing FB FBMed_ocnalb_o' diff --git a/mediator/med_field_info_mod.F90 b/mediator/med_field_info_mod.F90 new file mode 100644 index 000000000..197f0a1b1 --- /dev/null +++ b/mediator/med_field_info_mod.F90 @@ -0,0 +1,225 @@ +module med_field_info_mod + + !----------------------------------------------------------------------------- + ! Defines a type and related operations for storing metadata about fields that can be + ! used to create an ESMF FieldBundle. + !----------------------------------------------------------------------------- + + use ESMF , only : ESMF_MAXSTR, ESMF_SUCCESS + use ESMF , only : ESMF_Field, ESMF_State, ESMF_AttributeGet, ESMF_StateGet + use med_utils_mod , only : ChkErr => med_utils_ChkErr + use shr_log_mod , only : shr_log_error + use wtracers_mod , only : wtracers_is_wtracer_field + + implicit none + private + + !----------------------------------------------- + ! Public methods + !----------------------------------------------- + + ! Create a single field + public :: med_field_info_create + + ! Create an array of field_info objects based on an array of names, where water tracers + ! are treated specially (being given an ungridded dimension) + public :: med_field_info_array_from_names_wtracers + + ! Create an array of field_info objects based on the fields in an ESMF State + public :: med_field_info_array_from_state + + !----------------------------------------------- + ! Types + !----------------------------------------------- + + type, public :: med_field_info_type + character(ESMF_MAXSTR) :: name + integer :: n_ungridded ! number of ungridded dimensions + + ! These arrays will be allocated to be of size ungridded_count + integer, allocatable :: ungridded_lbound(:) + integer, allocatable :: ungridded_ubound(:) + end type med_field_info_type + + character(len=*),parameter :: u_FILE_u = & + __FILE__ + +!================================================================================ +contains +!================================================================================ + + function med_field_info_create(name, ungridded_lbound, ungridded_ubound, rc) result(field_info) + ! Create a single field + + ! input/output variables + character(len=*), intent(in) :: name + + ! ungridded_lbound and ungridded_ubound must either both be present or both be absent; + ! if present, they must be the same size + integer, intent(in), optional :: ungridded_lbound(:) + integer, intent(in), optional :: ungridded_ubound(:) + + integer, intent(out) :: rc + type(med_field_info_type) :: field_info ! function result + + ! local variables + integer :: n_ungridded + character(len=*), parameter :: subname = '(med_field_info_create)' + ! ---------------------------------------------- + + rc = ESMF_SUCCESS + + if (present(ungridded_lbound) .neqv. present(ungridded_ubound)) then + call shr_log_error( & + subname//": ERROR: ungridded_lbound and ungridded_ubound must both be present or both absent.", & + line=__LINE__, file=u_FILE_u, rc=rc) + return + end if + + field_info%name = name + + if (present(ungridded_lbound)) then + n_ungridded = size(ungridded_lbound) + if (size(ungridded_ubound) /= n_ungridded) then + call shr_log_error( & + subname//": ERROR: ungridded_lbound and ungridded_ubound must have the same size.", & + line=__LINE__, file=u_FILE_u, rc=rc) + return + end if + field_info%n_ungridded = n_ungridded + allocate(field_info%ungridded_lbound(n_ungridded)) + allocate(field_info%ungridded_ubound(n_ungridded)) + field_info%ungridded_lbound = ungridded_lbound + field_info%ungridded_ubound = ungridded_ubound + else + field_info%n_ungridded = 0 + end if + + end function med_field_info_create + + !----------------------------------------------------------------------------- + + subroutine med_field_info_array_from_names_wtracers(field_names, field_info_array, rc) + ! Create an array of field_info objects based on an array of names, where water + ! tracers are treated specially (being given an ungridded dimension). + ! + ! It is assumed that fields generally have no ungridded dimensions. However, for + ! fields ending with the water tracer suffix, it is instead assumed that they have a + ! single ungridded dimension of size given by shr_wtracers_get_num_tracers. + ! + ! field_info_array is allocated here (and, since it has intent(out), it is + ! automatically deallocated if it is already allocated on entry to this subroutine) + + ! input/output variables + character(len=*), intent(in) :: field_names(:) + type(med_field_info_type), allocatable, intent(out) :: field_info_array(:) + integer, intent(out) :: rc + + ! local variables + integer :: i, n_fields + logical :: is_tracer + integer :: n_tracers + character(len=*), parameter :: subname = '(med_field_info_array_from_names_wtracers)' + ! ---------------------------------------------- + + rc = ESMF_SUCCESS + + n_fields = size(field_names) + allocate(field_info_array(n_fields)) + ! For now, hard-code n_tracers, since we haven't set up the tracer information; we'll + ! fix this in an upcoming set of changes + n_tracers = 0 + + do i = 1, n_fields + is_tracer = wtracers_is_wtracer_field(field_names(i)) + if (is_tracer) then + ! Field is a water tracer; assume a single ungridded dimension + field_info_array(i) = med_field_info_create( & + name=field_names(i), & + ungridded_lbound=[1], & + ungridded_ubound=[n_tracers], & + rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + else + ! Not a water tracer; assume no ungridded dimensions + field_info_array(i) = med_field_info_create( & + name=field_names(i), & + rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if + end do + + end subroutine med_field_info_array_from_names_wtracers + + !----------------------------------------------------------------------------- + + subroutine med_field_info_array_from_state(state, field_info_array, rc) + ! Create an array of field_info objects based on the Fields in an ESMF State + ! + ! field_info_array is allocated here (and, since it has intent(out), it is + ! automatically deallocated if it is already allocated on entry to this subroutine) + + ! input/output variables + type(ESMF_State), intent(in) :: state + type(med_field_info_type), allocatable, intent(out) :: field_info_array(:) + integer, intent(out) :: rc + + ! local variables + integer :: i, n_fields + character(ESMF_MAXSTR), allocatable :: field_names(:) + type(ESMF_Field) :: field + logical :: is_present + integer :: n_ungridded + integer, allocatable :: ungridded_lbound(:) + integer, allocatable :: ungridded_ubound(:) + character(len=*), parameter :: subname = '(med_field_info_array_from_state)' + ! ---------------------------------------------- + + rc = ESMF_SUCCESS + + call ESMF_StateGet(state, itemCount=n_fields, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + allocate(field_names(n_fields)) + allocate(field_info_array(n_fields)) + call ESMF_StateGet(state, itemNameList=field_names, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + do i = 1, n_fields + call ESMF_StateGet(state, itemName=trim(field_names(i)), field=field, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + call ESMF_AttributeGet(field, name="UngriddedUBound", convention="NUOPC", & + purpose="Instance", itemCount=n_ungridded, isPresent=is_present, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + if (.not. is_present) then + n_ungridded = 0 + end if + + if (n_ungridded == 0) then + field_info_array(i) = med_field_info_create( & + name=field_names(i), & + rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + else + allocate(ungridded_lbound(n_ungridded)) + allocate(ungridded_ubound(n_ungridded)) + call ESMF_AttributeGet(field, name="UngriddedLBound", convention="NUOPC", & + purpose="Instance", valueList=ungridded_lbound, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_AttributeGet(field, name="UngriddedUBound", convention="NUOPC", & + purpose="Instance", valueList=ungridded_ubound, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_info_array(i) = med_field_info_create( & + name=field_names(i), & + ungridded_lbound=ungridded_lbound, & + ungridded_ubound=ungridded_ubound, & + rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + deallocate(ungridded_lbound) + deallocate(ungridded_ubound) + end if + end do + + end subroutine med_field_info_array_from_state + +end module med_field_info_mod diff --git a/mediator/med_fraction_mod.F90 b/mediator/med_fraction_mod.F90 index 7f9cfb8ba..9d58a43d1 100644 --- a/mediator/med_fraction_mod.F90 +++ b/mediator/med_fraction_mod.F90 @@ -135,6 +135,8 @@ module med_fraction_mod use med_methods_mod , only : fldbun_reset => med_methods_FB_reset use med_map_mod , only : med_map_field use med_internalstate_mod , only : ncomps, samegrid_atmlnd + use med_field_info_mod , only : med_field_info_type + use med_field_info_mod , only : med_field_info_array_from_names_wtracers, med_field_info_array_from_state implicit none private @@ -189,6 +191,7 @@ subroutine med_fraction_init(gcomp, rc) type(InternalState) :: is_local type(ESMF_Field) :: field_src type(ESMF_Field) :: field_dst + type(med_field_info_type), allocatable :: field_info_array(:) real(R8), pointer :: frac(:) real(R8), pointer :: ofrac(:) real(R8), pointer :: aofrac(:) @@ -255,13 +258,18 @@ subroutine med_fraction_init(gcomp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return ! create FBFrac + call med_field_info_array_from_names_wtracers( & + field_names = fraclist(:,n1), & + field_info_array = field_info_array, & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return if (fieldCount == 0) then call fldbun_init(is_local%wrap%FBfrac(n1), is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateExp(n1), fieldNameList=fraclist(:,n1), & + field_info_array=field_info_array, STgeom=is_local%wrap%NStateExp(n1), & name='FBfrac'//trim(compname(n1)), rc=rc) else call fldbun_init(is_local%wrap%FBfrac(n1), is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateImp(n1), fieldNameList=fraclist(:,n1), & + field_info_array=field_info_array, STgeom=is_local%wrap%NStateImp(n1), & name='FBfrac'//trim(compname(n1)), rc=rc) end if if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -673,9 +681,14 @@ subroutine med_fraction_init(gcomp, rc) if (is_local%wrap%comp_present(compice) .and. is_local%wrap%comp_present(compocn)) then if (.not. med_map_RH_is_created(is_local%wrap%RH(compice,compocn,:),mapfcopy, rc=rc)) then if (.not. ESMF_FieldBundleIsCreated(is_local%wrap%FBImp(compice,compocn))) then + call med_field_info_array_from_state( & + state = is_local%wrap%NStateImp(compice), & + field_info_array = field_info_array, & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call fldbun_init(is_local%wrap%FBImp(compice,compocn), is_local%wrap%flds_scalar_name, & + field_info_array=field_info_array, & STgeom=is_local%wrap%NStateImp(compocn), & - STflds=is_local%wrap%NStateImp(compice), & name='FBImp'//trim(compname(compice))//'_'//trim(compname(compocn)), rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if @@ -687,9 +700,14 @@ subroutine med_fraction_init(gcomp, rc) end if if (.not. med_map_RH_is_created(is_local%wrap%RH(compocn,compice,:),mapfcopy, rc=rc)) then if (.not. ESMF_FieldBundleIsCreated(is_local%wrap%FBImp(compocn,compice))) then + call med_field_info_array_from_state( & + state = is_local%wrap%NStateImp(compocn), & + field_info_array = field_info_array, & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call fldbun_init(is_local%wrap%FBImp(compocn,compice), is_local%wrap%flds_scalar_name, & + field_info_array = field_info_array, & STgeom=is_local%wrap%NStateImp(compice), & - STflds=is_local%wrap%NStateImp(compocn), & name='FBImp'//trim(compname(compocn))//'_'//trim(compname(compice)), rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if diff --git a/mediator/med_methods_mod.F90 b/mediator/med_methods_mod.F90 index ac059bc7c..26dfa773b 100644 --- a/mediator/med_methods_mod.F90 +++ b/mediator/med_methods_mod.F90 @@ -15,6 +15,7 @@ module med_methods_mod use med_constants_mod , only : czero => med_constants_czero use med_constants_mod , only : spval_init => med_constants_spval_init use med_utils_mod , only : ChkErr => med_utils_ChkErr + use med_field_info_mod , only : med_field_info_type use shr_log_mod , only : shr_log_error implicit none private @@ -223,11 +224,14 @@ end subroutine med_methods_FB_init_pointer !----------------------------------------------------------------------------- - subroutine med_methods_FB_init(FBout, flds_scalar_name, fieldNameList, FBgeom, STgeom, FBflds, STflds, name, rc) + subroutine med_methods_FB_init(FBout, flds_scalar_name, field_info_array, FBgeom, STgeom, name, rc) ! ---------------------------------------------- - ! Create FBout from fieldNameList, FBflds, STflds, FBgeom or STgeom in that order or priority - ! Pass in FBgeom OR STgeom, get mesh from that object + ! Create FBout from field_info_array (see med_field_info_mod for some convenience + ! functions for creating a field_info array from field names or an ESMF State) + ! + ! Mesh is retrieved from either FBgeom or STgeom (one of those must be present, but + ! not both) ! ---------------------------------------------- use ESMF , only : ESMF_Field, ESMF_FieldBundle, ESMF_FieldBundleCreate, ESMF_FieldBundleGet @@ -238,27 +242,19 @@ subroutine med_methods_FB_init(FBout, flds_scalar_name, fieldNameList, FBgeom, S ! input/output variables type(ESMF_FieldBundle), intent(inout) :: FBout ! output field bundle character(len=*) , intent(in) :: flds_scalar_name ! name of scalar fields - character(len=*) , intent(in), optional :: fieldNameList(:) ! names of fields to use in output field bundle + type(med_field_info_type), intent(in) :: field_info_array(:) ! info on the fields to put in the output FieldBundle type(ESMF_FieldBundle), intent(in), optional :: FBgeom ! input field bundle geometry to use type(ESMF_State) , intent(in), optional :: STgeom ! input state geometry to use - type(ESMF_FieldBundle), intent(in), optional :: FBflds ! input field bundle fields - type(ESMF_State) , intent(in), optional :: STflds ! input state fields character(len=*) , intent(in), optional :: name ! name to use for output field bundle integer , intent(out) :: rc ! local variables - integer :: n,n1 + integer :: n integer :: fieldCount,fieldCountgeom character(ESMF_MAXSTR) :: lname type(ESMF_Field) :: field,lfield type(ESMF_Mesh) :: lmesh type(ESMF_MeshLoc) :: meshloc - integer :: ungriddedCount - integer :: ungriddedCount_in - integer, allocatable :: ungriddedLBound(:) - integer, allocatable :: ungriddedUBound(:) - logical :: isPresent - character(ESMF_MAXSTR), allocatable :: lfieldNameList(:) character(len=*), parameter :: subname='(med_methods_FB_init)' ! ---------------------------------------------- @@ -278,11 +274,6 @@ subroutine med_methods_FB_init(FBout, flds_scalar_name, fieldNameList, FBgeom, S ! verify that geom argument has a field !--------------------------------- - if (present(fieldNameList) .and. present(FBflds) .and. present(STflds)) then - call shr_log_error(trim(subname)//": ERROR only fieldNameList, FBflds, or STflds can be an argument", rc=rc) - return - endif - if (present(FBgeom) .and. present(STgeom)) then call shr_log_error(trim(subname)//": ERROR FBgeom and STgeom cannot both be arguments", rc=rc) return @@ -305,70 +296,12 @@ subroutine med_methods_FB_init(FBout, flds_scalar_name, fieldNameList, FBgeom, S endif !--------------------------------- - ! determine the names of fields that will be in FBout + ! Determine number of fields + ! + ! Note that scalars and blank fields will be removed later !--------------------------------- - if (present(fieldNameList)) then - fieldcount = size(fieldNameList) - allocate(lfieldNameList(fieldcount)) - lfieldNameList = fieldNameList - if (dbug_flag > 5) then - call ESMF_LogWrite(trim(subname)//":"//trim(lname)//" fieldNameList from argument", ESMF_LOGMSG_INFO) - end if - elseif (present(FBflds)) then - call ESMF_FieldBundleGet(FBflds, fieldCount=fieldCount, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - allocate(lfieldNameList(fieldCount)) - call ESMF_FieldBundleGet(FBflds, fieldNameList=lfieldNameList, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - if (dbug_flag > 5) then - call ESMF_LogWrite(trim(subname)//":"//trim(lname)//" fieldNameList from FBflds", ESMF_LOGMSG_INFO) - end if - elseif (present(STflds)) then - call ESMF_StateGet(STflds, itemCount=fieldCount, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - allocate(lfieldNameList(fieldCount)) - call ESMF_StateGet(STflds, itemNameList=lfieldNameList, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - if (dbug_flag > 5) then - call ESMF_LogWrite(trim(subname)//":"//trim(lname)//" fieldNameList from STflds", ESMF_LOGMSG_INFO) - end if - elseif (present(FBgeom)) then - call ESMF_FieldBundleGet(FBgeom, fieldCount=fieldCount, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - allocate(lfieldNameList(fieldCount)) - call ESMF_FieldBundleGet(FBgeom, fieldNameList=lfieldNameList, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - if (dbug_flag > 5) then - call ESMF_LogWrite(trim(subname)//":"//trim(lname)//" fieldNameList from FBgeom", ESMF_LOGMSG_INFO) - end if - elseif (present(STgeom)) then - call ESMF_StateGet(STgeom, itemCount=fieldCount, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - allocate(lfieldNameList(fieldCount)) - call ESMF_StateGet(STgeom, itemNameList=lfieldNameList, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - if (dbug_flag > 5) then - call ESMF_LogWrite(trim(subname)//":"//trim(lname)//" fieldNameList from STgeom", ESMF_LOGMSG_INFO) - end if - else - call shr_log_error(trim(subname)//": ERROR fieldNameList, FBflds, STflds, FBgeom, or STgeom must be passed", rc=rc) - return - endif - - !--------------------------------- - ! remove scalar field and blank fields from field bundle - !--------------------------------- - - do n = 1, fieldCount - if (trim(lfieldnamelist(n)) == trim(flds_scalar_name) .or. & - trim(lfieldnamelist(n)) == '') then - do n1 = n, fieldCount-1 - lfieldnamelist(n1) = lfieldnamelist(n1+1) - enddo - fieldCount = fieldCount - 1 - endif - enddo ! n + fieldCount = size(field_info_array) !--------------------------------- ! create the mesh(lmesh) that will be used for FBout fields @@ -426,61 +359,31 @@ subroutine med_methods_FB_init(FBout, flds_scalar_name, fieldNameList, FBgeom, S ! Now loop over all the fields in the field name list do n = 1, fieldCount - ! Note that input fields come from ONE of FBFlds, STflds, or fieldNamelist input argument - if (present(FBFlds) .or. present(STflds)) then - - ! ungridded dimensions might be present in the input states or field bundles - if (present(FBflds)) then - call ESMF_FieldBundleGet(FBflds, fieldName=lfieldnamelist(n), field=lfield, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - elseif (present(STflds)) then - call ESMF_StateGet(STflds, itemName=trim(lfieldnamelist(n)), field=lfield, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - end if + ! Don't add scalar field or blank fields to field bundle + if (field_info_array(n)%name == flds_scalar_name .or. & + len_trim(field_info_array(n)%name) == 0) then + cycle + end if - ! Determine ungridded lower and upper bounds for lfield - call ESMF_AttributeGet(lfield, name="UngriddedUBound", convention="NUOPC", & - purpose="Instance", itemCount=ungriddedCount_in, isPresent=isPresent, rc=rc) + ! Create the field + if (field_info_array(n)%n_ungridded > 0) then + field = ESMF_FieldCreate(lmesh, ESMF_TYPEKIND_R8, meshloc=meshloc, & + name=field_info_array(n)%name, & + ungriddedLbound=field_info_array(n)%ungridded_lbound, & + ungriddedUbound=field_info_array(n)%ungridded_ubound, & + gridToFieldMap=[field_info_array(n)%n_ungridded+1], & + rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - if (isPresent) then - ungriddedCount = ungriddedCount_in - else - ungriddedCount=0 ! initialize in case it was not set - end if - - ! Create the field on a lmesh - if (ungriddedCount > 0) then - ! ungridded dimensions in field - allocate(ungriddedLBound(ungriddedCount), ungriddedUBound(ungriddedCount)) - call ESMF_AttributeGet(lfield, name="UngriddedLBound", convention="NUOPC", & - purpose="Instance", valueList=ungriddedLBound, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_AttributeGet(lfield, name="UngriddedUBound", convention="NUOPC", & - purpose="Instance", valueList=ungriddedUBound, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - field = ESMF_FieldCreate(lmesh, ESMF_TYPEKIND_R8, meshloc=meshloc, name=lfieldNameList(n), & - ungriddedLbound=ungriddedLbound, ungriddedUbound=ungriddedUbound, gridToFieldMap=(/2/)) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - deallocate( ungriddedLbound, ungriddedUbound) - else - ! No ungridded dimensions in field - field = ESMF_FieldCreate(lmesh, ESMF_TYPEKIND_R8, meshloc=meshloc, name=lfieldNameList(n), rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - end if - - else if (present(fieldNameList)) then - - ! Assume no ungridded dimensions if just the field name list is give - field = ESMF_FieldCreate(lmesh, ESMF_TYPEKIND_R8, meshloc=meshloc, name=lfieldNameList(n), rc=rc) + else + field = ESMF_FieldCreate(lmesh, ESMF_TYPEKIND_R8, meshloc=meshloc, & + name=field_info_array(n)%name, & + rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - end if - ! Add the created field bundle FBout + ! Add the created field to field bundle FBout if (dbug_flag > 1) then - call ESMF_LogWrite(trim(subname)//":"//trim(lname)//" adding field "//trim(lfieldNameList(n)), & + call ESMF_LogWrite(trim(subname)//":"//trim(lname)//" adding field "//trim(field_info_array(n)%name), & ESMF_LOGMSG_INFO) end if call ESMF_FieldBundleAdd(FBout, (/field/), rc=rc) @@ -489,8 +392,6 @@ subroutine med_methods_FB_init(FBout, flds_scalar_name, fieldNameList, FBgeom, S enddo ! fieldCount endif ! fieldcountgeom - deallocate(lfieldNameList) - call med_methods_FB_reset(FBout, value=spval_init, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return diff --git a/mediator/med_phases_aofluxes_mod.F90 b/mediator/med_phases_aofluxes_mod.F90 index 9417e2528..c0d0192b5 100644 --- a/mediator/med_phases_aofluxes_mod.F90 +++ b/mediator/med_phases_aofluxes_mod.F90 @@ -31,6 +31,8 @@ module med_phases_aofluxes_mod use med_constants_mod , only : dbug_flag => med_constants_dbug_flag use med_utils_mod , only : memcheck => med_memcheck use med_utils_mod , only : chkerr => med_utils_chkerr + use med_field_info_mod , only : med_field_info_type + use med_field_info_mod , only : med_field_info_array_from_names_wtracers, med_field_info_array_from_state use perf_mod , only : t_startf, t_stopf #ifndef CESMCOUPLED use ufs_const_mod , only : rearth => SHR_CONST_REARTH @@ -173,6 +175,7 @@ subroutine med_phases_aofluxes_init_fldbuns(gcomp, rc) integer :: fieldcount type(med_fldList_type), pointer :: fldListMed_aoflux type(InternalState) :: is_local + type(med_field_info_type), allocatable :: field_info_array(:) character(len=*),parameter :: subname=' (med_phases_aofluxes_init_fldbuns) ' !--------------------------------------- @@ -190,9 +193,16 @@ subroutine med_phases_aofluxes_init_fldbuns(gcomp, rc) call med_fldList_getfldnames(fldListMed_aoflux%fields, fldnames_aof_out, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + ! Create field_info_array for FBMed_aoflux_a and FBMed_aoflux_o + call med_field_info_array_from_names_wtracers( & + field_names = fldnames_aof_out, & + field_info_array = field_info_array, & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + ! Initialize FBMed_aoflux_a call FB_init(is_local%wrap%FBMed_aoflux_a, is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateImp(compatm), fieldnamelist=fldnames_aof_out, name='FBMed_aoflux_a', rc=rc) + field_info_array=field_info_array, STgeom=is_local%wrap%NStateImp(compatm), name='FBMed_aoflux_a', rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (maintask) then write(logunit,*) @@ -201,7 +211,7 @@ subroutine med_phases_aofluxes_init_fldbuns(gcomp, rc) ! Initialize FBMed_aoflux_o call FB_init(is_local%wrap%FBMed_aoflux_o, is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateImp(compocn), fieldnamelist=fldnames_aof_out, name='FBMed_aoflux_o', rc=rc) + field_info_array=field_info_array, STgeom=is_local%wrap%NStateImp(compocn), name='FBMed_aoflux_o', rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (maintask) then write(logunit,'(a)') trim(subname)//' initialized FB FBMed_aoflux_o' @@ -219,8 +229,13 @@ subroutine med_phases_aofluxes_init_fldbuns(gcomp, rc) if (maintask) then write(logunit,'(a)') trim(subname)//' creating field bundle FBImp(compatm,compocn)' end if + call med_field_info_array_from_state( & + state = is_local%wrap%NStateImp(compatm), & + field_info_array = field_info_array, & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call FB_init(is_local%wrap%FBImp(compatm,compocn), is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateImp(compocn), STflds=is_local%wrap%NStateImp(compatm), & + field_info_array=field_info_array, STgeom=is_local%wrap%NStateImp(compocn), & name='FBImp'//trim(compname(compatm))//'_'//trim(compname(compocn)), rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if @@ -234,8 +249,13 @@ subroutine med_phases_aofluxes_init_fldbuns(gcomp, rc) if (maintask) then write(logunit,'(a)') trim(subname)//' creating field bundle FBImp(compocn,compatm)' end if + call med_field_info_array_from_state( & + state = is_local%wrap%NStateImp(compocn), & + field_info_array = field_info_array, & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call FB_init(is_local%wrap%FBImp(compocn,compatm), is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateImp(compatm), STflds=is_local%wrap%NStateImp(compocn), & + field_info_array = field_info_array, STgeom=is_local%wrap%NStateImp(compatm), & name='FBImp'//trim(compname(compocn))//'_'//trim(compname(compatm)), rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if @@ -606,6 +626,7 @@ subroutine med_aofluxes_init_agrid(gcomp, aoflux_in, aoflux_out, rc) integer :: maptype type(ESMF_Field) :: lfield type(ESMF_Mesh) :: lmesh + type(med_field_info_type), allocatable :: field_info_array(:) real(R8), pointer :: garea(:) => null() type(ESMF_CoordSys_Flag) :: coordSys character(len=*),parameter :: subname=' (med_aofluxes_init_atmgrid) ' @@ -623,8 +644,13 @@ subroutine med_aofluxes_init_agrid(gcomp, aoflux_in, aoflux_out, rc) allocate(fldnames_ocn_in(4)) fldnames_ocn_in = (/'So_omask','So_t ','So_u ','So_v '/) + call med_field_info_array_from_names_wtracers( & + field_names = fldnames_ocn_in, & + field_info_array = field_info_array, & + rc = rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return call FB_init(FBocn_a, is_local%wrap%flds_scalar_name, & - FBgeom=is_local%wrap%FBImp(compatm,compatm), fieldnamelist=fldnames_ocn_in, name='FBocn_a', rc=rc) + field_info_array=field_info_array, FBgeom=is_local%wrap%FBImp(compatm,compatm), name='FBocn_a', rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return call set_aoflux_in_pointers(is_local%wrap%FBImp(compatm,compatm), FBocn_a, aoflux_in, lsize, rc=rc) diff --git a/mediator/med_phases_cdeps_mod.F90 b/mediator/med_phases_cdeps_mod.F90 index 4f37b6f79..9fe869bb2 100644 --- a/mediator/med_phases_cdeps_mod.F90 +++ b/mediator/med_phases_cdeps_mod.F90 @@ -20,7 +20,6 @@ module med_phases_cdeps_mod use med_methods_mod , only: FB_FldChk => med_methods_FB_FldChk use med_methods_mod , only: FB_getFieldN => med_methods_FB_getFieldN use med_methods_mod , only: FB_getNumflds => med_methods_FB_getNumflds - use med_methods_mod , only: FB_init => med_methods_FB_Init use med_methods_mod , only: FB_diagnose => med_methods_FB_diagnose use med_methods_mod , only: FB_write => med_methods_FB_write use med_methods_mod , only: FB_GetFldPtr => med_methods_FB_GetFldPtr diff --git a/mediator/med_phases_history_mod.F90 b/mediator/med_phases_history_mod.F90 index fd533d70c..d0b049580 100644 --- a/mediator/med_phases_history_mod.F90 +++ b/mediator/med_phases_history_mod.F90 @@ -21,6 +21,7 @@ module med_phases_history_mod use med_internalstate_mod , only : ncomps, compname use med_internalstate_mod , only : InternalState, maintask, logunit use med_io_mod , only : med_io_write, med_io_wopen, med_io_enddef, med_io_close + use med_field_info_mod , only : med_field_info_type, med_field_info_array_from_state use perf_mod , only : t_startf, t_stopf use pio , only : file_desc_t use shr_log_mod , only : shr_log_error @@ -843,6 +844,7 @@ subroutine med_phases_history_write_comp_avg(gcomp, compid, avgfile, rc) ! local variables type(InternalState) :: is_local + type(med_field_info_type), allocatable :: field_info_array(:) character(CL) :: cvalue ! attribute string character(CL) :: hist_option ! freq_option setting (ndays, nsteps, etc) integer :: hist_n ! freq_n setting relative to freq_option @@ -907,8 +909,13 @@ subroutine med_phases_history_write_comp_avg(gcomp, compid, avgfile, rc) scalar_name = trim(is_local%wrap%flds_scalar_name) if ( ESMF_FieldBundleIsCreated(is_local%wrap%FBimp(compid,compid)) .and. .not. & ESMF_FieldBundleIsCreated(avgfile%FBaccum_import)) then + call med_field_info_array_from_state( & + state = is_local%wrap%NStateImp(compid), & + field_info_array = field_info_array, & + rc = rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return call med_methods_FB_init(avgfile%FBaccum_import, scalar_name, & - STgeom=is_local%wrap%NStateImp(compid), STflds=is_local%wrap%NStateImp(compid), rc=rc) + field_info_array=field_info_array, STgeom=is_local%wrap%NStateImp(compid), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return call med_methods_FB_reset(avgfile%FBaccum_import, czero, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return @@ -916,8 +923,13 @@ subroutine med_phases_history_write_comp_avg(gcomp, compid, avgfile, rc) end if if ( ESMF_FieldBundleIsCreated(is_local%wrap%FBexp(compid)) .and. .not. & ESMF_FieldBundleIsCreated(avgfile%FBaccum_export)) then + call med_field_info_array_from_state( & + state = is_local%wrap%NStateExp(compid), & + field_info_array = field_info_array, & + rc = rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return call med_methods_FB_init(avgfile%FBaccum_export, scalar_name, & - STgeom=is_local%wrap%NStateExp(compid), STflds=is_local%wrap%NStateExp(compid), rc=rc) + field_info_array=field_info_array, STgeom=is_local%wrap%NStateExp(compid), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return call med_methods_FB_reset(avgfile%FBaccum_export, czero, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return @@ -1050,6 +1062,7 @@ subroutine med_phases_history_write_comp_aux(gcomp, compid, auxcomp, rc) ! local variables type(InternalState) :: is_local + type(med_field_info_type), allocatable :: field_info_array(:) type(ESMF_VM) :: vm type(ESMF_Calendar) :: calendar ! calendar type logical :: isPresent ! is attribute present @@ -1179,8 +1192,13 @@ subroutine med_phases_history_write_comp_aux(gcomp, compid, auxcomp, rc) call ESMF_LogWrite(trim(subname)// ": initializing FBaccum(compid)", ESMF_LOGMSG_INFO) if ( ESMF_FieldBundleIsCreated(is_local%wrap%FBImp(compid,compid)) .and. .not. & ESMF_FieldBundleIsCreated(auxcomp%files(nfcnt)%FBaccum)) then + call med_field_info_array_from_state( & + state = is_local%wrap%NStateImp(compid), & + field_info_array = field_info_array, & + rc = rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return call med_methods_FB_init(auxcomp%files(nfcnt)%FBaccum, is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateImp(compid), STflds=is_local%wrap%NStateImp(compid), & + field_info_array=field_info_array, STgeom=is_local%wrap%NStateImp(compid), & rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return call med_methods_FB_reset(auxcomp%files(nfcnt)%FBaccum, czero, rc=rc) diff --git a/mediator/med_phases_prep_glc_mod.F90 b/mediator/med_phases_prep_glc_mod.F90 index e0e29089a..e218db9d9 100644 --- a/mediator/med_phases_prep_glc_mod.F90 +++ b/mediator/med_phases_prep_glc_mod.F90 @@ -38,6 +38,7 @@ module med_phases_prep_glc_mod use med_methods_mod , only : field_getdata2d => med_methods_Field_getdata2d use med_methods_mod , only : field_getdata1d => med_methods_Field_getdata1d use med_methods_mod , only : fldchk => med_methods_FB_FldChk + use med_field_info_mod , only : med_field_info_type, med_field_info_array_from_state use med_utils_mod , only : chkerr => med_utils_ChkErr use nuopc_shr_methods , only : alarmInit use glc_elevclass_mod , only : glc_get_num_elevation_classes @@ -131,6 +132,7 @@ subroutine med_phases_prep_glc_init(gcomp, rc) ! local variables type(InternalState) :: is_local + type(med_field_info_type), allocatable :: field_info_array(:) integer :: n,ns,nf type(ESMF_Mesh) :: mesh_l type(ESMF_Mesh) :: mesh_o @@ -286,9 +288,13 @@ subroutine med_phases_prep_glc_init(gcomp, rc) ! Create route handle if it has not been created - this will be needed to map the fractions if (.not. med_map_RH_is_created(is_local%wrap%RH(compglc(ns),complnd,:),mapconsd, rc=rc)) then if (.not. ESMF_FieldBundleIsCreated(is_local%wrap%FBImp(compglc(ns),complnd))) then + call med_field_info_array_from_state( & + state = is_local%wrap%NStateImp(compglc(ns)), & + field_info_array = field_info_array, & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call fldbun_init(is_local%wrap%FBImp(compglc(ns),complnd), is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateImp(complnd), & - STflds=is_local%wrap%NStateImp(compglc(ns)), & + field_info_array=field_info_array, STgeom=is_local%wrap%NStateImp(complnd), & name='FBImp'//trim(compname(compglc(ns)))//'_'//trim(compname(complnd)), rc=rc) end if call med_map_routehandles_init( compglc(ns), complnd, & diff --git a/mediator/med_phases_prep_ocn_mod.F90 b/mediator/med_phases_prep_ocn_mod.F90 index e30c4ada5..f4f9bd3b0 100644 --- a/mediator/med_phases_prep_ocn_mod.F90 +++ b/mediator/med_phases_prep_ocn_mod.F90 @@ -20,6 +20,7 @@ module med_phases_prep_ocn_mod use med_methods_mod , only : FB_copy => med_methods_FB_copy use med_methods_mod , only : FB_reset => med_methods_FB_reset use med_methods_mod , only : FB_check_for_nans => med_methods_FB_check_for_nans + use med_field_info_mod , only : med_field_info_type, med_field_info_array_from_state use esmFlds , only : med_fldList_GetfldListTo, med_fldlist_type use med_internalstate_mod , only : compocn, compatm, compice, coupling_mode use perf_mod , only : t_startf, t_stopf @@ -51,6 +52,7 @@ subroutine med_phases_prep_ocn_init(gcomp, rc) ! local variables type(InternalState) :: is_local + type(med_field_info_type), allocatable :: field_info_array(:) character(len=*),parameter :: subname=' (med_phases_prep_ocn_init) ' !--------------------------------------- @@ -64,8 +66,13 @@ subroutine med_phases_prep_ocn_init(gcomp, rc) if (maintask) then write(logunit,'(a)') trim(subname)//' initializing ocean export accumulation FB for ' end if + call med_field_info_array_from_state( & + state = is_local%wrap%NStateExp(compocn), & + field_info_array = field_info_array, & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call FB_init(is_local%wrap%FBExpAccumOcn, is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateExp(compocn), STflds=is_local%wrap%NStateExp(compocn), & + field_info_array=field_info_array, STgeom=is_local%wrap%NStateExp(compocn), & name='FBExpAccumOcn', rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call FB_reset(is_local%wrap%FBExpAccumOcn, value=czero, rc=rc) diff --git a/mediator/med_phases_prep_wav_mod.F90 b/mediator/med_phases_prep_wav_mod.F90 index 1cfd158be..f732f4dc6 100644 --- a/mediator/med_phases_prep_wav_mod.F90 +++ b/mediator/med_phases_prep_wav_mod.F90 @@ -18,6 +18,7 @@ module med_phases_prep_wav_mod use med_methods_mod , only : FB_copy => med_methods_FB_copy use med_methods_mod , only : FB_reset => med_methods_FB_reset use med_methods_mod , only : FB_check_for_nans => med_methods_FB_check_for_nans + use med_field_info_mod , only : med_field_info_type, med_field_info_array_from_state use esmFlds , only : med_fldList_GetfldListTo use med_internalstate_mod , only : compatm, compwav use perf_mod , only : t_startf, t_stopf @@ -47,6 +48,7 @@ subroutine med_phases_prep_wav_init(gcomp, rc) ! local variables type(InternalState) :: is_local + type(med_field_info_type), allocatable :: field_info_array(:) character(len=*),parameter :: subname=' (med_phases_prep_wav_init) ' !--------------------------------------- @@ -60,8 +62,13 @@ subroutine med_phases_prep_wav_init(gcomp, rc) if (maintask) then write(logunit,'(a)') trim(subname)//' initializing wave export accumulation FB for ' end if + call med_field_info_array_from_state( & + state = is_local%wrap%NStateExp(compwav), & + field_info_array = field_info_array, & + rc = rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call FB_Init(is_local%wrap%FBExpAccumWav, is_local%wrap%flds_scalar_name, & - STgeom=is_local%wrap%NStateExp(compwav), STflds=is_local%wrap%NStateExp(compwav), & + field_info_array = field_info_array, STgeom=is_local%wrap%NStateExp(compwav), & name='FBExpAccumWav', rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call FB_reset(is_local%wrap%FBExpAccumWav, value=czero, rc=rc) diff --git a/ufs/CMakeLists.txt b/ufs/CMakeLists.txt index bb047dabb..19b34b5ae 100644 --- a/ufs/CMakeLists.txt +++ b/ufs/CMakeLists.txt @@ -1,6 +1,6 @@ project(CMEPS_share Fortran) include(ExternalProject) -add_library(cmeps_share flux_atmocn_mod.F90 glc_elevclass_mod.F90 perf_mod.F90 ufs_const_mod.F90 ufs_kind_mod.F90) +add_library(cmeps_share flux_atmocn_mod.F90 glc_elevclass_mod.F90 perf_mod.F90 ufs_const_mod.F90 ufs_kind_mod.F90 wtracers_mod.F90) target_include_directories (cmeps_share PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${ESMF_F90COMPILEPATHS} ${PIO_Fortran_INCLUDE_DIRS}) diff --git a/ufs/wtracers_mod.F90 b/ufs/wtracers_mod.F90 new file mode 100644 index 000000000..17d2f3014 --- /dev/null +++ b/ufs/wtracers_mod.F90 @@ -0,0 +1,34 @@ +module wtracers_mod + + !----------------------------------------------------------------------------- + ! This module provides stub implementations for the shr_wtracers_mod code for when we + ! do not have access to the CESM_share library. + ! + ! See also the version of wtracers_mod in the cesm directory for when we have access to + ! the CESM_share library. + !----------------------------------------------------------------------------- + + implicit none + private + + public :: wtracers_is_wtracer_field ! return true if the given field name is a water tracer field + +contains + + !----------------------------------------------------------------------- + function wtracers_is_wtracer_field(fieldname) + ! + ! !DESCRIPTION: + ! Return true if the given field name is a water tracer field + ! + ! In this stub implementation, we always return false, since water tracers are not + ! implemented here. + ! + ! !ARGUMENTS + character(len=*), intent(in) :: fieldname + logical :: wtracers_is_wtracer_field + !----------------------------------------------------------------------- + wtracers_is_wtracer_field = .false. + end function wtracers_is_wtracer_field + +end module wtracers_mod