VariableSpec.F90 Source File


This file depends on

sourcefile~~variablespec.f90~~EfferentGraph sourcefile~variablespec.f90 VariableSpec.F90 sourcefile~actualconnectionpt.f90 ActualConnectionPt.F90 sourcefile~variablespec.f90->sourcefile~actualconnectionpt.f90 sourcefile~actualptvector.f90 ActualPtVector.F90 sourcefile~variablespec.f90->sourcefile~actualptvector.f90 sourcefile~errorhandling.f90 ErrorHandling.F90 sourcefile~variablespec.f90->sourcefile~errorhandling.f90 sourcefile~fielddictionary.f90 FieldDictionary.F90 sourcefile~variablespec.f90->sourcefile~fielddictionary.f90 sourcefile~horizontaldimsspec.f90 HorizontalDimsSpec.F90 sourcefile~variablespec.f90->sourcefile~horizontaldimsspec.f90 sourcefile~keywordenforcer.f90 KeywordEnforcer.F90 sourcefile~variablespec.f90->sourcefile~keywordenforcer.f90 sourcefile~stateitem.f90 StateItem.F90 sourcefile~variablespec.f90->sourcefile~stateitem.f90 sourcefile~stateregistry.f90 StateRegistry.F90 sourcefile~variablespec.f90->sourcefile~stateregistry.f90 sourcefile~ungriddeddims.f90 UngriddedDims.F90 sourcefile~variablespec.f90->sourcefile~ungriddeddims.f90 sourcefile~verticaldimspec.f90 VerticalDimSpec.F90 sourcefile~variablespec.f90->sourcefile~verticaldimspec.f90 sourcefile~verticalgrid.f90 VerticalGrid.F90 sourcefile~variablespec.f90->sourcefile~verticalgrid.f90 sourcefile~virtualconnectionpt.f90 VirtualConnectionPt.F90 sourcefile~variablespec.f90->sourcefile~virtualconnectionpt.f90

Files dependent on this one

sourcefile~~variablespec.f90~~AfferentGraph sourcefile~variablespec.f90 VariableSpec.F90 sourcefile~componentspec.f90 ComponentSpec.F90 sourcefile~componentspec.f90->sourcefile~variablespec.f90 sourcefile~componentspecparser.f90 ComponentSpecParser.F90 sourcefile~componentspecparser.f90->sourcefile~variablespec.f90 sourcefile~fieldspec.f90~2 FieldSpec.F90 sourcefile~fieldspec.f90~2->sourcefile~variablespec.f90 sourcefile~historycollectiongridcomp_private.f90 HistoryCollectionGridComp_private.F90 sourcefile~historycollectiongridcomp_private.f90->sourcefile~variablespec.f90 sourcefile~make_itemspec.f90 make_itemSpec.F90 sourcefile~make_itemspec.f90->sourcefile~variablespec.f90 sourcefile~mapl_generic.f90~2 MAPL_Generic.F90 sourcefile~mapl_generic.f90~2->sourcefile~variablespec.f90 sourcefile~mockitemspec.f90 MockItemSpec.F90 sourcefile~mockitemspec.f90->sourcefile~variablespec.f90 sourcefile~outermetacomponent.f90 OuterMetaComponent.F90 sourcefile~outermetacomponent.f90->sourcefile~variablespec.f90 sourcefile~servicespec.f90 ServiceSpec.F90 sourcefile~servicespec.f90->sourcefile~variablespec.f90 sourcefile~statespec.f90 StateSpec.F90 sourcefile~statespec.f90->sourcefile~variablespec.f90 sourcefile~test_modelverticalgrid.pf Test_ModelVerticalGrid.pf sourcefile~test_modelverticalgrid.pf->sourcefile~variablespec.f90 sourcefile~variablespecvector.f90 VariableSpecVector.F90 sourcefile~variablespecvector.f90->sourcefile~variablespec.f90

Source Code

#include "MAPL_Generic.h"

