Skip to content

Commit 6d93e62

Browse files
authored
Merge pull request #628 from billsacks/handle_fields_with_ungridded_dims
A few refactorings to handle fields with ungridded dimensions, particularly for prep_rof_mod ### Description of changes These are changes to support adding water tracers in CMEPS, which will be done using fields with ungridded dimensions. In particular, the changes here are needed to support adding ROF-related fields. I initially developed and tested these changes in the context of my branch for adding water tracers, but have split these off to their own PR to facilitate review of these changes, since they potentially impact things beyond just the addition of water tracers. (1) Refactor med_field_info_mod and med_methods_mod to expose two methods that will be useful for the water tracer work: med_field_info_create_from_field (extracted from med_field_info_array_from_state) and med_field_info_esmf_fieldcreate (extracted from med_methods_FB_init) (2) Change the mechanism for getting ungridded info from a Field: The previous mechanism - using ESMF/NUOPC attributes - doesn't work in a new context where I want to use this routine. So I have changed this to do a more direct querying of the Field. I added write statements to check whether there were any differences from this change, in `ERS_D_Ld3.ne30pg3_t232.B1850C_LTso.derecho_intel.allactive-defaultio`. At least in that configuration, the only difference was that, in various calls, `cpl_scalars` is now given an ungridded dimension of size 4, whereas previously it was not given an ungridded dimension. The new behavior seems probably correct, but I guess this didn't have any impact before. As noted below, this doesn't change answers, at least for the tests I ran. (3) Generalize code in prep_rof to handle fields with ungridded dimensions. This will be needed for water tracers. The one piece that is *not* handled yet is the irrigation-specific mapping. ### Specific notes Contributors other than yourself, if any: CMEPS Issues Fixed (include github issue #): Are changes expected to change answers? (specify if bfb, different at roundoff, more substantial) NO - bfb Any User Interface Changes (namelist or namelist defaults changes)? NO ### Testing performed Please describe the tests along with the target model and machine(s) If possible, please also added hashes that were used in the testing Tested in the context of cesm3_0_alpha08b, or something close to it (ESCOMP/CESM@622984f), with share updated to share1.1.18, and the changes here rebased onto cmeps1.1.32. The following tests all passed and were bit-for-bit with baselines: ``` ERS_Ly7.f09_g17_gris4.T1850Gg.derecho_intel SMS_Lm13.f10_f10_mg37.I1850Clm50SpG.derecho_intel MULTINOAIS_Ly2.f10_f10_ais8gris4_mg37.I1850Clm50SpRsGag.derecho_intel.cism-change_params SMS_D_Ld1.ne30pg3_t232.I1850Clm50BgcSpinup.derecho_intel.clm-cplhist SMS_Ld40.TL319_t232.C_JRA.derecho_intel ERS_D_Ld3.ne30pg3_t232.B1850C_LTso.derecho_intel.allactive-defaultio ERI.ne30pg3_t232.B1850C_LTso.derecho_intel.allactive-defaultio ERC_D_Ln9.ne30pg3_ne30pg3_mt232.FHISTC_LTso.derecho_intel.cam-outfrq9s ERI.TL319_t232.G_JRA.derecho_intel.cice-default SMS_D.TL319_t232.G_JRA_RYF.derecho_intel ```
2 parents 9991b7b + b25b294 commit 6d93e62

File tree

3 files changed

+192
-146
lines changed

3 files changed

+192
-146
lines changed

mediator/med_field_info_mod.F90

Lines changed: 111 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ module med_field_info_mod
55
! used to create an ESMF FieldBundle.
66
!-----------------------------------------------------------------------------
77

8-
use ESMF , only : ESMF_MAXSTR, ESMF_SUCCESS
9-
use ESMF , only : ESMF_Field, ESMF_State, ESMF_AttributeGet, ESMF_StateGet
8+
use ESMF , only : ESMF_MAXSTR, ESMF_SUCCESS, ESMF_TYPEKIND_R8
9+
use ESMF , only : ESMF_Field, ESMF_State, ESMF_StateGet
10+
use ESMF , only : ESMF_Mesh, ESMF_MeshLoc
11+
use ESMF , only : ESMF_FieldCreate, ESMF_FieldGet
1012
use med_utils_mod , only : ChkErr => med_utils_ChkErr
1113
use shr_log_mod , only : shr_log_error
1214
use wtracers_mod , only : wtracers_is_wtracer_field
@@ -18,8 +20,11 @@ module med_field_info_mod
1820
! Public methods
1921
!-----------------------------------------------
2022

