Test_RegridderManager.pf Source File


This file depends on

sourcefile~~test_regriddermanager.pf~~EfferentGraph sourcefile~test_regriddermanager.pf Test_RegridderManager.pf sourcefile~base_base.f90 Base_Base.F90 sourcefile~test_regriddermanager.pf->sourcefile~base_base.f90 sourcefile~esmf_testmethod.f90 ESMF_TestMethod.F90 sourcefile~test_regriddermanager.pf->sourcefile~esmf_testmethod.f90 sourcefile~geom_mgr.f90 geom_mgr.F90 sourcefile~test_regriddermanager.pf->sourcefile~geom_mgr.f90 sourcefile~regridder_mgr.f90 regridder_mgr.F90 sourcefile~test_regriddermanager.pf->sourcefile~regridder_mgr.f90 sourcefile~constants.f90 Constants.F90 sourcefile~base_base.f90->sourcefile~constants.f90 sourcefile~keywordenforcer.f90 KeywordEnforcer.F90 sourcefile~base_base.f90->sourcefile~keywordenforcer.f90 sourcefile~mapl_range.f90 MAPL_Range.F90 sourcefile~base_base.f90->sourcefile~mapl_range.f90 sourcefile~maplgrid.f90 MaplGrid.F90 sourcefile~base_base.f90->sourcefile~maplgrid.f90 sourcefile~esmf_testcase.f90 ESMF_TestCase.F90 sourcefile~esmf_testmethod.f90->sourcefile~esmf_testcase.f90 sourcefile~esmf_testparameter.f90 ESMF_TestParameter.F90 sourcefile~esmf_testmethod.f90->sourcefile~esmf_testparameter.f90 sourcefile~geomspec.f90 GeomSpec.F90 sourcefile~geom_mgr.f90->sourcefile~geomspec.f90 sourcefile~geomutilities.f90 GeomUtilities.F90 sourcefile~geom_mgr.f90->sourcefile~geomutilities.f90 sourcefile~dynamicmask.f90 DynamicMask.F90 sourcefile~regridder_mgr.f90->sourcefile~dynamicmask.f90 sourcefile~regriddermanager.f90 RegridderManager.F90 sourcefile~regridder_mgr.f90->sourcefile~regriddermanager.f90 sourcefile~regridderspec.f90~2 RegridderSpec.F90 sourcefile~regridder_mgr.f90->sourcefile~regridderspec.f90~2 sourcefile~internalconstants.f90 InternalConstants.F90 sourcefile~constants.f90->sourcefile~internalconstants.f90 sourcefile~mathconstants.f90 MathConstants.F90 sourcefile~constants.f90->sourcefile~mathconstants.f90 sourcefile~physicalconstants.f90 PhysicalConstants.F90 sourcefile~constants.f90->sourcefile~physicalconstants.f90 sourcefile~dynamicmask.f90->sourcefile~base_base.f90 sourcefile~errorhandling.f90 ErrorHandling.F90 sourcefile~dynamicmask.f90->sourcefile~errorhandling.f90 sourcefile~esmf_testcase.f90->sourcefile~esmf_testparameter.f90 sourcefile~geomutilities.f90->sourcefile~errorhandling.f90 sourcefile~mapl_exceptionhandling.f90 MAPL_ExceptionHandling.F90 sourcefile~mapl_range.f90->sourcefile~mapl_exceptionhandling.f90 sourcefile~maplgrid.f90->sourcefile~constants.f90 sourcefile~maplgrid.f90->sourcefile~keywordenforcer.f90 sourcefile~maplgrid.f90->sourcefile~errorhandling.f90 sourcefile~mapl_sort.f90 MAPL_Sort.F90 sourcefile~maplgrid.f90->sourcefile~mapl_sort.f90 sourcefile~pflogger_stub.f90 pflogger_stub.F90 sourcefile~maplgrid.f90->sourcefile~pflogger_stub.f90 sourcefile~regriddermanager.f90->sourcefile~regridderspec.f90~2 sourcefile~regriddermanager.f90->sourcefile~errorhandling.f90 sourcefile~esmfregridderfactory.f90 EsmfRegridderFactory.F90 sourcefile~regriddermanager.f90->sourcefile~esmfregridderfactory.f90 sourcefile~nullregridder.f90 NullRegridder.F90 sourcefile~regriddermanager.f90->sourcefile~nullregridder.f90 sourcefile~regridderfactory.f90 RegridderFactory.F90 sourcefile~regriddermanager.f90->sourcefile~regridderfactory.f90 sourcefile~regridderfactoryvector.f90 RegridderFactoryVector.F90 sourcefile~regriddermanager.f90->sourcefile~regridderfactoryvector.f90 sourcefile~regridderspecvector.f90 RegridderSpecVector.F90 sourcefile~regriddermanager.f90->sourcefile~regridderspecvector.f90 sourcefile~regriddervector.f90 RegridderVector.F90 sourcefile~regriddermanager.f90->sourcefile~regriddervector.f90 sourcefile~regridderspec.f90~2->sourcefile~geom_mgr.f90 sourcefile~regridderparam.f90 RegridderParam.F90 sourcefile~regridderspec.f90~2->sourcefile~regridderparam.f90