module mapl3g_VariableSpec

   use mapl3g_UngriddedDims
   use mapl3g_VerticalDimSpec
   use mapl3g_HorizontalDimsSpec
   use mapl3g_VirtualConnectionPt
   use mapl3g_ActualConnectionPt
   use mapl3g_VerticalGrid
   use mapl_KeywordEnforcerMod
   use mapl3g_ActualPtVector
   use mapl_ErrorHandling
   use mapl3g_StateRegistry
   use mapl3g_StateItem
   use mapl3g_EsmfRegridder, only: EsmfRegridderParam
   use mapl3g_FieldDictionary
   use esmf
   use gFTL2_StringVector
   use nuopc

   implicit none
   private

   public :: VariableSpec

   ! This type provides components that might be needed for _any_
   ! state item.  This is largely to support legacy interfaces, but it
   ! also allows us to defer interpretation until after user
   ! setservices() have run.
   type VariableSpec
      ! Mandatory values:
      type(ESMF_StateIntent_Flag) :: state_intent
      character(:), allocatable :: short_name
      type(ESMF_TypeKind_Flag) :: typekind = ESMF_TYPEKIND_R4
      type(EsmfRegridderParam) :: regrid_param

      ! Metadata
      character(:), allocatable :: standard_name
      type(ESMF_StateItem_Flag) :: itemtype = MAPL_STATEITEM_FIELD
      type(StringVector), allocatable :: service_items
      character(:), allocatable :: units
      character(:), allocatable :: substate
      real, allocatable :: default_value
      type(StringVector) :: attributes
      integer, allocatable :: bracket_size

      ! Geometry
      type(ESMF_Geom), allocatable :: geom
      type(VerticalDimSpec) :: vertical_dim_spec = VERTICAL_DIM_UNKNOWN ! none, center, edge
      type(HorizontalDimsSpec) :: horizontal_dims_spec = HORIZONTAL_DIMS_GEOM ! none, geom
      type(UngriddedDims) :: ungridded_dims
      type(StringVector) :: dependencies
   contains
      procedure :: make_virtualPt
      procedure :: make_dependencies
      procedure :: initialize
      procedure, private :: set_regrid_param_
   end type VariableSpec

   interface VariableSpec
      module procedure :: new_VariableSpec
   end interface VariableSpec

contains

   function new_VariableSpec( &
        state_intent, short_name, unusable, standard_name, geom, &
        units, substate, itemtype, typekind, vertical_dim_spec, ungridded_dims, default_value, &
        service_items, attributes, &
        bracket_size, &
        dependencies, regrid_param) result(var_spec)

      type(VariableSpec) :: var_spec
      type(ESMF_StateIntent_Flag), intent(in) :: state_intent
      character(*), intent(in) :: short_name
      ! Optional args:
      class(KeywordEnforcer), optional, intent(in) :: unusable
      character(*), optional, intent(in) :: standard_name
      type(ESMF_Geom), optional, intent(in) :: geom
      type(ESMF_StateItem_Flag), optional, intent(in) :: itemtype
      type(StringVector), optional :: service_items
      character(*), optional, intent(in) :: units
      character(*), optional, intent(in) :: substate
      type(ESMF_TypeKind_Flag), optional, intent(in) :: typekind
      type(VerticalDimSpec), optional, intent(in) :: vertical_dim_spec
      type(UngriddedDims), optional, intent(in) :: ungridded_dims
      real, optional, intent(in) :: default_value
      type(StringVector), optional, intent(in) :: attributes
      integer, optional, intent(in) :: bracket_size
      type(StringVector), optional, intent(in) :: dependencies
      type(EsmfRegridderParam), optional, intent(in) :: regrid_param

      type(ESMF_RegridMethod_Flag), allocatable :: regrid_method
      integer :: status

      var_spec%state_intent = state_intent
      var_spec%short_name = short_name