21-
! Create a single field
22-
public :: med_field_info_create
23+
! Create a single field_info object from direct specification of values
24+
public :: med_field_info_create_directly
25+
26+
! Create a single field_info object from information in an ESMF_Field
27+
public :: med_field_info_create_from_field
2328

2429
! Create an array of field_info objects based on an array of names, where water tracers
2530
! are treated specially (being given an ungridded dimension)
@@ -28,6 +33,9 @@ module med_field_info_mod
2833
! Create an array of field_info objects based on the fields in an ESMF State
2934
public :: med_field_info_array_from_state
3035

36+
! Create an ESMF Field (using ESMF_FieldCreate) based on a field_info object
37+
public :: med_field_info_esmf_fieldcreate
38+
3139
!-----------------------------------------------
3240
! Types
3341
!-----------------------------------------------
@@ -48,8 +56,8 @@ module med_field_info_mod
4856
contains
4957
!================================================================================
5058

51-
function med_field_info_create(name, ungridded_lbound, ungridded_ubound, rc) result(field_info)
52-
! Create a single field
59+
function med_field_info_create_directly(name, ungridded_lbound, ungridded_ubound, rc) result(field_info)
60+
! Create a single field_info object from direct specification of values
5361

5462
! input/output variables
5563
character(len=*), intent(in) :: name
@@ -64,7 +72,7 @@ function med_field_info_create(name, ungridded_lbound, ungridded_ubound, rc) res
6472

6573
! local variables
6674
integer :: n_ungridded
67-
character(len=*), parameter :: subname = '(med_field_info_create)'
75+
character(len=*), parameter :: subname = '(med_field_info_create_directly)'
6876
! ----------------------------------------------
6977

7078
rc = ESMF_SUCCESS
@@ -95,7 +103,61 @@ function med_field_info_create(name, ungridded_lbound, ungridded_ubound, rc) res
95103
field_info%n_ungridded = 0
96104
end if
97105

98-
end function med_field_info_create
106+
end function med_field_info_create_directly
107+
108+
!-----------------------------------------------------------------------------
109+
110+
function med_field_info_create_from_field(field, name, rc) result(field_info)
111+
! Create a single field_info object from information in an ESMF_Field
112+
113+
! input/output variables
114+
! We get information other than the name from this ESMF_Field object
115+
type(ESMF_Field), intent(in) :: field
116+
117+
! We should be able to get the name from the field, but in all current uses of this
118+
! function, we already have the name available, so it's easy enough to just pass it in
119+
! rather than making this function query it again. If future users did not already
120+
! have the name readily available, we could either change this to optional or remove
121+
! it entirely and just always get the name from querying the field.
122+
character(len=*), intent(in) :: name
123+
124+
integer, intent(out) :: rc
125+
type(med_field_info_type) :: field_info ! function result
126+
127+
! local variables
128+
integer :: n_ungridded
129+
integer, allocatable :: ungridded_lbound(:)
130+
integer, allocatable :: ungridded_ubound(:)
131+
132+
character(len=*), parameter :: subname = '(med_field_info_create_from_field)'
133+
! ----------------------------------------------
134+
135+
rc = ESMF_SUCCESS
136+
137+
call ESMF_FieldGet(field, ungriddedDimCount=n_ungridded, rc=rc)
138+
if (chkerr(rc,__LINE__,u_FILE_u)) return
139+
140+
if (n_ungridded == 0) then
141+
field_info = med_field_info_create_directly( &
142+
name=name, &
143+
rc=rc)
144+
if (chkerr(rc,__LINE__,u_FILE_u)) return
145+
else
146+
allocate(ungridded_lbound(n_ungridded))
147+
allocate(ungridded_ubound(n_ungridded))
148+
call ESMF_FieldGet(field, &
149+
ungriddedLBound=ungridded_lbound, ungriddedUBound=ungridded_ubound, rc=rc)
150+
if (chkerr(rc,__LINE__,u_FILE_u)) return
151+
field_info = med_field_info_create_directly( &
152+
name=name, &
153+
ungridded_lbound=ungridded_lbound, &
154+
ungridded_ubound=ungridded_ubound, &
155+
rc=rc)
156+
if (chkerr(rc,__LINE__,u_FILE_u)) return
157+
deallocate(ungridded_lbound)
158+
deallocate(ungridded_ubound)
159+
end if
160+
end function med_field_info_create_from_field
99161

100162
!-----------------------------------------------------------------------------
101163

