From 1921680853d50cf51760a30fedfb67353ba272f4 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 5 Dec 2025 13:17:32 -0700 Subject: [PATCH 01/10] Remove some unused behavior from med_methods_FB_init --- mediator/med_methods_mod.F90 | 56 +++++++------------------------ mediator/med_phases_cdeps_mod.F90 | 1 - 2 files changed, 12 insertions(+), 45 deletions(-) diff --git a/mediator/med_methods_mod.F90 b/mediator/med_methods_mod.F90 index ac059bc7c..613ed0477 100644 --- a/mediator/med_methods_mod.F90 +++ b/mediator/med_methods_mod.F90 @@ -223,11 +223,12 @@ 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, fieldNameList, FBgeom, STgeom, STflds, 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 fieldNameList or STflds (one of those must be present, but not both) + ! + ! 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 @@ -241,7 +242,6 @@ subroutine med_methods_FB_init(FBout, flds_scalar_name, fieldNameList, FBgeom, S character(len=*) , intent(in), optional :: fieldNameList(:) ! names of fields to use in output field bundle 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 @@ -278,8 +278,8 @@ 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) + if (present(fieldNameList) .and. present(STflds)) then + call shr_log_error(trim(subname)//": ERROR only one of fieldNameList or STflds can be an argument", rc=rc) return endif @@ -315,15 +315,6 @@ subroutine med_methods_FB_init(FBout, flds_scalar_name, fieldNameList, FBgeom, S 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 @@ -333,26 +324,8 @@ subroutine med_methods_FB_init(FBout, flds_scalar_name, fieldNameList, FBgeom, S 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) + call shr_log_error(trim(subname)//": ERROR fieldNameList or STflds must be passed", rc=rc) return endif @@ -426,17 +399,12 @@ 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 + ! Note that input fields come from ONE of STflds or fieldNamelist input argument + if (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 + ! ungridded dimensions might be present in the input states + call ESMF_StateGet(STflds, itemName=trim(lfieldnamelist(n)), field=lfield, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return ! Determine ungridded lower and upper bounds for lfield call ESMF_AttributeGet(lfield, name="UngriddedUBound", convention="NUOPC", & 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 From b1b8d7b4740860bfb68a4ece1036d08cbb548f46 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 23 Dec 2025 14:59:53 -0700 Subject: [PATCH 02/10] Refactor med_methods_FB_init to allow handling of water tracer fields Rather than having med_methods_FB_init accept one of fieldNameList or STflds, now it accepts an array of med_field_info_type objects. med_field_info_type is defined in a new module that also includes some creation methods, making calls to med_methods_FB_init a two-step process: first create field_info_array, then call med_methods_FB_init with this field_info_array. A key new feature is that the creation of a field_info_array from field_names will assume a single ungridded dimension with size given by shr_wtracers_get_num_tracers for any field with the water tracer suffix. This was the main motivation for the refactor here. Some specific notes about the changes in this commit: - Behavior change: if there are only scalar or blank fields, we do some unnecessary work now (retrieving the mesh that we won't end up ever using) - I think I got the gridToFieldMap right: before it was hard-coded to 2, but I think that was only right for a single ungridded dimension; here I'm generalizing that for multiple ungridded dimensions --- mediator/med.F90 | 22 ++- mediator/med_field_info_mod.F90 | 220 +++++++++++++++++++++++++++ mediator/med_fraction_mod.F90 | 26 +++- mediator/med_methods_mod.F90 | 129 ++++------------ mediator/med_phases_aofluxes_mod.F90 | 36 ++++- mediator/med_phases_history_mod.F90 | 24 ++- mediator/med_phases_prep_glc_mod.F90 | 10 +- mediator/med_phases_prep_ocn_mod.F90 | 9 +- mediator/med_phases_prep_wav_mod.F90 | 9 +- 9 files changed, 367 insertions(+), 118 deletions(-) create mode 100644 mediator/med_field_info_mod.F90 diff --git a/mediator/med.F90 b/mediator/med.F90 index d7e0d20f5..1f3507b89 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_ungridded, 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_ungridded( & + 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..0955b3989 --- /dev/null +++ b/mediator/med_field_info_mod.F90 @@ -0,0 +1,220 @@ +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 shr_string_mod, only : shr_string_withoutSuffix + use shr_wtracers_mod, only : WTRACERS_SUFFIX, shr_wtracers_get_num_tracers + + implicit none + private + + !----------------------------------------------- + ! Public methods + !----------------------------------------------- + + public :: med_field_info_create ! Create a single field + public :: med_field_info_array_from_names_wtracers_ungridded ! Create an array of field_info objects based on an array of names, where water tracers are given an ungridded dimension + public :: med_field_info_array_from_state ! Create an array of field_info objects based on the fields in an ESMF 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_ungridded(field_names, field_info_array, rc) + ! Create an array of field_info objects based on an array of names, where water + ! tracers are 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. + + ! 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 + integer :: localrc + character(len=*), parameter :: subname = '(med_field_info_array_from_names_wtracers_ungridded)' + ! ---------------------------------------------- + + rc = ESMF_SUCCESS + + n_fields = size(field_names) + allocate(field_info_array(n_fields)) + n_tracers = shr_wtracers_get_num_tracers() + + do i = 1, n_fields + call shr_string_withoutSuffix( & + in_str = field_names(i), & + suffix = WTRACERS_SUFFIX, & + has_suffix = is_tracer, & + rc = localrc) + if (localrc /= 0) then + call shr_log_error(subname//": ERROR in shr_string_withoutSuffix", rc=rc) + return + end if + + 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_ungridded + + 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 + + ! 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..d4c8968ba 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_ungridded, 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_ungridded( & + 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 613ed0477..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,12 +224,14 @@ end subroutine med_methods_FB_init_pointer !----------------------------------------------------------------------------- - subroutine med_methods_FB_init(FBout, flds_scalar_name, fieldNameList, FBgeom, STgeom, STflds, name, rc) + subroutine med_methods_FB_init(FBout, flds_scalar_name, field_info_array, FBgeom, STgeom, name, rc) ! ---------------------------------------------- - ! Create FBout from fieldNameList or STflds (one of those must be present, but not both) + ! 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) + ! 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 @@ -239,26 +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_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(STflds)) then - call shr_log_error(trim(subname)//": ERROR only one of fieldNameList 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,43 +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(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 - else - call shr_log_error(trim(subname)//": ERROR fieldNameList or STflds 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 @@ -399,56 +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 STflds or fieldNamelist input argument - if (present(STflds)) then - - ! ungridded dimensions might be present in the input states - call ESMF_StateGet(STflds, itemName=trim(lfieldnamelist(n)), field=lfield, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return + ! 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) @@ -457,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..f4151c5be 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_ungridded, 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_ungridded( & + 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_ungridded( & + 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_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) From a39d47db5cef55490dd7e786ce884df917c4eab5 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 23 Dec 2025 18:15:49 -0700 Subject: [PATCH 03/10] For now, hard-code n_tracers = 0 We haven't set that up here; we'll fix this in an upcoming set of changes. --- mediator/med_field_info_mod.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mediator/med_field_info_mod.F90 b/mediator/med_field_info_mod.F90 index 0955b3989..3856fa93b 100644 --- a/mediator/med_field_info_mod.F90 +++ b/mediator/med_field_info_mod.F90 @@ -10,7 +10,7 @@ module med_field_info_mod use med_utils_mod, only : ChkErr => med_utils_ChkErr use shr_log_mod, only : shr_log_error use shr_string_mod, only : shr_string_withoutSuffix - use shr_wtracers_mod, only : WTRACERS_SUFFIX, shr_wtracers_get_num_tracers + use shr_wtracers_mod, only : WTRACERS_SUFFIX implicit none private @@ -119,7 +119,9 @@ subroutine med_field_info_array_from_names_wtracers_ungridded(field_names, field n_fields = size(field_names) allocate(field_info_array(n_fields)) - n_tracers = shr_wtracers_get_num_tracers() + ! 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 call shr_string_withoutSuffix( & From e9dc860e39c631aa9b32881b1dc09b096b9a2cfd Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 30 Dec 2025 14:56:49 -0700 Subject: [PATCH 04/10] Add new file to CMakeLists.txt --- mediator/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) 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 From 889368bf8a24a396e6c65a1a65e02ad70190db8f Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 30 Dec 2025 15:03:15 -0700 Subject: [PATCH 05/10] Minor cleanup suggested in review --- mediator/med_field_info_mod.F90 | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/mediator/med_field_info_mod.F90 b/mediator/med_field_info_mod.F90 index 3856fa93b..be8a132bc 100644 --- a/mediator/med_field_info_mod.F90 +++ b/mediator/med_field_info_mod.F90 @@ -5,11 +5,11 @@ module med_field_info_mod ! 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 shr_string_mod, only : shr_string_withoutSuffix + 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 shr_string_mod , only : shr_string_withoutSuffix use shr_wtracers_mod, only : WTRACERS_SUFFIX implicit none @@ -19,9 +19,15 @@ module med_field_info_mod ! Public methods !----------------------------------------------- - public :: med_field_info_create ! Create a single field - public :: med_field_info_array_from_names_wtracers_ungridded ! Create an array of field_info objects based on an array of names, where water tracers are given an ungridded dimension - public :: med_field_info_array_from_state ! Create an array of field_info objects based on the fields in an ESMF State + ! 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 given an ungridded dimension + public :: med_field_info_array_from_names_wtracers_ungridded + + ! Create an array of field_info objects based on the fields in an ESMF State + public :: med_field_info_array_from_state !----------------------------------------------- ! Types @@ -101,6 +107,8 @@ subroutine med_field_info_array_from_names_wtracers_ungridded(field_names, field ! 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 ! input/output variables character(len=*), intent(in) :: field_names(:) @@ -153,8 +161,12 @@ subroutine med_field_info_array_from_names_wtracers_ungridded(field_names, field end subroutine med_field_info_array_from_names_wtracers_ungridded + !----------------------------------------------------------------------------- + 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 ! input/output variables type(ESMF_State), intent(in) :: state From 5a3d2b8b9bfdaa1136046bf90a2545c84c2a5971 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 30 Dec 2025 16:05:22 -0700 Subject: [PATCH 06/10] Rename a subroutine, as suggested in review --- mediator/med.F90 | 4 ++-- mediator/med_field_info_mod.F90 | 12 ++++++------ mediator/med_fraction_mod.F90 | 4 ++-- mediator/med_phases_aofluxes_mod.F90 | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/mediator/med.F90 b/mediator/med.F90 index 1f3507b89..81909d012 100644 --- a/mediator/med.F90 +++ b/mediator/med.F90 @@ -38,7 +38,7 @@ module MED 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_ungridded, med_field_info_array_from_state + 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 @@ -1798,7 +1798,7 @@ 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_ungridded( & + call med_field_info_array_from_names_wtracers( & field_names = fldnames, & field_info_array = field_info_array, & rc = rc) diff --git a/mediator/med_field_info_mod.F90 b/mediator/med_field_info_mod.F90 index be8a132bc..04e0c59af 100644 --- a/mediator/med_field_info_mod.F90 +++ b/mediator/med_field_info_mod.F90 @@ -23,8 +23,8 @@ module med_field_info_mod public :: med_field_info_create ! Create an array of field_info objects based on an array of names, where water tracers - ! are given an ungridded dimension - public :: med_field_info_array_from_names_wtracers_ungridded + ! 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 @@ -100,9 +100,9 @@ end function med_field_info_create !----------------------------------------------------------------------------- - subroutine med_field_info_array_from_names_wtracers_ungridded(field_names, field_info_array, rc) + 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 given an ungridded dimension. + ! 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 @@ -120,7 +120,7 @@ subroutine med_field_info_array_from_names_wtracers_ungridded(field_names, field logical :: is_tracer integer :: n_tracers integer :: localrc - character(len=*), parameter :: subname = '(med_field_info_array_from_names_wtracers_ungridded)' + character(len=*), parameter :: subname = '(med_field_info_array_from_names_wtracers)' ! ---------------------------------------------- rc = ESMF_SUCCESS @@ -159,7 +159,7 @@ subroutine med_field_info_array_from_names_wtracers_ungridded(field_names, field end if end do - end subroutine med_field_info_array_from_names_wtracers_ungridded + end subroutine med_field_info_array_from_names_wtracers !----------------------------------------------------------------------------- diff --git a/mediator/med_fraction_mod.F90 b/mediator/med_fraction_mod.F90 index d4c8968ba..9d58a43d1 100644 --- a/mediator/med_fraction_mod.F90 +++ b/mediator/med_fraction_mod.F90 @@ -136,7 +136,7 @@ module med_fraction_mod 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_ungridded, med_field_info_array_from_state + use med_field_info_mod , only : med_field_info_array_from_names_wtracers, med_field_info_array_from_state implicit none private @@ -258,7 +258,7 @@ subroutine med_fraction_init(gcomp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return ! create FBFrac - call med_field_info_array_from_names_wtracers_ungridded( & + call med_field_info_array_from_names_wtracers( & field_names = fraclist(:,n1), & field_info_array = field_info_array, & rc = rc) diff --git a/mediator/med_phases_aofluxes_mod.F90 b/mediator/med_phases_aofluxes_mod.F90 index f4151c5be..c0d0192b5 100644 --- a/mediator/med_phases_aofluxes_mod.F90 +++ b/mediator/med_phases_aofluxes_mod.F90 @@ -32,7 +32,7 @@ module med_phases_aofluxes_mod 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_ungridded, med_field_info_array_from_state + 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 @@ -194,7 +194,7 @@ subroutine med_phases_aofluxes_init_fldbuns(gcomp, 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_ungridded( & + call med_field_info_array_from_names_wtracers( & field_names = fldnames_aof_out, & field_info_array = field_info_array, & rc = rc) @@ -644,7 +644,7 @@ 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_ungridded( & + call med_field_info_array_from_names_wtracers( & field_names = fldnames_ocn_in, & field_info_array = field_info_array, & rc = rc) From adca1fd14cc2a57d0d6e7e73002877e920379c4b Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Wed, 31 Dec 2025 14:56:16 -0700 Subject: [PATCH 07/10] Refactor to use new shr_wtracers_is_wtracer_field function --- mediator/med_field_info_mod.F90 | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/mediator/med_field_info_mod.F90 b/mediator/med_field_info_mod.F90 index 04e0c59af..3d562c6b2 100644 --- a/mediator/med_field_info_mod.F90 +++ b/mediator/med_field_info_mod.F90 @@ -9,8 +9,7 @@ module med_field_info_mod 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 shr_string_mod , only : shr_string_withoutSuffix - use shr_wtracers_mod, only : WTRACERS_SUFFIX + use shr_wtracers_mod, only : shr_wtracers_is_wtracer_field implicit none private @@ -132,16 +131,7 @@ subroutine med_field_info_array_from_names_wtracers(field_names, field_info_arra n_tracers = 0 do i = 1, n_fields - call shr_string_withoutSuffix( & - in_str = field_names(i), & - suffix = WTRACERS_SUFFIX, & - has_suffix = is_tracer, & - rc = localrc) - if (localrc /= 0) then - call shr_log_error(subname//": ERROR in shr_string_withoutSuffix", rc=rc) - return - end if - + is_tracer = shr_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( & From 2ec86d3ae15b27dfcbf0cf8ccbfa2f4db1c2cb74 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Wed, 31 Dec 2025 14:57:21 -0700 Subject: [PATCH 08/10] Add some comments --- mediator/med_field_info_mod.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mediator/med_field_info_mod.F90 b/mediator/med_field_info_mod.F90 index 3d562c6b2..4aec00d87 100644 --- a/mediator/med_field_info_mod.F90 +++ b/mediator/med_field_info_mod.F90 @@ -107,7 +107,8 @@ subroutine med_field_info_array_from_names_wtracers(field_names, field_info_arra ! 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 + ! 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(:) @@ -156,7 +157,8 @@ 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 + ! 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 From d60fbebd5f947cb20678ccbfbedc0f5bd63cd152 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Wed, 31 Dec 2025 15:48:39 -0700 Subject: [PATCH 09/10] Wrap shr_wtracers_mod This way CESM can use shr_wtracers_mod while UFS uses a stub that removes this CESM_share dependency. --- cesm/share_wrappers/wtracers_mod.F90 | 18 +++++++++++++++ cime_config/buildexe | 1 + mediator/med_field_info_mod.F90 | 4 ++-- ufs/CMakeLists.txt | 2 +- ufs/wtracers_mod.F90 | 34 ++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 cesm/share_wrappers/wtracers_mod.F90 create mode 100644 ufs/wtracers_mod.F90 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/med_field_info_mod.F90 b/mediator/med_field_info_mod.F90 index 4aec00d87..eb8611197 100644 --- a/mediator/med_field_info_mod.F90 +++ b/mediator/med_field_info_mod.F90 @@ -9,7 +9,7 @@ module med_field_info_mod 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 shr_wtracers_mod, only : shr_wtracers_is_wtracer_field + use wtracers_mod , only : wtracers_is_wtracer_field implicit none private @@ -132,7 +132,7 @@ subroutine med_field_info_array_from_names_wtracers(field_names, field_info_arra n_tracers = 0 do i = 1, n_fields - is_tracer = shr_wtracers_is_wtracer_field(field_names(i)) + 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( & 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 From 43e4594d3ce3f64cd8dcb96e927410f9b8e730f9 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Wed, 31 Dec 2025 16:02:22 -0700 Subject: [PATCH 10/10] Remove unused variable --- mediator/med_field_info_mod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/mediator/med_field_info_mod.F90 b/mediator/med_field_info_mod.F90 index eb8611197..197f0a1b1 100644 --- a/mediator/med_field_info_mod.F90 +++ b/mediator/med_field_info_mod.F90 @@ -119,7 +119,6 @@ subroutine med_field_info_array_from_names_wtracers(field_names, field_info_arra integer :: i, n_fields logical :: is_tracer integer :: n_tracers - integer :: localrc character(len=*), parameter :: subname = '(med_field_info_array_from_names_wtracers)' ! ----------------------------------------------