SharedIO.F90 Source File


This file depends on

sourcefile~~sharedio.f90~~EfferentGraph sourcefile~sharedio.f90 SharedIO.F90 sourcefile~base_base.f90 Base_Base.F90 sourcefile~sharedio.f90->sourcefile~base_base.f90 sourcefile~errorhandling.f90 ErrorHandling.F90 sourcefile~sharedio.f90->sourcefile~errorhandling.f90 sourcefile~fieldbundleget.f90 FieldBundleGet.F90 sourcefile~sharedio.f90->sourcefile~fieldbundleget.f90 sourcefile~fieldget.f90 FieldGet.F90 sourcefile~sharedio.f90->sourcefile~fieldget.f90 sourcefile~geom_mgr.f90 geom_mgr.F90 sourcefile~sharedio.f90->sourcefile~geom_mgr.f90 sourcefile~pfio.f90 pFIO.F90 sourcefile~sharedio.f90->sourcefile~pfio.f90 sourcefile~ungriddeddim.f90 UngriddedDim.F90 sourcefile~sharedio.f90->sourcefile~ungriddeddim.f90 sourcefile~ungriddeddims.f90 UngriddedDims.F90 sourcefile~sharedio.f90->sourcefile~ungriddeddims.f90 sourcefile~verticalstaggerloc.f90 VerticalStaggerLoc.F90 sourcefile~sharedio.f90->sourcefile~verticalstaggerloc.f90

Files dependent on this one

sourcefile~~sharedio.f90~~AfferentGraph sourcefile~sharedio.f90 SharedIO.F90 sourcefile~geom_pfio.f90 Geom_PFIO.F90 sourcefile~geom_pfio.f90->sourcefile~sharedio.f90 sourcefile~geomio.f90 GeomIO.F90 sourcefile~geomio.f90->sourcefile~sharedio.f90 sourcefile~geomio.f90->sourcefile~geom_pfio.f90 sourcefile~geomcatagorizer.f90 GeomCatagorizer.F90 sourcefile~geomio.f90->sourcefile~geomcatagorizer.f90 sourcefile~grid_pfio.f90 Grid_PFIO.F90 sourcefile~grid_pfio.f90->sourcefile~sharedio.f90 sourcefile~grid_pfio.f90->sourcefile~geom_pfio.f90 sourcefile~restarthandler.f90 RestartHandler.F90 sourcefile~restarthandler.f90->sourcefile~sharedio.f90 sourcefile~restarthandler.f90->sourcefile~geomio.f90 sourcefile~test_sharedio.pf Test_SharedIO.pf sourcefile~test_sharedio.pf->sourcefile~sharedio.f90 sourcefile~geomcatagorizer.f90->sourcefile~geom_pfio.f90 sourcefile~geomcatagorizer.f90->sourcefile~grid_pfio.f90 sourcefile~historycollectiongridcomp.f90 HistoryCollectionGridComp.F90 sourcefile~historycollectiongridcomp.f90->sourcefile~geomio.f90 sourcefile~read_restart.f90~2 read_restart.F90 sourcefile~read_restart.f90~2->sourcefile~restarthandler.f90 sourcefile~write_restart.f90 write_restart.F90 sourcefile~write_restart.f90->sourcefile~restarthandler.f90 sourcefile~historygridcomp.f90 HistoryGridComp.F90 sourcefile~historygridcomp.f90->sourcefile~historycollectiongridcomp.f90

Source Code

#include "MAPL_Generic.h"
module mapl3g_SharedIO
   use mapl_ErrorHandlingMod
   use mapl3g_FieldBundleGet
   use mapl3g_FieldGet
   use mapl3g_VerticalStaggerLoc
   use pfio
   use gFTL2_StringVector
   use gFTL2_StringSet
   use mapl3g_geom_mgr
   use MAPL_BaseMod
   use mapl3g_UngriddedDims
   use mapl3g_UngriddedDim
