Test_ModelVerticalGrid.pf Source File


This file depends on

sourcefile~~test_modelverticalgrid.pf~~EfferentGraph sourcefile~test_modelverticalgrid.pf Test_ModelVerticalGrid.pf sourcefile~actualconnectionpt.f90 ActualConnectionPt.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~actualconnectionpt.f90 sourcefile~componentdriver.f90 ComponentDriver.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~componentdriver.f90 sourcefile~componentdriverptrvector.f90 ComponentDriverPtrVector.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~componentdriverptrvector.f90 sourcefile~componentdrivervector.f90 ComponentDriverVector.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~componentdrivervector.f90 sourcefile~couplerphases.f90 CouplerPhases.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~couplerphases.f90 sourcefile~errorhandling.f90 ErrorHandling.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~errorhandling.f90 sourcefile~esmf_testmethod.f90 ESMF_TestMethod.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~esmf_testmethod.f90 sourcefile~geom_mgr.f90 geom_mgr.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~geom_mgr.f90 sourcefile~griddedcomponentdriver.f90 GriddedComponentDriver.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~griddedcomponentdriver.f90 sourcefile~make_itemspec.f90 make_itemSpec.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~make_itemspec.f90 sourcefile~modelverticalgrid.f90 ModelVerticalGrid.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~modelverticalgrid.f90 sourcefile~multistate.f90 MultiState.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~multistate.f90 sourcefile~stateitemextension.f90 StateItemExtension.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~stateitemextension.f90 sourcefile~stateitemspec.f90 StateItemSpec.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~stateitemspec.f90 sourcefile~stateregistry.f90 StateRegistry.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~stateregistry.f90 sourcefile~variablespec.f90 VariableSpec.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~variablespec.f90 sourcefile~verticaldimspec.f90 VerticalDimSpec.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~verticaldimspec.f90 sourcefile~virtualconnectionpt.f90 VirtualConnectionPt.F90 sourcefile~test_modelverticalgrid.pf->sourcefile~virtualconnectionpt.f90

Source Code

#include "MAPL_TestErr.h"
#include "MAPL_Generic.h"

! We use ESMF_TestMethod rather than basic TestMethod just in case
! there are any implied barriers is the ESMF construction in these
! tests.  E.g., if we end up needing to create nested grid comps.
! Almost certainly, is unnecessary.

module Test_ModelVerticalGrid

   use mapl_ErrorHandling
   use mapl3g_VerticalDimSpec
   use mapl3g_ModelVerticalGrid
   use mapl3g_StateRegistry
   use mapl3g_VariableSpec
   use mapl3g_VirtualConnectionPt
   use mapl3g_ActualConnectionPt
   use mapl3g_StateItemSpec
   use mapl3g_StateItemExtension
   use mapl3g_GriddedComponentDriver
   use mapl3g_ComponentDriver
   use mapl3g_ComponentDriverVector
   use mapl3g_ComponentDriverPtrVector
   use mapl3g_MultiState
   use mapl3g_make_ItemSpec
   use mapl3g_geom_mgr
   use mapl3g_CouplerPhases, only: GENERIC_COUPLER_UPDATE
   use esmf
   ! testing framework
   use ESMF_TestMethod_mod
   use funit

   implicit none (type, external)

   integer, parameter :: IM=6, JM=7, LM=3

   ! Trying to avoid a complex test fixture
   type(StateRegistry), target :: r