#if defined(_SET_OPTIONAL)
#  undef _SET_OPTIONAL
#endif
#define _SET_OPTIONAL(attr) if (present(attr)) var_spec%attr = attr

      _SET_OPTIONAL(standard_name)
      _SET_OPTIONAL(geom)
      _SET_OPTIONAL(itemtype)
      _SET_OPTIONAL(units)
      _SET_OPTIONAL(substate)
      _SET_OPTIONAL(typekind)
      _SET_OPTIONAL(service_items)
      _SET_OPTIONAL(default_value)
      _SET_OPTIONAL(vertical_dim_spec)
      _SET_OPTIONAL(ungridded_dims)
      _SET_OPTIONAL(attributes)
      _SET_OPTIONAL(bracket_size)
      _SET_OPTIONAL(dependencies)

      call var_spec%set_regrid_param_(regrid_param)

      _UNUSED_DUMMY(unusable)
   end function new_VariableSpec


   ! Failing to find attributes in config is ok - they are
   ! left uninitialized. Constistency and sufficiency checks are
   ! relegated to the various StateItemSpec subclasses.
   subroutine initialize(this, config)
      class(VariableSpec), intent(out) :: this
      type(ESMF_HConfig), intent(in) :: config

      this%standard_name = ESMF_HConfigAsString(config,keyString='standard_name')
      this%itemtype = get_itemtype(config)
      this%units = ESMF_HConfigAsString(config,keyString='units')

   contains

      function get_itemtype(config) result(itemtype)
         type(ESMF_StateItem_Flag) :: itemtype
         type(ESMF_HConfig), intent(in) :: config

         character(:), allocatable :: itemtype_as_string
         integer :: status

         itemtype = MAPL_STATEITEM_FIELD ! default
         if (.not. ESMF_HConfigIsDefined(config,keyString='itemtype')) return

         itemtype_as_string = ESMF_HConfigAsString(config,keyString='itemtype',rc=status)
         if (status /= 0) then
            itemtype = MAPL_STATEITEM_UNKNOWN
            return
         end if

         select case (itemtype_as_string)
         case ('field')
            itemtype = MAPL_STATEITEM_FIELD
         case ('bundle')
            itemtype = MAPL_STATEITEM_FIELDBUNDLE
         case ('state')
            itemtype = MAPL_STATEITEM_STATE
         case ('service_provider')
            itemtype = MAPL_STATEITEM_SERVICE_PROVIDER
         case ('service_subcriber')
            itemtype = MAPL_STATEITEM_SERVICE_SUBSCRIBER
         case ('wildcard')
            itemtype = MAPL_STATEITEM_WILDCARD
         case ('bracket')
            itemtype = MAPL_STATEITEM_BRACKET
         case default
            itemtype = MAPL_STATEITEM_UNKNOWN
         end select

      end function get_itemtype

   end subroutine initialize

   function make_virtualPt(this) result(v_pt)
      type(VirtualConnectionPt) :: v_pt
      class(VariableSpec), intent(in) :: this
      v_pt = VirtualConnectionPt(this%state_intent, this%short_name)
      if (allocated(this%substate)) then
         v_pt = v_pt%add_comp_name(this%substate)
      end if
   end function make_virtualPt

   subroutine fill_units(this, units, rc)
      class(VariableSpec), intent(in) :: this
      character(:), allocatable, intent(out) :: units
      integer, optional, intent(out) :: rc

      character(len=ESMF_MAXSTR) :: canonical_units
      integer :: status

      ! Only fill if not already specified
      if (allocated(this%units)) then
         units = this%units
         _RETURN(_SUCCESS)
      end if

      ! Only fill if standard name is provided
      _RETURN_UNLESS(allocated(this%standard_name))

      call NUOPC_FieldDictionaryGetEntry(this%standard_name, canonical_units, status)
      _ASSERT(status == ESMF_SUCCESS,'Units not found for standard name: <'//this%standard_name//'>')
      units = trim(canonical_units)

      _RETURN(_SUCCESS)
   end subroutine fill_units

   function make_dependencies(this, rc) result(dependencies)
      type(ActualPtVector) :: dependencies
      class(VariableSpec), intent(in) :: this
      integer, optional, intent(out) :: rc

      integer :: status
      integer :: i
      type(ActualConnectionPt) :: a_pt

      dependencies = ActualPtVector()
      do i = 1, this%dependencies%size()
         a_pt = ActualConnectionPt(VirtualConnectionPt(ESMF_STATEINTENT_EXPORT, this%dependencies%of(i)))
         call dependencies%push_back(a_pt)
      end do

      _RETURN(_SUCCESS)
   end function make_dependencies

   subroutine set_regrid_param_(this, regrid_param)
      class(VariableSpec), intent(inout) :: this
      type(EsmfRegridderParam), optional, intent(in) :: regrid_param

      type(ESMF_RegridMethod_Flag) :: regrid_method
      integer :: status

      if (present(regrid_param)) then
         this%regrid_param = regrid_param
         return
      end if

      ! if (NUOPC_FieldDictionaryHasEntry(this%standard_name, rc=status)) then
      !    call NUOPC_FieldDictionaryGetEntry(this%standard_name, regrid_method, rc=status)
      !    if (status==ESMF_SUCCESS) then
      !       this%regrid_param = EsmfRegridderParam(regridmethod=regrid_method)
      !       return
      !    end if
      ! end if
      regrid_method = get_regrid_method_from_field_dict_(this%standard_name, rc=status)
      if (status==ESMF_SUCCESS) then
         this%regrid_param = EsmfRegridderParam(regridmethod=regrid_method)
         return
      end if

      this%regrid_param = EsmfRegridderParam() ! last resort - use default regrid method
   end subroutine set_regrid_param_

   function get_regrid_method_from_field_dict_(stdname, rc) result(regrid_method)
      type(ESMF_RegridMethod_Flag) :: regrid_method
      character(:), allocatable, intent(in) :: stdname
      integer, optional, intent(out) :: rc

      character(len=*), parameter :: field_dictionary_file = "field_dictionary.yml"
      type(FieldDictionary) :: field_dict
      logical :: file_exists
      integer :: status

      inquire(file=trim(field_dictionary_file), exist=file_exists)
      if (.not. file_exists) then
         rc = _FAILURE
         return
      end if

      field_dict = FieldDictionary(filename=field_dictionary_file, _RC)
      if (.not. allocated(stdname)) then
         rc = _FAILURE
         return
      end if
      regrid_method = field_dict%get_regrid_method(stdname, _RC)

      _RETURN(_SUCCESS)
   end function get_regrid_method_from_field_dict_

end module mapl3g_VariableSpec