@@ -134,15 +196,15 @@ subroutine med_field_info_array_from_names_wtracers(field_names, field_info_arra
134196
is_tracer = wtracers_is_wtracer_field(field_names(i))
135197
if (is_tracer) then
136198
! Field is a water tracer; assume a single ungridded dimension
137-
field_info_array(i) = med_field_info_create( &
199+
field_info_array(i) = med_field_info_create_directly( &
138200
name=field_names(i), &
139201
ungridded_lbound=[1], &
140202
ungridded_ubound=[n_tracers], &
141203
rc=rc)
142204
if (chkerr(rc,__LINE__,u_FILE_u)) return
143205
else
144206
! Not a water tracer; assume no ungridded dimensions
145-
field_info_array(i) = med_field_info_create( &
207+
field_info_array(i) = med_field_info_create_directly( &
146208
name=field_names(i), &
147209
rc=rc)
148210
if (chkerr(rc,__LINE__,u_FILE_u)) return
@@ -168,10 +230,6 @@ subroutine med_field_info_array_from_state(state, field_info_array, rc)
168230
integer :: i, n_fields
169231
character(ESMF_MAXSTR), allocatable :: field_names(:)
170232
type(ESMF_Field) :: field
171-
logical :: is_present
172-
integer :: n_ungridded
173-
integer, allocatable :: ungridded_lbound(:)
174-
integer, allocatable :: ungridded_ubound(:)
175233
character(len=*), parameter :: subname = '(med_field_info_array_from_state)'
176234
! ----------------------------------------------
177235

@@ -188,38 +246,48 @@ subroutine med_field_info_array_from_state(state, field_info_array, rc)
188246
call ESMF_StateGet(state, itemName=trim(field_names(i)), field=field, rc=rc)
189247
if (chkerr(rc,__LINE__,u_FILE_u)) return
190248

191-
call ESMF_AttributeGet(field, name="UngriddedUBound", convention="NUOPC", &
192-
purpose="Instance", itemCount=n_ungridded, isPresent=is_present, rc=rc)
249+
field_info_array(i) = med_field_info_create_from_field( &
250+
field=field, &
251+
name=field_names(i), &
252+
rc=rc)
193253
if (chkerr(rc,__LINE__,u_FILE_u)) return
194-
if (.not. is_present) then
195-
n_ungridded = 0
196-
end if
197-
198-
if (n_ungridded == 0) then
199-
field_info_array(i) = med_field_info_create( &
200-
name=field_names(i), &
201-
rc=rc)
202-
if (chkerr(rc,__LINE__,u_FILE_u)) return
203-
else
204-
allocate(ungridded_lbound(n_ungridded))
205-
allocate(ungridded_ubound(n_ungridded))
206-
call ESMF_AttributeGet(field, name="UngriddedLBound", convention="NUOPC", &
207-
purpose="Instance", valueList=ungridded_lbound, rc=rc)
208-
if (chkerr(rc,__LINE__,u_FILE_u)) return
209-
call ESMF_AttributeGet(field, name="UngriddedUBound", convention="NUOPC", &
210-
purpose="Instance", valueList=ungridded_ubound, rc=rc)
211-
if (chkerr(rc,__LINE__,u_FILE_u)) return
212-
field_info_array(i) = med_field_info_create( &
213-
name=field_names(i), &
214-
ungridded_lbound=ungridded_lbound, &
215-
ungridded_ubound=ungridded_ubound, &
216-
rc=rc)
217-
if (chkerr(rc,__LINE__,u_FILE_u)) return
218-
deallocate(ungridded_lbound)
219-
deallocate(ungridded_ubound)
220-
end if
221254
end do
222255

223256
end subroutine med_field_info_array_from_state
224257

258+
!-----------------------------------------------------------------------------
259+
260+
subroutine med_field_info_esmf_fieldcreate(field_info, mesh, meshloc, field, rc)
261+
! Create an ESMF Field (using ESMF_FieldCreate) based on a field_info object
262+
263+
! input/output variables
264+
type(med_field_info_type), intent(in) :: field_info
265+
type(ESMF_Mesh), intent(in) :: mesh
266+
type(ESMF_MeshLoc), intent(in) :: meshloc
267+
type(ESMF_Field), intent(out) :: field
268+
integer, intent(out) :: rc
269+
270+
! local variables
271+
character(len=*), parameter :: subname = '(med_field_info_esmf_fieldcreate)'
272+
! ----------------------------------------------
273+
274+
rc = ESMF_SUCCESS
275+
276+
if (field_info%n_ungridded > 0) then
277+
field = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, meshloc=meshloc, &
278+
name=field_info%name, &
279+
ungriddedLbound=field_info%ungridded_lbound, &
280+
ungriddedUbound=field_info%ungridded_ubound, &
281+
gridToFieldMap=[field_info%n_ungridded+1], &
282+
rc=rc)
283+
if (chkerr(rc,__LINE__,u_FILE_u)) return
284+
else
285+
field = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, meshloc=meshloc, &
286+
name=field_info%name, &
287+
rc=rc)
288+
if (chkerr(rc,__LINE__,u_FILE_u)) return
289+
end if
290+
291+
end subroutine med_field_info_esmf_fieldcreate
292+
225293
end module med_field_info_mod

mediator/med_methods_mod.F90

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ module med_methods_mod
1515
use med_constants_mod , only : czero => med_constants_czero
1616
use med_constants_mod , only : spval_init => med_constants_spval_init
1717
use med_utils_mod , only : ChkErr => med_utils_ChkErr
18-
use med_field_info_mod , only : med_field_info_type
18+
use med_field_info_mod , only : med_field_info_type, med_field_info_esmf_fieldcreate
1919
use shr_log_mod , only : shr_log_error
2020
implicit none
2121
private
@@ -237,7 +237,7 @@ subroutine med_methods_FB_init(FBout, flds_scalar_name, field_info_array, FBgeom
237237
use ESMF , only : ESMF_Field, ESMF_FieldBundle, ESMF_FieldBundleCreate, ESMF_FieldBundleGet
238238
use ESMF , only : ESMF_State, ESMF_Mesh, ESMF_StaggerLoc, ESMF_MeshLoc
239239
use ESMF , only : ESMF_StateGet, ESMF_FieldGet, ESMF_FieldBundleAdd, ESMF_FieldCreate
240-
use ESMF , only : ESMF_TYPEKIND_R8, ESMF_FIELDSTATUS_EMPTY, ESMF_AttributeGet
240+
use ESMF , only : ESMF_FIELDSTATUS_EMPTY, ESMF_AttributeGet
241241

242242
! input/output variables
243243
type(ESMF_FieldBundle), intent(inout) :: FBout ! output field bundle
@@ -366,20 +366,8 @@ subroutine med_methods_FB_init(FBout, flds_scalar_name, field_info_array, FBgeom
366366
end if
367367

368368
! Create the field
369-
if (field_info_array(n)%n_ungridded > 0) then
370-
field = ESMF_FieldCreate(lmesh, ESMF_TYPEKIND_R8, meshloc=meshloc, &
371-
name=field_info_array(n)%name, &
372-
ungriddedLbound=field_info_array(n)%ungridded_lbound, &
373-
ungriddedUbound=field_info_array(n)%ungridded_ubound, &
374-
gridToFieldMap=[field_info_array(n)%n_ungridded+1], &
375-
rc=rc)
376-
if (chkerr(rc,__LINE__,u_FILE_u)) return
377-
else
378-
field = ESMF_FieldCreate(lmesh, ESMF_TYPEKIND_R8, meshloc=meshloc, &
379-
name=field_info_array(n)%name, &
380-
rc=rc)
381-
if (chkerr(rc,__LINE__,u_FILE_u)) return
382-
end if
369+
call med_field_info_esmf_fieldcreate(field_info_array(n), lmesh, meshloc, field, rc)
370+
if (chkerr(rc,__LINE__,u_FILE_u)) return
383371

384372
! Add the created field to field bundle FBout
385373
if (dbug_flag > 1) then
@@ -720,7 +708,8 @@ end subroutine med_methods_State_reset
720708
subroutine med_methods_FB_average(FB, count, rc)
721709

722710
! ----------------------------------------------
723-
! Set all fields to zero in FB
711+
! Divide all fields in FB by count
712+
! If count is 0, nothing is done
724713
! ----------------------------------------------
725714

726715
use ESMF, only : ESMF_FieldBundle, ESMF_FieldBundleGet, ESMF_Field
@@ -1240,7 +1229,9 @@ subroutine med_methods_FB_accum(FBout, FBin, copy, rc)
12401229

12411230
! ----------------------------------------------
12421231
! Accumulate common field names from FBin to FBout
1243-
! If copy is passed in and true, the this is a copy
1232+
!
1233+
! If copy is passed in and true, then data is copied from FBin to FBout, overwriting
1234+
! values in FBout, rather than accumulating
12441235
! ----------------------------------------------
12451236

12461237
use ESMF , only : ESMF_FieldBundle, ESMF_FieldBundleGet, ESMF_Field

0 commit comments

Comments
 (0)