Source Code

#define _VERIFY(status) \
   if(status /= 0) then; \
      call assert_that(status, is(0), location=SourceLocation(__FILE__,__LINE__)); \
      if (anyExceptions()) return; \
   endif
#define _RC rc=status); _VERIFY(status

! Helper procedures
#define _SUCCESS 0
#define _RC2 rc=status); _VERIFY2(status
#define _VERIFY2(status)  if (status /= 0) then; if (present(rc)) rc=status; return; endif
#define _RETURN(status) if (present(rc)) rc=status; return

module Test_RegridderManager
   use pfunit
   use mapl3g_regridder_mgr
   use mapl3g_geom_mgr
   use mapl_BaseMod, only: MAPL_UNDEF
   use esmf_TestMethod_mod ! mapl
   use esmf
   implicit none

contains

   ! Helper procedures
   ! TODO add error handling to helper procedures
   
   function make_geom(geom_mgr, hconfig, rc) result(geom)
      type(ESMF_Geom) :: geom
      type(GeomManager), intent(inout) :: geom_mgr
      type(ESMF_HConfig), optional, intent(in) :: hconfig
      integer, optional, intent(out) :: rc

      type(MaplGeom), pointer :: mapl_geom
      integer :: status
      type(ESMF_HConfig) :: hconfig_

      hconfig_ = ESMF_HConfigCreate(content="{class: latlon, im_world: 12, jm_world: 13, pole: PC, dateline: DC, nx: 1, ny: 1}", &
           _RC2)
      if (present(hconfig)) hconfig_ = hconfig

      mapl_geom => geom_mgr%get_mapl_geom(hconfig_, _RC2)
      geom = mapl_geom%get_geom()

      _RETURN(_SUCCESS)
   end function make_geom

   function make_field(geom, name, value, lm, rc) result(field)
      type(ESMF_Field) :: field
      type(ESMF_Geom), intent(in) :: geom
      character(*), intent(in) :: name
      real(kind=ESMF_KIND_R4), intent(in) :: value
      integer, optional, intent(in) :: lm
      integer, optional, intent(out) :: rc

      real(kind=ESMF_KIND_R4), pointer :: x(:,:)
      real(kind=ESMF_KIND_R4), pointer :: x_3d(:,:,:)
      integer :: status

      field = ESMF_FieldEmptyCreate(name=name, _RC2)
      call ESMF_FieldEmptySet(field, geom, _RC2)
      if (present(lm)) then
         call ESMF_FieldEmptyComplete(field, typekind=ESMF_TYPEKIND_R4, ungriddedLBound=[1], ungriddedUBound=[lm], _RC2)
         call ESMF_FieldGet(field, farrayptr=x_3d,_RC2)
         x_3d = value
      else
         call ESMF_FieldEmptyComplete(field, typekind=ESMF_TYPEKIND_R4, _RC2)
         call ESMF_FieldGet(field, farrayptr=x, _RC2)
         x = value
      end if

      _RETURN(_SUCCESS)
   end function make_field

   @test(type=ESMF_TestMethod, npes=[1])
   ! Just execute a series of plausible commands and ensure that no
   ! failures are indicated Regrid a constant field onto identical
   ! geometry should not change any values.
   subroutine test_basic(this)
      class(ESMF_TestMethod), intent(inout) :: this
      type(GeomManager) :: geom_mgr
      type(RegridderManager) :: regridder_mgr
      type(RegridderSpec) :: regridder_spec
      integer :: status
      class(Regridder), pointer :: my_regridder
      type(ESMF_Geom) :: geom

      type(ESMF_Field) :: f1, f2
      real(kind=ESMF_KIND_R4), pointer :: x(:,:)


      geom_mgr = GeomManager()
      regridder_mgr = RegridderManager()

      geom = make_geom(geom_mgr, _RC)

      ! use default esmf regrid parameters: method, zero region, etc
      regridder_spec = RegridderSpec(EsmfRegridderParam(), geom, geom)

      my_regridder => regridder_mgr%get_regridder(regridder_spec, _RC)

      f1 = make_field(geom, 'f1', value=3._ESMF_KIND_R4, _RC)
      f2 = make_field(geom, 'f2', value=0._ESMF_KIND_R4, _RC)

      call my_regridder%regrid(f1, f2, _RC)
      call ESMF_FieldGet(f2, farrayptr=x, _RC)

      @assert_that(x, every_item(is(equal_to(3._ESMF_KIND_R4))))

   end subroutine test_basic

   @test(type=ESMF_TestMethod, npes=[1])
   ! Test that identical spec returns same regridder object.  I.e.,
   ! that the manager is properly caching.
   subroutine test_reuse_regridder(this)
      class(ESMF_TestMethod), intent(inout) :: this
      type(GeomManager) :: geom_mgr
      type(RegridderManager), target :: regridder_mgr
      type(RegridderSpec) :: regridder_spec
      integer :: status
      class(Regridder), pointer :: regridder_1, regridder_2
      type(ESMF_Geom) :: geom

      geom_mgr = GeomManager()
      regridder_mgr = RegridderManager()

      geom = make_geom(geom_mgr, _RC)

      regridder_spec = RegridderSpec(EsmfRegridderParam(), geom, geom)

      regridder_1 => regridder_mgr%get_regridder(regridder_spec, _RC)

      regridder_2 => regridder_mgr%get_regridder(regridder_spec, _RC)

      @assertTrue(associated(regridder_2, regridder_1))
   end subroutine test_reuse_regridder

   @test(type=ESMF_TestMethod, npes=[1])
   ! Test that different spec returns different regridder object.  I.e.,
   ! that the manager is properly caching.
   subroutine test_do_not_reuse_regridder(this)
      class(ESMF_TestMethod), intent(inout) :: this
      type(GeomManager) :: geom_mgr
      type(RegridderManager), target :: regridder_mgr
      type(RegridderSpec) :: spec_1, spec_2
      integer :: status
      class(Regridder), pointer :: regridder_1, regridder_2
      type(ESMF_Geom) :: geom_1, geom_2
      type(ESMF_HConfig) :: hconfig

      geom_mgr = GeomManager()
      regridder_mgr = RegridderManager()

      geom_1 = make_geom(geom_mgr, _RC)

      hconfig = ESMF_HConfigCreate(content="{class: latlon, im_world: 12, jm_world: 11, pole: PC, dateline: DC, nx: 1, ny: 1}", _RC)
      geom_2 = make_geom(geom_mgr, hconfig, _RC) ! variant of geom_1

      
      spec_1 = RegridderSpec(EsmfRegridderParam(), geom_1, geom_1)
      regridder_1 => regridder_mgr%get_regridder(spec_1, _RC)

      spec_2 = RegridderSpec(EsmfRegridderParam(), geom_1, geom_2)
      regridder_2 => regridder_mgr%get_regridder(spec_2, _RC)

      @assertFalse(associated(regridder_1, regridder_2))
   end subroutine test_do_not_reuse_regridder

   @test(type=ESMF_TestMethod, npes=[1])
   ! Test realistic regridding.  A checkerboard input field (in
   ! longitude) with constant spacing should produce a constant output
   ! grid with default bilinear regrid method.
   subroutine test_regrid_values(this)
      class(ESMF_TestMethod), intent(inout) :: this
      type(GeomManager) :: geom_mgr
      type(RegridderManager), target :: regridder_mgr
      type(RegridderSpec) :: spec
      integer :: status
      class(Regridder), pointer :: my_regridder
      type(ESMF_Geom) :: geom_1, geom_2
      type(ESMF_HConfig) :: hconfig
      type(ESMF_Field) :: f1, f2
      real(kind=ESMF_KIND_R4), pointer :: x1(:,:)
      real(kind=ESMF_KIND_R4), pointer :: x2(:,:)

      geom_mgr = GeomManager()
      regridder_mgr = RegridderManager()

      hconfig = ESMF_HConfigCreate(content="{class: latlon, im_world: 12, jm_world: 11, pole: PC, dateline: DE, nx: 1, ny: 1}", _RC)
      geom_1 = make_geom(geom_mgr, hconfig, _RC)

      hconfig = ESMF_HConfigCreate(content="{class: latlon, im_world: 6, jm_world: 5, pole: PC, dateline: DE, nx: 1, ny: 1}", _RC)
      geom_2 = make_geom(geom_mgr, hconfig, _RC) ! variant of geom_1

      spec = RegridderSpec(EsmfRegridderParam(regridmethod=ESMF_REGRIDMETHOD_CONSERVE), geom_1, geom_2)
      my_regridder => regridder_mgr%get_regridder(spec, _RC)

      f1 = make_field(geom_1, 'f1', value=2._ESMF_KIND_R4, _RC)
      call ESMF_FieldGet(f1, farrayptr=x1, _RC)
      x1(2::2,:) = 0 ! checkerboard
      
      f2 = make_field(geom_2, 'f2', value=0._ESMF_KIND_R4, _RC)

      ! (0 + 2)/2 == 1
      call my_regridder%regrid(f1, f2, _RC)
      call ESMF_FieldGet(f2, farrayptr=x2, _RC)
 
      @assert_that(x2, every_item(is(equal_to(1._ESMF_KIND_R4))))

   end subroutine test_regrid_values


   @test(type=ESMF_TestMethod, npes=[1])
   ! Test regridding on fields with ungridded dimensions.  ESMF does
   ! not directly support this case, and this test is to drive the
   ! creation of a wrapper layer in MAPL.
   subroutine test_regrid_3d(this)
      class(ESMF_TestMethod), intent(inout) :: this
      type(GeomManager) :: geom_mgr
      type(RegridderManager), target :: regridder_mgr
      type(RegridderSpec) :: spec
      integer :: status
      class(Regridder), pointer :: my_regridder
      type(ESMF_Geom) :: geom_1, geom_2
      type(ESMF_HConfig) :: hconfig
      type(ESMF_Field) :: f1, f2
      real(kind=ESMF_KIND_R4), pointer :: x1(:,:,:)
      real(kind=ESMF_KIND_R4), pointer :: x2(:,:,:)

      type(DynamicMask) :: dyn_mask
      
      geom_mgr = GeomManager()
      regridder_mgr = RegridderManager()

      hconfig = ESMF_HConfigCreate(content="{class: latlon, im_world: 12, jm_world: 11, pole: PC, dateline: DE, nx: 1, ny: 1}", _RC)
      geom_1 = make_geom(geom_mgr, hconfig, _RC)

      hconfig = ESMF_HConfigCreate(content="{class: latlon, im_world: 6, jm_world: 5, pole: PC, dateline: DE, nx: 1, ny: 1}", _RC)
      geom_2 = make_geom(geom_mgr, hconfig, _RC) ! variant of geom_1

      dyn_mask = DynamicMask(mask_type='missing_value', src_mask_value=real(MAPL_UNDEF,kind=ESMF_KIND_R8), handleAllElements=.true.,_RC)
      
      spec = RegridderSpec(EsmfRegridderParam(regridmethod=ESMF_REGRIDMETHOD_CONSERVE, dyn_mask=dyn_mask), geom_1, geom_2)
      my_regridder => regridder_mgr%get_regridder(spec, _RC)

      f1 = make_field(geom_1, 'f1', value=2._ESMF_KIND_R4, lm=2, _RC)
      call ESMF_FieldGet(f1, farrayptr=x1)
      x1(::4,6,1) = MAPL_UNDEF ! missing bits in level 1
      x1(1::2,:,2) = 0 ! checkerboard on level 2
      
      f2 = make_field(geom_2, 'f2', value=0._ESMF_KIND_R4, lm=2, _RC)

      call my_regridder%regrid(f1, f2, _RC)

      call ESMF_FieldGet(f2, farrayptr=x2, _RC)


      ! Missing elements case
      @assert_that(x2(1:2,:,1), every_item(is(equal_to(2._ESMF_KIND_R4))))
      ! Non missing elements case

      ! Weirdly this introduces roundoff that was not present in the
      ! previous test.  This has been reported to the ESMF core team.
      @assert_that(x2(:,:,2), every_item(is(near(1._ESMF_KIND_R4, 1.e-6))))

   end subroutine test_regrid_3d


end module Test_RegridderManager