!#   use mapl3g_FieldDimensionInfo
   use esmf

   implicit none(type,external)

   public add_variables
   public add_variable
   public get_mapl_geom
   public create_time_variable
   public bundle_to_metadata
   public esmf_to_pfio_type

   public :: add_vertical_dimensions
   public :: get_vertical_dimension_name_from_field
   public :: add_ungridded_dimensions
   public :: ungridded_dim_names

   character(len=*), parameter :: EMPTY = ''
contains

   function bundle_to_metadata(bundle, geom, rc) result(metadata)
      type(FileMetaData) :: metadata
      type(ESMF_FieldBundle), intent(in) :: bundle
      type(ESMF_Geom), intent(in) :: geom
      integer, optional, intent(out) :: rc

      integer:: status
      type(MaplGeom), pointer :: mapl_geom
      type(Variable) :: time_var
      type(ESMF_Time) :: fake_time

      mapl_geom => get_mapl_geom(geom, _RC)
      metadata = mapl_geom%get_file_metadata()

      ! Add metadata for vertical geom, note could be both center and edge
      call add_vertical_dimensions(bundle, metadata, _RC)

      ! Add metadata for all unique ungridded dimensions the set of fields has
      call add_ungridded_dimensions(bundle, metadata, _RC)

      ! Add time metadata
      call ESMF_TimeSet(fake_time, timeString="1900-04-03T21:00:00", _RC)
      call metadata%add_dimension('time', pFIO_UNLIMITED)
      time_var = create_time_variable(fake_time, _RC)
      call metadata%add_variable('time', time_var, _RC)

      ! Variables
      call add_variables(metadata, bundle, _RC)

      _RETURN(_SUCCESS)
   end function bundle_to_metadata

   subroutine add_variables(metadata, bundle, rc)
      type(ESMF_FieldBundle), intent(in) :: bundle
      type(FileMetaData), intent(inout) :: metadata
      integer, intent(out), optional :: rc

      integer :: status, i
      type(ESMF_Field) :: field
      type(ESMF_Field), allocatable :: fieldList(:)

      call MAPL_FieldBundleGet(bundle, fieldList=fieldList, _RC)
      do i = 1, size(fieldList)
         call add_variable(metadata, fieldList(i), _RC)
      enddo

      _RETURN(_SUCCESS)
   end subroutine add_variables

   subroutine add_variable(metadata, field,  rc)
      type(ESMF_Field), intent(in) :: field
      type(FileMetaData), intent(inout) :: metadata
      integer, intent(out), optional :: rc

      integer :: status
      type(Variable) :: v
      character(len=:), allocatable :: variable_dim_names
      type(ESMF_TYPEKIND_FLAG) :: typekind
      character(len=:), allocatable :: short_name
      character(len=:), allocatable :: units
      character(len=:), allocatable :: long_name
      character(len=:), allocatable :: standard_name

      type(ESMF_Geom) :: geom
      integer :: pfio_type

      variable_dim_names = get_variable_dim_names(field, geom, _RC)
      call MAPL_FieldGet(field, short_name=short_name, typekind=typekind, _RC)
      pfio_type = esmf_to_pfio_type(typekind ,_RC)
      v = Variable(type=pfio_type, dimensions=variable_dim_names)

      ! Attributes
      call MAPL_FieldGet(field, units=units, long_name=long_name, standard_name=standard_name, _RC)
      if (allocated(units))then
         call v%add_attribute('units', units)
      end if
      if (allocated(long_name)) then
         call v%add_attribute('long_name', long_name)
      end if
      if (allocated(standard_name)) then
         call v%add_attribute('standard_name', standard_name)
      end if

      call metadata%add_variable(short_name, v, _RC)

      _RETURN(_SUCCESS)
   end subroutine add_variable

   function get_variable_dim_names(field, geom, rc) result(dim_names)
      character(len=:), allocatable :: dim_names
      type(ESMF_Field), intent(in) :: field
      type(ESMF_Geom), intent(in) :: geom
      integer, optional, intent(out) :: rc
      
      type(MAPLGeom), pointer :: mapl_geom
      type(StringVector) :: grid_variables
      type(ESMF_Geom) :: esmfgeom
      character(len=:), allocatable :: vert_dim_name, ungridded_names
      integer :: status
      
      call ESMF_FieldGet(field, geom=esmfgeom, _RC)
      mapl_geom => get_mapl_geom(esmfgeom, _RC)
      grid_variables = mapl_geom%get_gridded_dims()
      dim_names = string_vec_to_comma_sep(grid_variables)
      ! add vertical dimension
      vert_dim_name = get_vertical_dimension_name_from_field(field, _RC)
      if(vert_dim_name /= EMPTY) dim_names = dim_names // "," // vert_dim_name
      ! add any ungridded dimensions
      ungridded_names = ungridded_dim_names(field, _RC)
      if(ungridded_names /= EMPTY) dim_names = dim_names // ungridded_names
      ! add time dimension
      dim_names = dim_names // ",time"

      _RETURN(_SUCCESS)
   end function get_variable_dim_names


   function get_mapl_geom(geom, rc) result(mapl_geom)
      type(MAPLGeom), pointer :: mapl_geom
      type(ESMF_Geom), intent(in) :: geom 
      integer, optional, intent(out) :: rc

      integer :: status, id
      type(GeomManager), pointer :: geom_mgr

      geom_mgr => get_geom_manager()
      id = MAPL_GeomGetId(geom, _RC)
      mapl_geom => geom_mgr%get_mapl_geom_from_id(id, _RC)
      _RETURN(_SUCCESS)

   end function get_mapl_geom

   function esmf_to_pfio_type(esmf_type, rc) result(pfio_type)
      integer :: pfio_type
      type(ESMF_TYPEKIND_FLAG), intent(in) :: esmf_type
      integer, intent(out), optional :: rc

      if (esmf_type == ESMF_TYPEKIND_R4) then
         pfio_type = pFIO_REAL32
      else if (esmf_type == ESMF_TYPEKIND_R8) then
         pfio_type = pFIO_REAL64
      else
         _FAIL("Unsupported ESMF field typekind for output")
      end if

      _RETURN(_SUCCESS)
   end function

   function string_vec_to_comma_sep(string_vec) result(comma_sep)
      character(len=:), allocatable :: comma_sep
      type(StringVector), intent(in) :: string_vec
      type(stringVectorIterator) :: iter
      character(len=:), pointer :: var

      iter = string_vec%begin()
      var => iter%of()
      comma_sep = var
      call iter%next()
      do while (iter /= string_vec%end())
         var => iter%of()
         comma_sep = comma_sep // "," // var
         call iter%next()
      enddo

   end function  

   function create_time_variable(current_time, rc) result(time_var)
      type(Variable) :: time_var
      type(ESMF_Time), intent(in) :: current_time
      integer, optional, intent(out) :: rc

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

      call ESMF_TimeGet(current_time, timeString=iso_time_string, _RC)
      iso_time_string = "minutes since "//trim(iso_time_string)
      time_var = Variable(type=PFIO_REAL32, dimensions='time')
      call time_var%add_attribute('long_name', 'time')
      call time_var%add_attribute('units', iso_time_string, _RC)

      _RETURN(_SUCCESS)
   end function create_time_variable

   subroutine add_vertical_dimensions(bundle, metadata, rc)
      type(ESMF_FieldBundle), intent(in) :: bundle
      type(FileMetaData), intent(inout) :: metadata
      integer, optional, intent(out) :: rc

      integer :: status
      integer :: num_levels
      type(StringVectorIterator) :: iter
      character(len=:), allocatable :: dim_name
      type(VerticalStaggerLoc) :: vert_staggerloc
      integer :: i, num_vgrid_levels, field_vgrid_levels
      type(ESMF_Field), allocatable :: fieldList(:)


      call MAPL_FieldBundleGet(bundle, fieldList=fieldList, _RC)
      num_vgrid_levels = 0
      
      do i = 1, size(fieldList)
         call MAPL_FieldGet(fieldList(i), vert_staggerloc=vert_staggerloc, _RC)
         if (vert_staggerloc == VERTICAL_STAGGER_NONE) cycle

         ! Ensure consistent vertical grid
         call MAPL_FieldGet(fieldList(i), num_vgrid_levels=field_vgrid_levels, _RC)
         if (num_vgrid_levels > 0) then
            _ASSERT(field_vgrid_levels == num_vgrid_levels, "Inconsistent vertical grid in bundle.")
         else
            num_vgrid_levels = field_vgrid_levels
         end if

         dim_name = vert_staggerloc%get_dimension_name()
         call metadata%add_dimension(dim_name, num_levels)

      end do

      _RETURN(_SUCCESS)
   end subroutine add_vertical_dimensions


   function get_vertical_dimension_name_from_field(field, rc) result(dim_name)
      character(len=:), allocatable :: dim_name
      type(ESMF_Field), intent(in) :: field
      integer, intent(out), optional :: rc

      integer :: status
      type(VerticalStaggerLoc) :: vert_staggerloc

      call MAPL_FieldGet(field, vert_staggerLoc=vert_staggerLoc, _RC)
      dim_name = vert_staggerLoc%get_dimension_name()
      _RETURN(_SUCCESS)

   end function get_vertical_dimension_name_from_field

   subroutine add_ungridded_dimensions(bundle, metadata, rc)
      type(ESMF_FieldBundle), intent(in) :: bundle
      type(FileMetaData), intent(inout) :: metadata
      integer, optional, intent(out) :: rc
      integer :: status
      type(UngriddedDims) :: field_ungridded_dims, ungridded_dims
      type(UngriddedDim) :: u
      integer :: i, j
      type(ESMF_Field) :: field
      type(ESMF_Field), allocatable :: fieldList(:)
      type(StringSet) :: dim_names
      character(:), allocatable :: dim_name
      logical :: is_new

      call MAPL_FieldBundleGet(bundle, fieldList=fieldList, _RC)
      do i = 1, size(fieldList)
         call MAPL_FieldGet(fieldList(i), ungridded_dims=field_ungridded_dims, _RC)
         
         do j = 1, field_ungridded_dims%get_num_ungridded()
            u = ungridded_dims%get_ith_dim_spec(i)
            dim_name = u%get_name()
            call dim_names%insert(dim_name, is_new=is_new)
            if (is_new) then
               call metadata%add_dimension(u%get_name(), u%get_extent())
            end if
         end do
      end do

      _RETURN(_SUCCESS)
   end subroutine add_ungridded_dimensions

   function ungridded_dim_names(field, rc) result(dim_names)
      character(len=:), allocatable :: dim_names
      type(ESMF_Field), intent(in) :: field
      integer, optional, intent(out) :: rc
      integer :: status
      type(UngriddedDims) :: ungridded_dims

      call MAPL_FieldGet(field, ungridded_dims=ungridded_dims, _RC)
      dim_names = cat_ungridded_dim_names(ungridded_dims)

      _RETURN(_SUCCESS)
   end function ungridded_dim_names

   
   function cat_ungridded_dim_names(dims) result(dim_names)
      character(len=:), allocatable :: dim_names
      class(UngriddedDims), intent(in) :: dims

      integer :: i

#define JOIN(a,b) a // ',' // b
      dim_names = EMPTY
      do i = 1, dims%get_num_ungridded()
         associate (u => dims%get_ith_dim_spec(i))
           dim_names = JOIN(dim_names, u%get_name())
         end associate
      end do
#undef JOIN

   end function cat_ungridded_dim_names

end module mapl3g_SharedIO