From 491b5c6ad790dcf787a82330747b37668a67c273 Mon Sep 17 00:00:00 2001 From: "denise.worthen" Date: Fri, 17 Nov 2023 09:33:06 -0500 Subject: [PATCH 1/4] update ccpp --- ccpp/physics | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ccpp/physics b/ccpp/physics index d566ea4ae..bf5a53852 160000 --- a/ccpp/physics +++ b/ccpp/physics @@ -1 +1 @@ -Subproject commit d566ea4ae7dc777f8c1fcdfbda75a6ff150b168a +Subproject commit bf5a53852181bf38e2bb716f3845dddbc95d5a2f From aeb1dfc0de8770646363f68c1816760661be34f3 Mon Sep 17 00:00:00 2001 From: "denise.worthen" Date: Fri, 17 Nov 2023 09:44:36 -0500 Subject: [PATCH 2/4] Revert "update ccpp" This reverts commit 491b5c6ad790dcf787a82330747b37668a67c273. --- ccpp/physics | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ccpp/physics b/ccpp/physics index bf5a53852..d566ea4ae 160000 --- a/ccpp/physics +++ b/ccpp/physics @@ -1 +1 @@ -Subproject commit bf5a53852181bf38e2bb716f3845dddbc95d5a2f +Subproject commit d566ea4ae7dc777f8c1fcdfbda75a6ff150b168a From 6048f89caa9d028ed11374caae69d7423a485c72 Mon Sep 17 00:00:00 2001 From: Denise Worthen Date: Mon, 4 Mar 2024 08:30:35 -0500 Subject: [PATCH 3/4] add cpl_scalars for atm * add field cpl_scalars to export state of fv3atm when coupled. cpl_scalars contain the dimensions of the fv3atm domain and are used by cmeps to write mediator history files as a single 2d grid for regional and 6 2d grids for CSG. --- CMakeLists.txt | 1 + atmos_model.F90 | 54 +++++----- cpl/module_cap_cpl.F90 | 1 - cpl/module_cplfields.F90 | 42 ++++---- cpl/module_cplscalars.F90 | 204 ++++++++++++++++++++++++++++++++++++++ fv3_cap.F90 | 55 +++++++++- module_fcst_grid_comp.F90 | 26 ++++- 7 files changed, 337 insertions(+), 46 deletions(-) create mode 100644 cpl/module_cplscalars.F90 diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d0dcf6f6..67ca4e965 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,6 +104,7 @@ add_library(fv3atm cpl/module_block_data.F90 cpl/module_cplfields.F90 cpl/module_cap_cpl.F90 + cpl/module_cplscalars.F90 io/fv3atm_common_io.F90 io/fv3atm_clm_lake_io.F90 io/fv3atm_rrfs_sd_io.F90 diff --git a/atmos_model.F90 b/atmos_model.F90 index 3f5de6b2c..5f41736b6 100644 --- a/atmos_model.F90 +++ b/atmos_model.F90 @@ -3142,7 +3142,8 @@ subroutine setup_exportdata(rc) use ESMF - use module_cplfields, only: exportFields, chemistryFieldNames + use module_cplfields, only: exportFields, chemistryFieldNames + use module_cplscalars, only: flds_scalar_name !--- arguments integer, optional, intent(out) :: rc @@ -3192,33 +3193,36 @@ subroutine setup_exportdata(rc) if (isFound) then call ESMF_FieldGet(exportFields(n), name=fieldname, rank=rank, typekind=datatype, rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__, rcToReturn=rc)) return - if (datatype == ESMF_TYPEKIND_R8) then - select case (rank) - case (2) - call ESMF_FieldGet(exportFields(n),farrayPtr=datar82d,localDE=0, rc=localrc) - if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__, rcToReturn=rc)) return - case (3) - call ESMF_FieldGet(exportFields(n),farrayPtr=datar83d,localDE=0, rc=localrc) - if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__, rcToReturn=rc)) return - case default - !--- skip field - isFound = .false. - end select - else if (datatype == ESMF_TYPEKIND_R4) then - select case (rank) - case (2) - call ESMF_FieldGet(exportFields(n),farrayPtr=datar42d,localDE=0, rc=localrc) - if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__, rcToReturn=rc)) return - case default - !--- skip field - isFound = .false. - end select - else - !--- skip field + if (trim(fieldname) == trim(flds_scalar_name)) then isFound = .false. + else + if (datatype == ESMF_TYPEKIND_R8) then + select case (rank) + case (2) + call ESMF_FieldGet(exportFields(n),farrayPtr=datar82d,localDE=0, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__, rcToReturn=rc)) return + case (3) + call ESMF_FieldGet(exportFields(n),farrayPtr=datar83d,localDE=0, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__, rcToReturn=rc)) return + case default + !--- skip field + isFound = .false. + end select + else if (datatype == ESMF_TYPEKIND_R4) then + select case (rank) + case (2) + call ESMF_FieldGet(exportFields(n),farrayPtr=datar42d,localDE=0, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__, rcToReturn=rc)) return + case default + !--- skip field + isFound = .false. + end select + else + !--- skip field + isFound = .false. + end if end if end if - !--- skip field if only required for chemistry if (isFound .and. GFS_control%cplchm) isFound = .not.any(trim(fieldname) == chemistryFieldNames) diff --git a/cpl/module_cap_cpl.F90 b/cpl/module_cap_cpl.F90 index 313ab6cf6..cd92532d7 100644 --- a/cpl/module_cap_cpl.F90 +++ b/cpl/module_cap_cpl.F90 @@ -11,7 +11,6 @@ module module_cap_cpl private public diagnose_cplFields -! contains !----------------------------------------------------------------------------- diff --git a/cpl/module_cplfields.F90 b/cpl/module_cplfields.F90 index bce01c979..524db0208 100644 --- a/cpl/module_cplfields.F90 +++ b/cpl/module_cplfields.F90 @@ -26,7 +26,7 @@ module module_cplfields ! l : model levels (3D) ! s : surface (2D) ! t : tracers (4D) - integer, public, parameter :: NexportFields = 119 + integer, public, parameter :: NexportFields = 120 type(ESMF_Field), target, public :: exportFields(NexportFields) type(FieldInfo), dimension(NexportFields), public, parameter :: exportFieldsInfo = [ & @@ -153,7 +153,8 @@ module module_cplfields FieldInfo("snwdph ", "s"), & FieldInfo("f10m ", "s"), & FieldInfo("zorl ", "s"), & - FieldInfo("t2m ", "s") ] + FieldInfo("t2m ", "s"), & + FieldInfo("cpl_scalars ", "s")] ! Import Fields ---------------------------------------- integer, public, parameter :: NimportFields = 64 @@ -192,7 +193,7 @@ module module_cplfields ! For receiving fluxes from external land component FieldInfo("land_fraction ", "s"), & FieldInfo("inst_snow_area_fraction_lnd ", "s"), & - FieldInfo("inst_spec_humid_lnd ", "s"), & + FieldInfo("inst_spec_humid_lnd ", "s"), & FieldInfo("inst_laten_heat_flx_lnd ", "s"), & FieldInfo("inst_sensi_heat_flx_lnd ", "s"), & FieldInfo("inst_potential_laten_heat_flx_lnd ", "s"), & @@ -441,6 +442,7 @@ subroutine realizeConnectedCplFields(state, grid, & use field_manager_mod, only: MODEL_ATMOS use tracer_manager_mod, only: get_number_tracers, get_tracer_names + use module_cplscalars, only: flds_scalar_name, flds_scalar_num, SetScalarField type(ESMF_State), intent(inout) :: state type(ESMF_Grid), intent(in) :: grid @@ -488,22 +490,27 @@ subroutine realizeConnectedCplFields(state, grid, & isConnected = NUOPC_IsConnected(state, fieldName=trim(fields_info(item)%name), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (isConnected) then - call ESMF_StateGet(state, field=field, itemName=trim(fields_info(item)%name), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - call ESMF_FieldEmptySet(field, grid=grid, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return - select case (fields_info(item)%type) + if (trim(fields_info(item)%name) == trim(flds_scalar_name)) then + ! Create the scalar field + call SetScalarField(field, flds_scalar_name, flds_scalar_num, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + else + call ESMF_StateGet(state, field=field, itemName=trim(fields_info(item)%name), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + call ESMF_FieldEmptySet(field, grid=grid, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + select case (fields_info(item)%type) case ('l','layer') call ESMF_FieldEmptyComplete(field, typekind=ESMF_TYPEKIND_R8, & - ungriddedLBound=(/1/), ungriddedUBound=(/numLevels/), rc=rc) + ungriddedLBound=(/1/), ungriddedUBound=(/numLevels/), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return case ('i','interface') call ESMF_FieldEmptyComplete(field, typekind=ESMF_TYPEKIND_R8, & - ungriddedLBound=(/1/), ungriddedUBound=(/numLevels+1/), rc=rc) + ungriddedLBound=(/1/), ungriddedUBound=(/numLevels+1/), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return case ('t','tracer') call ESMF_FieldEmptyComplete(field, typekind=ESMF_TYPEKIND_R8, & - ungriddedLBound=(/1, 1/), ungriddedUBound=(/numLevels, numTracers/), rc=rc) + ungriddedLBound=(/1, 1/), ungriddedUBound=(/numLevels, numTracers/), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (allocated(tracerNames)) then call addFieldMetadata(field, 'tracerNames', tracerNames, rc=rc) @@ -518,14 +525,15 @@ subroutine realizeConnectedCplFields(state, grid, & if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return case ('g','soil') call ESMF_FieldEmptyComplete(field, typekind=ESMF_TYPEKIND_R8, & - ungriddedLBound=(/1/), ungriddedUBound=(/numSoilLayers/), rc=rc) + ungriddedLBound=(/1/), ungriddedUBound=(/numSoilLayers/), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return case default call ESMF_LogSetError(ESMF_RC_NOT_VALID, & - msg="exportFieldType = '"//trim(fields_info(item)%type)//"' not recognized", & - line=__LINE__, file=__FILE__, rcToReturn=rc) + msg="exportFieldType = '"//trim(fields_info(item)%type)//"' not recognized", & + line=__LINE__, file=__FILE__, rcToReturn=rc) return - end select + end select + end if call NUOPC_Realize(state, field=field, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return @@ -536,13 +544,13 @@ subroutine realizeConnectedCplFields(state, grid, & ! -- save field fieldList(item) = field call ESMF_LogWrite('realizeConnectedCplFields '//trim(state_tag)//' Field '//trim(fields_info(item)%name) & - // ' is connected ', ESMF_LOGMSG_INFO, line=__LINE__, file=__FILE__, rc=rc) + // ' is connected ', ESMF_LOGMSG_INFO, line=__LINE__, file=__FILE__, rc=rc) else ! remove a not connected Field from State call ESMF_StateRemove(state, (/trim(fields_info(item)%name)/), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_LogWrite('realizeConnectedCplFields '//trim(state_tag)//' Field '//trim(fields_info(item)%name) & - // ' is not connected ', ESMF_LOGMSG_INFO, line=__LINE__, file=__FILE__, rc=rc) + // ' is not connected ', ESMF_LOGMSG_INFO, line=__LINE__, file=__FILE__, rc=rc) end if end do diff --git a/cpl/module_cplscalars.F90 b/cpl/module_cplscalars.F90 new file mode 100644 index 000000000..8bfabd4df --- /dev/null +++ b/cpl/module_cplscalars.F90 @@ -0,0 +1,204 @@ +!> @file +!> @brief Manage cpl_scalars +!> @author mvertens@ucar.edu +!> @author modified for FV3atm by Denise.Worthen@noaa.gov @date 03-03-2024 + +!> Manage scalars in import and export states. Called by realizeConnectedCplFields +!> to set the required scalar data into a state. The scalar_value will be set into +!> a field with name flds_scalar_name. The scalar_id identifies which dimension in +!> the scalar field is given by the scalar_value. The number of scalars is used to +!> ensure that the scalar_id is within the bounds of the scalar field + +module module_cplscalars + + use NUOPC + use ESMF, only : ESMF_Field, ESMF_Distgrid, ESMF_Grid, ESMF_State + use ESMF, only : ESMF_VM, ESMF_VMGetCurrent, ESMF_VMGet, ESMF_VMBroadCast + use ESMF, only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_FAILURE, ESMF_SUCCESS + use ESMF, only : ESMF_LOGMSG_INFO, ESMF_LOGWRITE, ESMF_TYPEKIND_R8, ESMF_KIND_R8 + use ESMF, only : ESMF_GridCreate, ESMF_FieldCreate, ESMF_StateGet, ESMF_DistGridCreate + use ESMF, only : ESMF_FieldGet + + implicit none + + private + public SetScalarField + public State_SetScalar + public State_GetScalar + + ! set from config + integer, public :: flds_scalar_num, flds_scalar_index_nx + integer, public :: flds_scalar_index_ny, flds_scalar_index_ntile + character(len=80), public :: flds_scalar_name + +contains + + !================================================================================ + !> Create a scalar field + !> + !> @param[inout] field an ESMF_Field + !> @param[in] flds_scalar_name the name of the scalar + !> @param[in] flds_scalar_num the number of scalars + !> @param[inout] rc a return code + !> + !> @author mvertens@ucar.edu, Denise.Worthen@noaa.gov + !> @date 03-03-2024 + subroutine SetScalarField(field, flds_scalar_name, flds_scalar_num, rc) + + type(ESMF_Field) , intent(inout) :: field + character(len=*) , intent(in) :: flds_scalar_name + integer , intent(in) :: flds_scalar_num + integer , intent(inout) :: rc + + ! local variables + type(ESMF_Distgrid) :: distgrid + type(ESMF_Grid) :: grid + + character(len=*), parameter :: subname='(module_cplscalars:SetScalarField)' + ! ---------------------------------------------- + + rc = ESMF_SUCCESS + + ! create a DistGrid with a single index space element, which gets mapped onto DE 0. + distgrid = ESMF_DistGridCreate(minIndex=(/1/), maxIndex=(/1/), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + grid = ESMF_GridCreate(distgrid, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + field = ESMF_FieldCreate(name=trim(flds_scalar_name), grid=grid, typekind=ESMF_TYPEKIND_R8, & + ungriddedLBound=(/1/), ungriddedUBound=(/flds_scalar_num/), gridToFieldMap=(/2/), rc=rc) ! num of scalar values + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + end subroutine SetScalarField + + !================================================================================ + !> Set scalar data into a state + !> + !> @param[inout] State an ESMF_State + !> @param[in] scalar_value the value of the scalar + !> @param[in] scalar_id the identity of the scalar + !> @param[in] flds_scalar_name the name of the scalar + !> @param[in] flds_scalar_num the number of scalars + !> @param[inout] rc a return code + !> + !> @author mvertens@ucar.edu, Denise.Worthen@noaa.gov + !> @date 03-02-2024 + subroutine State_SetScalar(scalar_value, scalar_id, State, flds_scalar_name, flds_scalar_num, rc) + + ! input/output arguments + real(ESMF_KIND_R8), intent(in) :: scalar_value + integer, intent(in) :: scalar_id + type(ESMF_State), intent(inout) :: State + character(len=*), intent(in) :: flds_scalar_name + integer, intent(in) :: flds_scalar_num + integer, intent(inout) :: rc + + ! local variables + integer :: mytask + type(ESMF_Field) :: lfield + type(ESMF_VM) :: vm + real(ESMF_KIND_R8), pointer :: farrayptr(:,:) + + character(len=*), parameter :: subname = ' (module_cplscalars:state_setscalar) ' + ! ---------------------------------------------- + + rc = ESMF_SUCCESS + + call ESMF_VMGetCurrent(vm, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_VMGet(vm, localPet=mytask, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_StateGet(State, itemName=trim(flds_scalar_name), field=lfield, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + if (mytask == 0) then + call ESMF_FieldGet(lfield, farrayPtr = farrayptr, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + if (scalar_id < 0 .or. scalar_id > flds_scalar_num) then + call ESMF_LogWrite(trim(subname)//": ERROR in scalar_id", ESMF_LOGMSG_INFO) + rc = ESMF_FAILURE + return + endif + farrayptr(scalar_id,1) = scalar_value + endif + + end subroutine State_SetScalar + + !=============================================================================== + !> Get scalar data from a state + !> + !> @details Obtain the field flds_scalar_name from a State and broadcast and + !> it to all PEs + !> + !> @param[in] State an ESMF_State + !> @param[in] scalar_value the value of the scalar + !> @param[in] scalar_id the identity of the scalar + !> @param[in] flds_scalar_name the name of the scalar + !> @param[in] flds_scalar_num the number of scalars + !> @param[out] rc a return code + !> + !> @author mvertens@ucar.edu, Denise.Worthen@noaa.gov + !> @date 03-02-2024 + subroutine State_GetScalar(state, scalar_id, scalar_value, flds_scalar_name, flds_scalar_num, rc) + + ! ---------------------------------------------- + ! Get scalar data from State for a particular name and broadcast it to all other pets + ! ---------------------------------------------- + + ! input/output variables + type(ESMF_State), intent(in) :: state + integer, intent(in) :: scalar_id + real(ESMF_KIND_R8), intent(out) :: scalar_value + character(len=*), intent(in) :: flds_scalar_name + integer, intent(in) :: flds_scalar_num + integer, intent(inout) :: rc + + ! local variables + integer :: mytask, ierr, icount + type(ESMF_VM) :: vm + type(ESMF_Field) :: field + real(ESMF_KIND_R8), pointer :: farrayptr(:,:) + real(ESMF_KIND_R8) :: tmp(1) + + character(len=*), parameter :: subname = ' (module_cplscalars:state_getscalar) ' + ! ---------------------------------------------- + + rc = ESMF_SUCCESS + + call ESMF_VMGetCurrent(vm, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + call ESMF_VMGet(vm, localPet=mytask, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + ! check item exist or not? + call ESMF_StateGet(State, itemSearch=trim(flds_scalar_name), itemCount=icount, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + if (icount > 0) then + call ESMF_StateGet(State, itemName=trim(flds_scalar_name), field=field, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + + if (mytask == 0) then + call ESMF_FieldGet(field, farrayPtr = farrayptr, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + if (scalar_id < 0 .or. scalar_id > flds_scalar_num) then + call ESMF_LogWrite(trim(subname)//": ERROR in scalar_id", ESMF_LOGMSG_INFO, line=__LINE__, file=__FILE__) + rc = ESMF_FAILURE + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + endif + tmp(:) = farrayptr(scalar_id,:) + endif + call ESMF_VMBroadCast(vm, tmp, 1, 0, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + scalar_value = tmp(1) + else + scalar_value = 0.0_ESMF_KIND_R8 + call ESMF_LogWrite(trim(subname)//": no ESMF_Field found named: "//trim(flds_scalar_name), ESMF_LOGMSG_INFO) + end if + + end subroutine State_GetScalar +end module module_cplscalars diff --git a/fv3_cap.F90 b/fv3_cap.F90 index 5401e66a5..713460fe3 100644 --- a/fv3_cap.F90 +++ b/fv3_cap.F90 @@ -46,6 +46,9 @@ module fv3atm_cap_mod use module_cplfields, only: importFieldsValid, queryImportFields use module_cap_cpl, only: diagnose_cplFields + use module_cplscalars, only: flds_scalar_name, flds_scalar_num, & + flds_scalar_index_nx, flds_scalar_index_ny, & + flds_scalar_index_ntile implicit none private @@ -216,6 +219,7 @@ subroutine InitializeAdvertise(gcomp, rc) integer :: sloc type(ESMF_StaggerLoc) :: staggerloc + character(len=20) :: cvalue ! !------------------------------------------------------------------------ ! @@ -260,7 +264,7 @@ subroutine InitializeAdvertise(gcomp, rc) cplprint_flag = (trim(value)=="true") write(msgString,'(A,l6)') trim(subname)//' cplprint_flag = ',cplprint_flag - call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO, rc=rc) + call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO) ! Read in cap debug flag call NUOPC_CompAttributeGet(gcomp, name='dbug_flag', value=value, isPresent=isPresent, isSet=isSet, rc=rc) @@ -269,7 +273,54 @@ subroutine InitializeAdvertise(gcomp, rc) read(value,*) dbug end if write(msgString,'(A,i6)') trim(subname)//' dbug = ',dbug - call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO, rc=rc) + call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO) + + ! set cpl_scalars from config. Default to null values for standalone + flds_scalar_name = '' + flds_scalar_num = 0 + flds_scalar_index_nx = 0 + flds_scalar_index_ny = 0 + flds_scalar_index_ntile = 0 + call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldName", value=cvalue, isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + if (isPresent .and. isSet) then + flds_scalar_name = trim(cvalue) + call ESMF_LogWrite(trim(subname)//' flds_scalar_name = '//trim(flds_scalar_name), ESMF_LOGMSG_INFO) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + endif + + call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldCount", value=cvalue, isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + if (isPresent .and. isSet) then + read(cvalue, *) flds_scalar_num + write(msgString,*) flds_scalar_num + call ESMF_LogWrite(trim(subname)//' flds_scalar_num = '//trim(msgString), ESMF_LOGMSG_INFO) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + endif + call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldIdxGridNX", value=cvalue, isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + if (isPresent .and. isSet) then + read(cvalue,*) flds_scalar_index_nx + write(msgString,*) flds_scalar_index_nx + call ESMF_LogWrite(trim(subname)//' : flds_scalar_index_nx = '//trim(msgString), ESMF_LOGMSG_INFO) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + endif + call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldIdxGridNY", value=cvalue, isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + if (isPresent .and. isSet) then + read(cvalue,*) flds_scalar_index_ny + write(msgString,*) flds_scalar_index_ny + call ESMF_LogWrite(trim(subname)//' : flds_scalar_index_ny = '//trim(msgString), ESMF_LOGMSG_INFO) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + endif + call NUOPC_CompAttributeGet(gcomp, name="ScalarFieldIdxGridNTile", value=cvalue, isPresent=isPresent, isSet=isSet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + if (isPresent .and. isSet) then + read(cvalue,*) flds_scalar_index_ntile + write(msgString,*) flds_scalar_index_ntile + call ESMF_LogWrite(trim(subname)//' : flds_scalar_index_ntile = '//trim(msgString), ESMF_LOGMSG_INFO) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + endif !------------------------------------------------------------------------ ! get config variables diff --git a/module_fcst_grid_comp.F90 b/module_fcst_grid_comp.F90 index ea622369c..6fbb902f0 100644 --- a/module_fcst_grid_comp.F90 +++ b/module_fcst_grid_comp.F90 @@ -474,6 +474,12 @@ end subroutine init_advertise ! subroutine init_realize(nest, importState, exportState, clock, rc) ! + + use module_cplscalars, only : flds_scalar_name, flds_scalar_num, & + flds_scalar_index_nx, flds_scalar_index_ny, & + flds_scalar_index_ntile + use module_cplscalars, only : State_SetScalar + type(ESMF_GridComp) :: nest type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock @@ -481,10 +487,18 @@ subroutine init_realize(nest, importState, exportState, clock, rc) ! !*** local variables ! + real(ESMF_KIND_R8) :: scalardim(3) type(ESMF_Grid) :: grid + scalardim = 0.0 + ! cpl_scalars for export state + scalardim(1) = real(Atmos%mlon,8) + scalardim(2) = real(Atmos%mlat,8) + scalardim(3) = 1.0 + if (.not. Atmos%regional)scalardim(3) = 6.0 + rc = ESMF_SUCCESS -! + ! access this domain grid call ESMF_GridCompGet(nest, grid=grid, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return @@ -495,6 +509,16 @@ subroutine init_realize(nest, importState, exportState, clock, rc) exportFieldsInfo, 'FV3 Export', exportFields, 0.0_ESMF_KIND_R8, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + if (flds_scalar_num > 0) then + ! Set the scalar data into the exportstate + call State_SetScalar(scalardim(1), flds_scalar_index_nx, exportState, flds_scalar_name, flds_scalar_num, rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + call State_SetScalar(scalardim(2), flds_scalar_index_ny, exportState, flds_scalar_name, flds_scalar_num, rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + call State_SetScalar(scalardim(3), flds_scalar_index_ntile, exportState, flds_scalar_name, flds_scalar_num, rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return + end if + ! -- initialize export fields if applicable call setup_exportdata(rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return From a8b7165d293b2c0888925ab691ccbea0fa34f55e Mon Sep 17 00:00:00 2001 From: Denise Worthen Date: Wed, 20 Mar 2024 09:15:17 -0400 Subject: [PATCH 4/4] remove unused NUOPC use statement --- cpl/module_cplscalars.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/cpl/module_cplscalars.F90 b/cpl/module_cplscalars.F90 index 8bfabd4df..2b3e5869e 100644 --- a/cpl/module_cplscalars.F90 +++ b/cpl/module_cplscalars.F90 @@ -11,7 +11,6 @@ module module_cplscalars - use NUOPC use ESMF, only : ESMF_Field, ESMF_Distgrid, ESMF_Grid, ESMF_State use ESMF, only : ESMF_VM, ESMF_VMGetCurrent, ESMF_VMGet, ESMF_VMBroadCast use ESMF, only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_FAILURE, ESMF_SUCCESS