Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 111 additions & 43 deletions mediator/med_field_info_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ 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 ESMF , only : ESMF_MAXSTR, ESMF_SUCCESS, ESMF_TYPEKIND_R8
use ESMF , only : ESMF_Field, ESMF_State, ESMF_StateGet
use ESMF , only : ESMF_Mesh, ESMF_MeshLoc
use ESMF , only : ESMF_FieldCreate, ESMF_FieldGet
use med_utils_mod , only : ChkErr => med_utils_ChkErr
use shr_log_mod , only : shr_log_error
use wtracers_mod , only : wtracers_is_wtracer_field
Expand All @@ -18,8 +20,11 @@ module med_field_info_mod
! Public methods
!-----------------------------------------------

! Create a single field
public :: med_field_info_create
! Create a single field_info object from direct specification of values
public :: med_field_info_create_directly

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could create an interface and call these interchangably

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. I personally find that to often be more confusing than helpful except in very limited cases such as supporting multiple data types or array ranks: In cases where there is a completely different interface, my experience is that having a generic interface adds little if any value, and just makes it harder to figure out what's actually being called when trying to trace the code.

That said, I'm open to doing this if others prefer it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it's not always useful or prudent to do this and I leave it to your discretion.

! Create a single field_info object from information in an ESMF_Field
public :: med_field_info_create_from_field

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

! Create an ESMF Field (using ESMF_FieldCreate) based on a field_info object
public :: med_field_info_esmf_fieldcreate

!-----------------------------------------------
! Types
!-----------------------------------------------
Expand All @@ -48,8 +56,8 @@ module med_field_info_mod
contains
!================================================================================

function med_field_info_create(name, ungridded_lbound, ungridded_ubound, rc) result(field_info)
! Create a single field
function med_field_info_create_directly(name, ungridded_lbound, ungridded_ubound, rc) result(field_info)
! Create a single field_info object from direct specification of values

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

! local variables
integer :: n_ungridded
character(len=*), parameter :: subname = '(med_field_info_create)'
character(len=*), parameter :: subname = '(med_field_info_create_directly)'
! ----------------------------------------------

rc = ESMF_SUCCESS
Expand Down Expand Up @@ -95,7 +103,61 @@ function med_field_info_create(name, ungridded_lbound, ungridded_ubound, rc) res
field_info%n_ungridded = 0
end if

end function med_field_info_create
end function med_field_info_create_directly

!-----------------------------------------------------------------------------

function med_field_info_create_from_field(field, name, rc) result(field_info)
! Create a single field_info object from information in an ESMF_Field

! input/output variables
! We get information other than the name from this ESMF_Field object
type(ESMF_Field), intent(in) :: field

! We should be able to get the name from the field, but in all current uses of this
! function, we already have the name available, so it's easy enough to just pass it in
! rather than making this function query it again. If future users did not already
! have the name readily available, we could either change this to optional or remove
! it entirely and just always get the name from querying the field.
character(len=*), intent(in) :: name

integer, intent(out) :: rc
type(med_field_info_type) :: field_info ! function result

! local variables
integer :: n_ungridded
integer, allocatable :: ungridded_lbound(:)
integer, allocatable :: ungridded_ubound(:)

character(len=*), parameter :: subname = '(med_field_info_create_from_field)'
! ----------------------------------------------

rc = ESMF_SUCCESS

call ESMF_FieldGet(field, ungriddedDimCount=n_ungridded, rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return

if (n_ungridded == 0) then
field_info = med_field_info_create_directly( &
name=name, &
rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return
else
allocate(ungridded_lbound(n_ungridded))
allocate(ungridded_ubound(n_ungridded))
call ESMF_FieldGet(field, &
ungriddedLBound=ungridded_lbound, ungriddedUBound=ungridded_ubound, rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return
field_info = med_field_info_create_directly( &
name=name, &
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 function med_field_info_create_from_field

!-----------------------------------------------------------------------------

Expand Down Expand Up @@ -134,15 +196,15 @@ subroutine med_field_info_array_from_names_wtracers(field_names, field_info_arra
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( &
field_info_array(i) = med_field_info_create_directly( &
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( &
field_info_array(i) = med_field_info_create_directly( &
name=field_names(i), &
rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return
Expand All @@ -168,10 +230,6 @@ subroutine med_field_info_array_from_state(state, field_info_array, rc)
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)'
! ----------------------------------------------

Expand All @@ -188,38 +246,48 @@ subroutine med_field_info_array_from_state(state, field_info_array, rc)
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)
field_info_array(i) = med_field_info_create_from_field( &
field=field, &
name=field_names(i), &
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

!-----------------------------------------------------------------------------

subroutine med_field_info_esmf_fieldcreate(field_info, mesh, meshloc, field, rc)
! Create an ESMF Field (using ESMF_FieldCreate) based on a field_info object

! input/output variables
type(med_field_info_type), intent(in) :: field_info
type(ESMF_Mesh), intent(in) :: mesh
type(ESMF_MeshLoc), intent(in) :: meshloc
type(ESMF_Field), intent(out) :: field
integer, intent(out) :: rc

! local variables
character(len=*), parameter :: subname = '(med_field_info_esmf_fieldcreate)'
! ----------------------------------------------

rc = ESMF_SUCCESS

if (field_info%n_ungridded > 0) then
field = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, meshloc=meshloc, &
name=field_info%name, &
ungriddedLbound=field_info%ungridded_lbound, &
ungriddedUbound=field_info%ungridded_ubound, &
gridToFieldMap=[field_info%n_ungridded+1], &
rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return
else
field = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, meshloc=meshloc, &
name=field_info%name, &
rc=rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return
end if

end subroutine med_field_info_esmf_fieldcreate

end module med_field_info_mod
27 changes: 9 additions & 18 deletions mediator/med_methods_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +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 med_field_info_mod , only : med_field_info_type, med_field_info_esmf_fieldcreate
use shr_log_mod , only : shr_log_error
implicit none
private
Expand Down Expand Up @@ -237,7 +237,7 @@ subroutine med_methods_FB_init(FBout, flds_scalar_name, field_info_array, FBgeom
use ESMF , only : ESMF_Field, ESMF_FieldBundle, ESMF_FieldBundleCreate, ESMF_FieldBundleGet
use ESMF , only : ESMF_State, ESMF_Mesh, ESMF_StaggerLoc, ESMF_MeshLoc
use ESMF , only : ESMF_StateGet, ESMF_FieldGet, ESMF_FieldBundleAdd, ESMF_FieldCreate
use ESMF , only : ESMF_TYPEKIND_R8, ESMF_FIELDSTATUS_EMPTY, ESMF_AttributeGet
use ESMF , only : ESMF_FIELDSTATUS_EMPTY, ESMF_AttributeGet

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

! 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
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
call med_field_info_esmf_fieldcreate(field_info_array(n), lmesh, meshloc, field, rc)
if (chkerr(rc,__LINE__,u_FILE_u)) return

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

! ----------------------------------------------
! Set all fields to zero in FB
! Divide all fields in FB by count
! If count is 0, nothing is done
! ----------------------------------------------

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

! ----------------------------------------------
! Accumulate common field names from FBin to FBout
! If copy is passed in and true, the this is a copy
!
! If copy is passed in and true, then data is copied from FBin to FBout, overwriting
! values in FBout, rather than accumulating
! ----------------------------------------------

use ESMF , only : ESMF_FieldBundle, ESMF_FieldBundleGet, ESMF_Field
Expand Down
Loading