CubedSphereGeomFactory_smod.F90 Source File


This file depends on

sourcefile~~cubedspheregeomfactory_smod.f90~~EfferentGraph sourcefile~cubedspheregeomfactory_smod.f90 CubedSphereGeomFactory_smod.F90 sourcefile~constants.f90 Constants.F90 sourcefile~cubedspheregeomfactory_smod.f90->sourcefile~constants.f90 sourcefile~cubedspheredecomposition.f90 CubedSphereDecomposition.F90 sourcefile~cubedspheregeomfactory_smod.f90->sourcefile~cubedspheredecomposition.f90 sourcefile~cubedspheregeomfactory.f90 CubedSphereGeomFactory.F90 sourcefile~cubedspheregeomfactory_smod.f90->sourcefile~cubedspheregeomfactory.f90 sourcefile~cubedspheregeomspec.f90 CubedSphereGeomSpec.F90 sourcefile~cubedspheregeomfactory_smod.f90->sourcefile~cubedspheregeomspec.f90 sourcefile~errorhandling.f90 ErrorHandling.F90 sourcefile~cubedspheregeomfactory_smod.f90->sourcefile~errorhandling.f90 sourcefile~geomspec.f90 GeomSpec.F90 sourcefile~cubedspheregeomfactory_smod.f90->sourcefile~geomspec.f90 sourcefile~keywordenforcer.f90 KeywordEnforcer.F90 sourcefile~cubedspheregeomfactory_smod.f90->sourcefile~keywordenforcer.f90 sourcefile~lataxis.f90 LatAxis.F90 sourcefile~cubedspheregeomfactory_smod.f90->sourcefile~lataxis.f90 sourcefile~lonaxis.f90 LonAxis.F90 sourcefile~cubedspheregeomfactory_smod.f90->sourcefile~lonaxis.f90 sourcefile~mapl_minmax.f90 MAPL_MinMax.F90 sourcefile~cubedspheregeomfactory_smod.f90->sourcefile~mapl_minmax.f90 sourcefile~pfio.f90 pFIO.F90 sourcefile~cubedspheregeomfactory_smod.f90->sourcefile~pfio.f90

Source Code

#include "MAPL_ErrLog.h"
submodule (mapl3g_CubedSphereGeomFactory) CubedSphereGeomFactory_smod
   use mapl3g_GeomSpec
   use mapl3g_LonAxis
   use mapl3g_LatAxis
   use mapl3g_CubedSphereDecomposition
   use mapl3g_CubedSphereGeomSpec
   use mapl_MinMaxMod
   use mapl_ErrorHandlingMod
   use mapl_Constants
   use pFIO
   use gFTL2_StringVector
   use esmf
   use mapl_KeywordEnforcer, only: KE => KeywordEnforcer
   implicit none
   real(kind=ESMF_Kind_R8) :: undef_schmidt = 1d15