contains

   subroutine setup(var_name, vgrid, rc)
      character(*), intent(in) :: var_name
      type(ModelVerticalGrid), intent(out) :: vgrid
      integer, intent(out) :: rc

      type(VerticalDimSpec) :: vertical_dim_spec
      type(ESMF_Geom) :: geom
      type(VirtualConnectionPt) :: v_pt
      type(VariableSpec) :: var_spec
      class(StateItemSpec), allocatable :: fld_spec
      type(StateItemExtension), pointer :: extension
      class(StateItemSpec), pointer :: spec
      integer :: status

      select case (var_name)
      case ("PLE")
         vertical_dim_spec = VERTICAL_DIM_EDGE
      case ("PL")
         vertical_dim_spec = VERTICAL_DIM_CENTER
      case default
         _FAIL("var_name should be one of PLE/PL, not" // trim(var_name))
      end select

      rc = 0
      ! Inside user "set_geom" phase.
      geom = make_geom(_RC)
      vgrid = ModelVerticalGrid(standard_name="air_pressure", units="hPa", num_levels=LM)
      call vgrid%add_short_name(edge="PLE", center="PL")

      ! inside OuterMeta
      r = StateRegistry("dyn")
      call vgrid%set_registry(r) ! MAPL_SetVerticalGrid(...)

      v_pt = VirtualConnectionPt(state_intent="export", short_name=var_name)
      var_spec = VariableSpec(&
           short_name=var_name, &
           state_intent=ESMF_STATEINTENT_EXPORT, &
           standard_name="air_pressure", &
           units="hPa", &
           vertical_dim_spec=vertical_dim_spec, &
           default_value=3.)
      allocate(fld_spec, source=make_itemSpec(var_spec, r, rc=status))
      _VERIFY(status)
      call fld_spec%set_geometry(geom=geom, vertical_grid=vgrid, _RC)

      call r%add_primary_spec(v_pt, fld_spec)

      extension => r%get_primary_extension(v_pt, _RC)
      spec => extension%get_spec()
      call spec%set_active()
      call spec%create(_RC)
      call spec%allocate(_RC)
   end subroutine setup

   function make_geom(rc) result(geom)
      integer, intent(out) :: rc
      type(ESMF_Geom) :: geom
      integer :: status
      type(ESMF_HConfig) :: hconfig
      type(GeomManager), pointer :: geom_mgr
      type(MaplGeom), pointer :: mapl_geom

      rc = 0
      geom_mgr => get_geom_manager()
      hconfig = ESMF_HConfigCreate(content="{class: latlon, im_world: 6, jm_world: 7, pole: PC, dateline: DC}", _RC)
      mapl_geom => geom_mgr%get_mapl_geom(hconfig, _RC)
      geom = mapl_geom%get_geom()
   end function make_geom

   @test
   subroutine test_num_levels()
      type(ModelVerticalGrid) :: vgrid
      integer :: num_levels

      num_levels = 10
      vgrid = ModelVerticalGrid(standard_name="height", units="m", num_levels=num_levels)
      @assert_that(vgrid%get_num_levels(), is(num_levels))
   end subroutine test_num_levels

   @test(type=ESMF_TestMethod, npes=[1])
   subroutine test_created_fields_have_num_levels(this)
      class(ESMF_TestMethod), intent(inout) :: this
      type(ModelVerticalGrid) :: vgrid
      integer :: rank
      integer, allocatable :: localElementCount(:)
      type(VirtualConnectionPt) :: ple_pt
      class(StateItemSpec), pointer :: spec
      type(MultiState) :: multi_state
      type(StateItemExtension), pointer :: extension
      type(ESMF_Field) :: ple
      integer :: rc, status

      call setup("PLE", vgrid, _RC)

      ple_pt = VirtualConnectionPt(state_intent="export", short_name="PLE")
      extension => r%get_primary_extension(ple_pt, _RC)
      spec => extension%get_spec()

      multi_state = MultiState()
      call spec%add_to_state(multi_state, ActualConnectionPt(ple_pt), _RC)
      call ESMF_StateGet(multi_state%exportState, itemName="PLE", field=ple, _RC)
      call ESMF_FieldGet(ple, rank=rank, _RC)
      allocate(localElementCount(rank))
      call ESMF_FieldGet(ple, localElementCount=localElementCount, _RC)
      @assert_that(localElementCount, is(equal_to([IM,JM,LM+1])))
      _UNUSED_DUMMY(this)
   end subroutine test_created_fields_have_num_levels

   @test(type=ESMF_TestMethod, npes=[1])
   ! Request the specific coordinate corresponding particular geom/unit.
   ! In this case we start with one that already exists.  A later test
   ! should force extensions.
   subroutine test_get_coordinate_field_simple(this)
      class(ESMF_TestMethod), intent(inout) :: this
      type(ModelVerticalGrid) :: vgrid
      type(GriddedComponentDriver), pointer :: coupler
      type(ESMF_Field) :: vcoord
      type(ESMF_Geom) :: geom
      integer :: rc, status
      real(ESMF_KIND_R4), pointer :: a(:,:,:)

      call setup("PLE", vgrid, _RC)
      geom = make_geom(_RC)

      call vgrid%get_coordinate_field( &
           vcoord, coupler, &
           standard_name="air_pressure", &
           geom=geom, &
           typekind=ESMF_TYPEKIND_R4, &
           units="hPa", &
           vertical_dim_spec=VERTICAL_DIM_EDGE, &
           _RC)
      @assert_that(associated(coupler), is(false()))

      call ESMF_FieldGet(vcoord, fArrayPtr=a, _RC)
      @assert_that(a, every_item(is(equal_to(3.))))
      _UNUSED_DUMMY(this)
   end subroutine test_get_coordinate_field_simple

   @test(type=ESMF_TestMethod, npes=[1])
   ! Request the specific coordinate corresponding particular geom/unit.
   ! Here we request different units which should return a coordinate
   ! scaled by 100 (hPa = 100 Pa)
   subroutine test_get_coordinate_field_change_units_edge(this)
      class(ESMF_TestMethod), intent(inout) :: this
      type(ModelVerticalGrid) :: vgrid
      type(ESMF_Field) :: vcoord
      type(ESMF_Geom) :: geom
      integer :: status
      real(ESMF_KIND_R4), pointer :: a(:,:,:)
      type(ComponentDriverPtrVector) :: couplers
      type(ComponentDriverPtr) :: driver
      type(GriddedComponentDriver), pointer :: coupler
      integer :: i, rc

      call setup("PLE", vgrid, _RC)
      geom = make_geom(_RC)

      call vgrid%get_coordinate_field( &
           vcoord, coupler, &
           standard_name="air_pressure", &
           geom=geom, &
           typekind=ESMF_TYPEKIND_R4, &
           units="Pa", &
           vertical_dim_spec=VERTICAL_DIM_EDGE, &
           _RC)
      @assert_that(associated(coupler), is(true()))

      call r%allocate(_RC)

      call ESMF_FieldGet(vcoord, fArrayPtr=a, _RC)
      ! usually update is called on imports, but here we don't have an import handy,
      ! so we force updates on all export couplers in registry r.
      couplers = r%get_export_couplers()
      do i = 1, couplers%size()
         driver = couplers%of(i)
         call driver%ptr%initialize(_RC)
         call driver%ptr%run(phase_idx=GENERIC_COUPLER_UPDATE, _RC)
      end do
      @assert_that(shape(a), is(equal_to([IM, JM, LM+1])))
      @assert_that(a, every_item(is(equal_to(300.))))
      _UNUSED_DUMMY(this)
   end subroutine test_get_coordinate_field_change_units_edge

   @test(type=ESMF_TestMethod, npes=[1])
   ! Request the specific coordinate corresponding particular geom/unit.
   ! Here we request different units which should return a coordinate
   ! scaled by 100 (hPa = 100 Pa)
   subroutine test_get_coordinate_field_change_units_center(this)
      class(ESMF_TestMethod), intent(inout) :: this
      type(ModelVerticalGrid) :: vgrid
      type(ESMF_Field) :: vcoord
      type(ESMF_Geom) :: geom
      integer :: status
      real(ESMF_KIND_R4), pointer :: a(:,:,:)
      type(ComponentDriverPtrVector) :: couplers
      type(ComponentDriverPtr) :: driver
      type(GriddedComponentDriver), pointer :: coupler
      integer :: i, rc

      call setup("PL", vgrid, _RC)
      geom = make_geom(_RC)

      call vgrid%get_coordinate_field( &
           vcoord, coupler, &
           standard_name="air_pressure", &
           geom=geom, &
           typekind=ESMF_TYPEKIND_R4, units="Pa", &
           vertical_dim_spec=VERTICAL_DIM_CENTER, &
           _RC)
      @assert_that(associated(coupler), is(true()))

      call r%allocate(_RC)

      call ESMF_FieldGet(vcoord, fArrayPtr=a, _RC)
      ! usually update is called on imports, but here we don't have an import handy,
      ! so we force updates on all export couplers in registry r.
      couplers = r%get_export_couplers()
      do i = 1, couplers%size()
         driver = couplers%of(i)
         call driver%ptr%initialize(_RC)
         call driver%ptr%run(phase_idx=GENERIC_COUPLER_UPDATE, _RC)
      end do
      @assert_that(shape(a), is(equal_to([IM, JM, LM])))
      @assert_that(a, every_item(is(equal_to(300.))))
      _UNUSED_DUMMY(this)
   end subroutine test_get_coordinate_field_change_units_center

end module Test_ModelVerticalGrid