contains


   module function make_geom_spec_from_hconfig(this, hconfig, rc) result(geom_spec)
      class(GeomSpec), allocatable :: geom_spec
      class(CubedSphereGeomFactory), intent(in) :: this
      type(ESMF_HConfig), intent(in) :: hconfig
      integer, optional, intent(out) :: rc

      integer :: status

      geom_spec = make_CubedSphereGeomSpec(hconfig, _RC)

      _RETURN(_SUCCESS)
   end function make_geom_spec_from_hconfig


   module function make_geom_spec_from_metadata(this, file_metadata, rc) result(geom_spec)
      class(GeomSpec), allocatable :: geom_spec
      class(CubedSphereGeomFactory), intent(in) :: this
      type(FileMetadata), intent(in) :: file_metadata
      integer, optional, intent(out) :: rc

      integer :: status

      geom_spec = make_CubedSphereGeomSpec(file_metadata, _RC)

      _RETURN(_SUCCESS)
   end function make_geom_spec_from_metadata


   logical module function supports_spec(this, geom_spec) result(supports)
      class(CubedSphereGeomFactory), intent(in) :: this
      class(GeomSpec), intent(in) :: geom_spec

      type(CubedSphereGeomSpec) :: reference

      supports = same_type_as(geom_spec, reference)

   end function supports_spec

   logical module function supports_hconfig(this, hconfig, rc) result(supports)
      class(CubedSphereGeomFactory), intent(in) :: this
      type(ESMF_HConfig), intent(in) :: hconfig
      integer, optional, intent(out) :: rc

      integer :: status
      type(CubedSphereGeomSpec) :: spec

      supports = spec%supports(hconfig, _RC)
      
      _RETURN(_SUCCESS)
   end function supports_hconfig

   logical module function supports_metadata(this, file_metadata, rc) result(supports)
      class(CubedSphereGeomFactory), intent(in) :: this
      type(FileMetadata), intent(in) :: file_metadata
      integer, optional, intent(out) :: rc

      integer :: status
      type(CubedSphereGeomSpec) :: spec

      supports = spec%supports(file_metadata, _RC)
      
      _RETURN(_SUCCESS)
   end function supports_metadata


   module function make_geom(this, geom_spec, rc) result(geom)
      type(ESMF_Geom) :: geom
      class(CubedSphereGeomFactory), intent(in) :: this
      class(GeomSpec), intent(in) :: geom_spec
      integer, optional, intent(out) :: rc

      integer :: status

      select type (geom_spec)
      type is (CubedSphereGeomSpec)
         geom = typesafe_make_geom(geom_spec, _RC)
      class default
         _FAIL("geom_spec type not supported")
      end select

      _RETURN(_SUCCESS)
   end function make_geom


   function typesafe_make_geom(spec, rc) result(geom)
      type(ESMF_Geom) :: geom
      class(CubedSphereGeomSpec), intent(in) :: spec
      integer, optional, intent(out) :: rc

      integer :: status
      type(ESMF_Grid) :: grid

      grid = create_basic_grid(spec, _RC)
      geom = ESMF_GeomCreate(grid=grid, _RC)

      _RETURN(_SUCCESS)
   end function typesafe_make_geom


   module function create_basic_grid(spec, unusable, rc) result(grid)
      type(ESMF_Grid) :: grid
      type(CubedSphereGeomSpec), intent(in) :: spec
      class(KE), optional, intent(in) :: unusable
      integer, optional, intent(out) :: rc

      integer :: status, im_world, ntiles, i
      type(CubedSphereDecomposition) :: decomp
      type(ESMF_CubedSphereTransform_Args) :: schmidt_parameters
      logical :: not_stretched
      integer, allocatable :: ims(:,:), jms(:,:), face_ims(:), face_jms(:)

      ntiles = 6

      decomp = spec%get_decomposition()
      schmidt_parameters = spec%get_schmidt_parameters()
      im_world = spec%get_im_world()
      not_stretched = .not. is_stretched_cube(schmidt_parameters) 
      face_ims = decomp%get_x_distribution()
      face_jms = decomp%get_y_distribution()
      allocate(ims(size(face_ims),ntiles))
      allocate(jms(size(face_jms),ntiles))
      do i=1,ntiles
         ims(:,i) = face_ims 
         jms(:,i) = face_jms 
      enddo

      if (not_stretched) then
         grid = ESMF_GridCreateCubedSPhere(im_world,countsPerDEDim1PTile=ims, &
            countsPerDEDim2PTile=jms, &
            staggerLocList=[ESMF_STAGGERLOC_CENTER,ESMF_STAGGERLOC_CORNER], coordSys=ESMF_COORDSYS_SPH_RAD, _RC)
      else
         grid = ESMF_GridCreateCubedSPhere(im_world,countsPerDEDim1PTile=ims, &
            countsPerDEDim2PTile=jms,  &
            staggerLocList=[ESMF_STAGGERLOC_CENTER,ESMF_STAGGERLOC_CORNER], coordSys=ESMF_COORDSYS_SPH_RAD, &
            transformArgs=schmidt_parameters, _RC)
      end if
      
      _RETURN(_SUCCESS)
      _UNUSED_DUMMY(unusable)
   end function create_basic_grid

   module function make_gridded_dims(this, geom_spec, rc) result(gridded_dims)
      type(StringVector) :: gridded_dims
      class(CubedSphereGeomFactory), intent(in) :: this
      class(GeomSpec), intent(in) :: geom_spec
      integer, optional, intent(out) :: rc

      gridded_dims = StringVector()
      select type (geom_spec)
      type is (CubedSphereGeomSpec)
         call gridded_dims%push_back('Xdim')
         call gridded_dims%push_back('Ydim')
         call gridded_dims%push_back('nf')
      class default
         _FAIL('geom_spec is not of dynamic type CubedSphereGeomSpec.')
      end select

      _RETURN(_SUCCESS)
   end function make_gridded_dims


   module function make_file_metadata(this, geom_spec, unusable, chunksizes, rc) result(file_metadata)
      type(FileMetadata) :: file_metadata
      class(CubedSphereGeomFactory), intent(in) :: this
      class(KE), optional, intent(in) :: unusable
      integer, optional, intent(in) :: chunksizes(:)
      class(GeomSpec), intent(in) :: geom_spec
      integer, optional, intent(out) :: rc

      integer :: status

      file_metadata = FileMetadata()

      select type (geom_spec)
      type is (CubedSphereGeomSpec)
         file_metadata = typesafe_make_file_metadata(geom_spec, chunksizes=chunksizes, _RC)
      class default
         _FAIL('geom_spec is not of dynamic type CubedSphereGeomSpec.')
      end select

      _RETURN(_SUCCESS)
   end function make_file_metadata

   function typesafe_make_file_metadata(geom_spec, unusable, chunksizes, rc) result(file_metadata)
      type(FileMetadata) :: file_metadata
      type(CubedSphereGeomSpec), intent(in) :: geom_spec
      class(KE), optional, intent(in) :: unusable
      integer, optional, intent(in) :: chunksizes(:)
      integer, optional, intent(out) :: rc

      integer :: im, im_world
      type (Variable) :: v
      integer, parameter :: MAXLEN=80
      character(len=MAXLEN) :: gridspec_file_name
      !!! character(len=5), allocatable :: cvar(:,:)
      integer, allocatable :: ivar(:,:)
      integer, allocatable :: ivar2(:,:,:)

      real(REAL64), allocatable :: temp_coords(:)

      integer :: status, i
      integer, parameter :: ncontact = 4
      type(ESMF_CubedSphereTransform_Args) :: schmidt_parameters
      integer, parameter :: nf = 6
      logical :: is_stretched

      im_world = geom_spec%get_im_world()
      schmidt_parameters = geom_spec%get_schmidt_parameters()
      is_stretched = is_stretched_cube(schmidt_parameters)
      ! Grid dimensions
      call file_metadata%add_dimension('Xdim', im_world, _RC)
      call file_metadata%add_dimension('Ydim', im_world, _RC)
      call file_metadata%add_dimension('XCdim', im_world+1, _RC)
      call file_metadata%add_dimension('YCdim', im_world+1, _RC)
      call file_metadata%add_dimension('nf', nf, _RC)
      call file_metadata%add_dimension('ncontact', ncontact, _RC)
      call file_metadata%add_dimension('orientationStrLen', 5, _RC)

      ! Coordinate variables
      v = Variable(type=PFIO_REAL64, dimensions='Xdim')
      call v%add_attribute('long_name', 'Fake Longitude for GrADS Compatibility')
      call v%add_attribute('units', 'degrees_east')
      temp_coords = [(i,i=1,im_world)]
      call file_metadata%add_variable('Xdim', CoordinateVariable(v, temp_coords))
      deallocate(temp_coords)

      v = Variable(type=PFIO_REAL64, dimensions='Ydim')
      call v%add_attribute('long_name', 'Fake Latitude for GrADS Compatibility')
      call v%add_attribute('units', 'degrees_north')
      temp_coords = [(i,i=1,im_world)] 
      call file_metadata%add_variable('Ydim', CoordinateVariable(v, temp_coords))
      deallocate(temp_coords)

      v = Variable(type=PFIO_INT32, dimensions='nf')
      call v%add_attribute('long_name','cubed-sphere face')
      call v%add_attribute('axis','e')
      call v%add_attribute('grads_dim','e')
      call v%add_const_value(UnlimitedEntity([1,2,3,4,5,6]))
      call file_metadata%add_variable('nf',v)

      v = Variable(type=PFIO_INT32, dimensions='ncontact')
      call v%add_attribute('long_name','number of contact points')
      call v%add_const_value(UnlimitedEntity([1,2,3,4]))
      call file_metadata%add_variable('ncontact',v)
      ! Other variables
      allocate(ivar(4,6))
      ivar = reshape( [5, 3, 2, 6, &
                       1, 3, 4, 6, &
                       1, 5, 4, 2, &
                       3, 5, 6, 2, &
                       3, 1, 6, 4, &
                       5, 1, 2, 4 ], [ncontact,nf])
      v = Variable(type=PFIO_INT32, dimensions='ncontact,nf')
      call v%add_attribute('long_name', 'adjacent face starting from left side going clockwise')
      call v%add_const_value(UnlimitedEntity(ivar))
      call file_metadata%add_variable('contacts', v)      !!! At present pfio does not seem to work with string variables
      !!! allocate(cvar(4,6))
      !!! cvar =reshape([" Y:-X", " X:-Y", " Y:Y ", " X:X ", &
      !!!                " Y:Y ", " X:X ", " Y:-X", " X:-Y", &
      !!!                " Y:-X", " X:-Y", " Y:Y ", " X:X ", &
      !!!                " Y:Y ", " X:X ", " Y:-X", " X:-Y", &
      !!!                " Y:-X", " X:-Y", " Y:Y ", " X:X ", &
      !!!                " Y:Y ", " X:X ", " Y:-X", " X:-Y" ], [ncontact,nf])
      !!! v = Variable(type=PFIO_STRING, dimensions='orientationStrLen,ncontact,nf')
      !!! call v%add_attribute('long_name', 'orientation of boundary')
      !!! call v%add_const_value(UnlimitedEntity(cvar))
      !!! call file_metadata%add_variable('orientation', v)

      im = im_world
      allocate(ivar2(4,4,6))
      ivar2 = reshape(            &
               [[im, im,  1, im,  &
                  1, im,  1,  1,  &
                  1, im,  1,  1,  &
                 im, im,  1, im], &
                [im,  1, im, im,  &
                  1,  1, im,  1,  &
                  1,  1, im,  1,  &
                 im,  1, im, im], &
                [im, im,  1, im,  &
                  1, im,  1,  1,  &
                  1, im,  1,  1,  &
                 im, im,  1, im], &
                [im,  1, im, im,  &
                  1,  1, im,  1,  &
                  1,  1, im,  1,  &
                 im,  1, im, im], &
                [im, im,  1, im,  &
                  1, im,  1,  1,  &
                  1, im,  1,  1,  &
                 im, im,  1, im], &
                [im,  1, im, im,  &
                  1,  1, im,  1,  &
                  1,  1, im,  1,  &
                 im,  1, im, im] ], [ncontact,ncontact,nf])
      v = Variable(type=PFIO_INT32, dimensions='ncontact,ncontact,nf')
      call v%add_attribute('long_name', 'anchor point')
      call v%add_const_value(UnlimitedEntity(ivar2))
      call file_metadata%add_variable('anchor', v)

      call file_metadata%add_attribute('grid_mapping_name', 'gnomonic cubed-sphere')
      call file_metadata%add_attribute('file_format_version', '2.92')
      call file_metadata%add_attribute('additional_vars', 'contacts,orientation,anchor')
      write(gridspec_file_name,'("C",i0,"_gridspec.nc4")') im_world
      call file_metadata%add_attribute('gridspec_file', trim(gridspec_file_name))

      v = Variable(type=PFIO_REAL64, dimensions='Xdim,Ydim,nf')
      call v%add_attribute('long_name','longitude')
      call v%add_attribute('units','degrees_east')
      call file_metadata%add_variable('lons',v)

      v = Variable(type=PFIO_REAL64, dimensions='Xdim,Ydim,nf')
      call v%add_attribute('long_name','latitude')
      call v%add_attribute('units','degrees_north')
      call file_metadata%add_variable('lats',v)

      v = Variable(type=PFIO_REAL64, dimensions='XCdim,YCdim,nf')
      call v%add_attribute('long_name','longitude')
      call v%add_attribute('units','degrees_east')
      call file_metadata%add_variable('corner_lons',v)

      v = Variable(type=PFIO_REAL64, dimensions='XCdim,YCdim,nf')
      call v%add_attribute('long_name','latitude')
      call v%add_attribute('units','degrees_north')
      call file_metadata%add_variable('corner_lats',v)

      if (is_stretched) then
         call file_metadata%add_attribute('STRETCH_FACTOR',schmidt_parameters%stretch_factor)
         call file_metadata%add_attribute('TARGET_LON',schmidt_parameters%target_lon)
         call file_metadata%add_attribute('TARGET_LAT',schmidt_parameters%target_lat)
      end if


      _RETURN(_SUCCESS)
      _UNUSED_DUMMY(unusable)
   end function typesafe_make_file_metadata

   function is_stretched_cube(schmidt_parameters) result(is_stretched)
      logical :: is_stretched
      type(ESMF_CubedSphereTransform_Args), intent(in) :: schmidt_parameters

      is_stretched = (schmidt_parameters%target_lat /= undef_schmidt) .and. &
                          (schmidt_parameters%target_lon /= undef_schmidt) .and. &
                          (schmidt_parameters%stretch_factor /= undef_schmidt) 
   end function is_stretched_cube

end submodule CubedSphereGeomFactory_smod