TileGridIO.F90 Source File


This file depends on

sourcefile~~tilegridio.f90~~EfferentGraph sourcefile~tilegridio.f90 TileGridIO.F90 sourcefile~base_base.f90 Base_Base.F90 sourcefile~tilegridio.f90->sourcefile~base_base.f90 sourcefile~clientmanager.f90 ClientManager.F90 sourcefile~tilegridio.f90->sourcefile~clientmanager.f90 sourcefile~constants.f90 Constants.F90 sourcefile~tilegridio.f90->sourcefile~constants.f90 sourcefile~datacollection.f90 DataCollection.F90 sourcefile~tilegridio.f90->sourcefile~datacollection.f90 sourcefile~datacollectionmanager.f90 DataCollectionManager.F90 sourcefile~tilegridio.f90->sourcefile~datacollectionmanager.f90 sourcefile~downbit.f90 DownBit.F90 sourcefile~tilegridio.f90->sourcefile~downbit.f90 sourcefile~esmfl_mod.f90 ESMFL_Mod.F90 sourcefile~tilegridio.f90->sourcefile~esmfl_mod.f90 sourcefile~fieldpointerutilities.f90 FieldPointerUtilities.F90 sourcefile~tilegridio.f90->sourcefile~fieldpointerutilities.f90 sourcefile~fileioshared.f90 FileIOShared.F90 sourcefile~tilegridio.f90->sourcefile~fileioshared.f90 sourcefile~filemetadatautilities.f90 FileMetadataUtilities.F90 sourcefile~tilegridio.f90->sourcefile~filemetadatautilities.f90 sourcefile~griddedio.f90 GriddedIO.F90 sourcefile~tilegridio.f90->sourcefile~griddedio.f90 sourcefile~griddedioitem.f90 GriddedIOitem.F90 sourcefile~tilegridio.f90->sourcefile~griddedioitem.f90 sourcefile~mapl_abstractgridfactory.f90 MAPL_AbstractGridFactory.F90 sourcefile~tilegridio.f90->sourcefile~mapl_abstractgridfactory.f90 sourcefile~mapl_abstractregridder.f90 MAPL_AbstractRegridder.F90 sourcefile~tilegridio.f90->sourcefile~mapl_abstractregridder.f90 sourcefile~mapl_comms.f90 MAPL_Comms.F90 sourcefile~tilegridio.f90->sourcefile~mapl_comms.f90 sourcefile~mapl_exceptionhandling.f90 MAPL_ExceptionHandling.F90 sourcefile~tilegridio.f90->sourcefile~mapl_exceptionhandling.f90 sourcefile~mapl_gridmanager.f90 MAPL_GridManager.F90 sourcefile~tilegridio.f90->sourcefile~mapl_gridmanager.f90 sourcefile~mapl_locstreammod.f90 MAPL_LocStreamMod.F90 sourcefile~tilegridio.f90->sourcefile~mapl_locstreammod.f90 sourcefile~mapl_sort.f90 MAPL_Sort.F90 sourcefile~tilegridio.f90->sourcefile~mapl_sort.f90 sourcefile~mapl_timemethods.f90 MAPL_TimeMethods.F90 sourcefile~tilegridio.f90->sourcefile~mapl_timemethods.f90 sourcefile~mapl_verticalmethods.f90 MAPL_VerticalMethods.F90 sourcefile~tilegridio.f90->sourcefile~mapl_verticalmethods.f90 sourcefile~newregriddermanager.f90 NewRegridderManager.F90 sourcefile~tilegridio.f90->sourcefile~newregriddermanager.f90 sourcefile~pfio.f90 pFIO.F90 sourcefile~tilegridio.f90->sourcefile~pfio.f90 sourcefile~regridmethods.f90 RegridMethods.F90 sourcefile~tilegridio.f90->sourcefile~regridmethods.f90

Files dependent on this one

sourcefile~~tilegridio.f90~~AfferentGraph sourcefile~tilegridio.f90 TileGridIO.F90 sourcefile~extdata_iobundlemod.f90 ExtData_IOBundleMod.F90 sourcefile~extdata_iobundlemod.f90->sourcefile~tilegridio.f90 sourcefile~mapl_historygridcomp.f90 MAPL_HistoryGridComp.F90 sourcefile~mapl_historygridcomp.f90->sourcefile~tilegridio.f90 sourcefile~extdata_iobundlevectormod.f90~2 ExtData_IOBundleVectorMod.F90 sourcefile~extdata_iobundlevectormod.f90~2->sourcefile~extdata_iobundlemod.f90 sourcefile~extdatadrivergridcomp.f90 ExtDataDriverGridComp.F90 sourcefile~extdatadrivergridcomp.f90->sourcefile~mapl_historygridcomp.f90 sourcefile~extdatagridcompng.f90 ExtDataGridCompNG.F90 sourcefile~extdatadrivergridcomp.f90->sourcefile~extdatagridcompng.f90 sourcefile~extdatagridcompng.f90->sourcefile~extdata_iobundlemod.f90 sourcefile~extdatagridcompng.f90->sourcefile~extdata_iobundlevectormod.f90~2 sourcefile~mapl_capgridcomp.f90 MAPL_CapGridComp.F90 sourcefile~mapl_capgridcomp.f90->sourcefile~mapl_historygridcomp.f90 sourcefile~mapl_capgridcomp.f90->sourcefile~extdatagridcompng.f90 sourcefile~comp_testing_driver.f90 Comp_Testing_Driver.F90 sourcefile~comp_testing_driver.f90->sourcefile~mapl_capgridcomp.f90 sourcefile~extdatadriver.f90 ExtDataDriver.F90 sourcefile~extdatadriver.f90->sourcefile~extdatadrivergridcomp.f90 sourcefile~extdatadrivermod.f90 ExtDataDriverMod.F90 sourcefile~extdatadriver.f90->sourcefile~extdatadrivermod.f90 sourcefile~extdatadrivermod.f90->sourcefile~extdatadrivergridcomp.f90 sourcefile~mapl_cap.f90 MAPL_Cap.F90 sourcefile~mapl_cap.f90->sourcefile~mapl_capgridcomp.f90 sourcefile~mapl_gridcomps.f90 MAPL_GridComps.F90 sourcefile~mapl_gridcomps.f90->sourcefile~mapl_cap.f90 sourcefile~mapl_nuopcwrappermod.f90 MAPL_NUOPCWrapperMod.F90 sourcefile~mapl_nuopcwrappermod.f90->sourcefile~mapl_cap.f90

Source Code

#include "MAPL_Generic.h"

module MAPL_TileGridIOMod
  use ESMF
  use ESMFL_Mod
  use MAPL_AbstractGridFactoryMod
  use MAPL_AbstractRegridderMod
  use MAPL_GridManagerMod
  use MAPL_BaseMod
  use MAPL_NewRegridderManager
  use MAPL_RegridMethods
  use MAPL_TimeDataMod
  use MAPL_VerticalDataMod
  use MAPL_Constants
  use MAPL_GriddedIOMod
  use MAPL_LocStreamMod
  use MAPL_CommsMod
  use MAPL_BaseMod
  use MAPL_FieldPointerUtilities
  use MAPL_SortMod
  use pFIO
  use MAPL_GriddedIOItemVectorMod
  use MAPL_GriddedIOItemMod
  use MAPL_ExceptionHandling
  use pFIO_ClientManagerMod
  use MAPL_DataCollectionMod
  use MAPL_DataCollectionManagerMod
  use gFTL_StringVector
  use gFTL_StringStringMap
  use MAPL_FileMetadataUtilsMod
  use MAPL_DownbitMod
  use, intrinsic :: ISO_C_BINDING
  use, intrinsic :: iso_fortran_env, only: REAL64
  use ieee_arithmetic, only: isnan => ieee_is_nan
  use netcdf, only: nf90_inq_libvers
  use FIleIOSharedMod, only: MAPL_TileMaskGet
  implicit none

  private

  public :: MAPL_TileGridIO

  type tile_buffer
    real, allocatable :: ptr(:)
  end type

  type, extends(MAPL_GriddedIO) :: MAPL_TileGridIO
     type(ESMF_FieldBundle)         :: bundle
     type(tile_buffer), allocatable :: tile_buffer(:)
     type(ESMF_Field)               :: field_in, field_out
     type(ESMF_RouteHandle)         :: routeHandle
     real, allocatable              :: tilelons(:), tilelats(:)
     integer, allocatable           :: i_index(:), j_index(:)
     contains
        procedure :: CreateFileMetaData
        procedure :: CreateVariable
        procedure :: CreateQuantizationInfo
        procedure :: bundlePost
        procedure :: stageData
        procedure :: stage2DLatLon
        procedure :: regridScalar
        procedure :: request_data_from_file
        procedure :: process_data_from_file
        procedure :: swap_undef_value
        procedure :: destroy
        procedure :: InitRedistHandle
  end type MAPL_TileGridIO

  interface MAPL_TileGridIO
     module procedure new_MAPL_TileGridIO
     module procedure new_MAPL_TileIO
  end interface MAPL_TileGridIO

  contains

     function new_MAPL_TileGridIO(metadata,input_bundle,output_bundle,write_collection_id,read_collection_id, &
             metadata_collection_id,regrid_method,fraction,items,rc) result(TileGridIO)
        type(MAPL_TileGridIO) :: TileGridIO
        type(Filemetadata), intent(in), optional :: metadata
        type(ESMF_FieldBundle), intent(in), optional :: input_bundle
        type(ESMF_FieldBundle), intent(in), optional :: output_bundle
        integer, intent(in), optional :: write_collection_id
        integer, intent(in), optional :: read_collection_id
        integer, intent(in), optional :: metadata_collection_id
        integer, intent(in), optional :: regrid_method
        integer, intent(in), optional :: fraction
        type(GriddedIOitemVector), intent(in), optional :: items
        integer, intent(out), optional :: rc
        integer :: status

        TileGridIO%MAPL_GriddedIO = MAPL_GriddedIO(metadata,input_bundle,output_bundle,write_collection_id,read_collection_id, &
             metadata_collection_id,regrid_method,fraction,items,_RC)

        _RETURN(ESMF_SUCCESS)
     end function new_MAPL_TileGridIO

     function new_MAPL_TileIO(bundle,read_collection_id) result(TileIO)
        type(MAPL_TileGridIO) :: TileIO
        type(ESMF_FieldBundle),intent(in) :: bundle
        integer, intent(in) :: read_collection_id

        TileIO%bundle = bundle
        TileIO%read_collection_id = read_collection_id
     end function

     subroutine CreateFileMetaData(this,items,bundle,timeInfo,vdata,ogrid,global_attributes,rc)
        class (MAPL_TileGridIO), target, intent(inout) :: this
        type(GriddedIOitemVector), target, intent(inout) :: items
        type(ESMF_FieldBundle), intent(inout) :: bundle
        type(TimeData), intent(inout) :: timeInfo
        type(VerticalData), intent(inout), optional :: vdata
        type (ESMF_Grid), intent(inout), pointer, optional :: ogrid
        type(StringStringMap), target, intent(in), optional :: global_attributes
        integer, intent(out), optional :: rc

        type(ESMF_Grid) :: input_grid, output_grid

        type(GriddedIOitemVectorIterator) :: iter
        type(GriddedIOitem), pointer :: item
        type(stringVector) :: order
        integer :: metadataVarsSize
        type(StringStringMapIterator) :: s_iter
        character(len=:), pointer :: attr_name, attr_val
        class(Variable), pointer :: coord_var
        integer :: status
        type(Variable) :: v

        if ( allocated (this%metadata) ) deallocate(this%metadata)
        allocate(this%metadata)

        call MAPL_FieldBundleDestroy(this%output_bundle, _RC)

        this%items = items
        this%input_bundle = bundle
        this%output_bundle = ESMF_FieldBundleCreate(rc=status)
        _VERIFY(status)
        this%timeInfo = timeInfo

        call this%InitRedistHandle(_RC)

        call ESMF_FieldBundleSet(this%output_bundle,grid=this%output_grid,rc=status)
        _VERIFY(status)

        call this%timeInfo%add_time_to_metadata(this%metadata,rc=status)
        _VERIFY(status)

        order = this%metadata%get_order(rc=status)
        _VERIFY(status)
        metadataVarsSize = order%size()

        iter = this%items%begin()
        do while (iter /= this%items%end())
           item => iter%get()
           if (item%itemType == ItemTypeScalar) then
              call this%CreateVariable(item%xname,rc=status)
              _VERIFY(status)
           else if (item%itemType == ItemTypeVector) then
              call this%CreateVariable(item%xname,rc=status)
              _VERIFY(status)
              call this%CreateVariable(item%yname,rc=status)
              _VERIFY(status)
           end if
           call iter%next()
        enddo

        if (allocated(this%tilelons)) then
           v = Variable(type=PFIO_REAL32,dimensions='tile')
           call v%add_attribute('units','degrees_east')
           call v%add_attribute('long_name','longitude')
           call this%metadata%add_variable('lon',v,rc=status)
           _VERIFY(status)
           v = Variable(type=PFIO_REAL32,dimensions='tile')
           call v%add_attribute('units','degrees_north')
           call v%add_attribute('long_name','latitude')
           call this%metadata%add_variable('lat',v,rc=status)
           _VERIFY(status)
           v = Variable(type=PFIO_INT32,dimensions='tile')
           call v%add_attribute('units','1')
           call v%add_attribute('long_name','i_index')
           call this%metadata%add_variable('IG',v,rc=status)
           _VERIFY(status)
           v = Variable(type=PFIO_INT32,dimensions='tile')
           call v%add_attribute('units','1')
           call v%add_attribute('long_name','j_index')
           call this%metadata%add_variable('JG',v,rc=status)
           _VERIFY(status)
        endif


        if (this%itemOrderAlphabetical) then
           call this%alphabatize_variables(metadataVarsSize,rc=status)
           _VERIFY(status)
        end if

        if (present(global_attributes)) then
           s_iter = global_attributes%begin()
           do while(s_iter /= global_attributes%end())
              attr_name => s_iter%key()
              attr_val => s_iter%value()
              call this%metadata%add_attribute(attr_name,attr_val,_RC)
              call s_iter%next()
           enddo
        end if

        _RETURN(_SUCCESS)

     end subroutine CreateFileMetaData

     subroutine CreateVariable(this,itemName,rc)
        class (MAPL_TileGridIO), intent(inout) :: this
        character(len=*), intent(in) :: itemName
        integer, optional, intent(out) :: rc

        integer :: status

        type(ESMF_Field) :: field,newField
        class (AbstractGridFactory), pointer :: factory
        integer :: fieldRank, global_dim(3)
        logical :: isPresent
        real, pointer :: ptr1d(:), ptr2d(:,:), ptr3d(:,:,:)
        character(len=ESMF_MAXSTR) :: varName,longName,units
        character(len=:), allocatable :: grid_dims
        character(len=:), allocatable :: vdims
        type(Variable) :: v

        call ESMF_FieldBundleGet(this%input_bundle,itemName,field=field,rc=status)
        _VERIFY(status)

        call ESMF_FieldGet(field,rank=fieldRank,rc=status)
        _VERIFY(status)
        call ESMF_FieldGet(field,name=varName,rc=status)
        _VERIFY(status)
        call ESMF_AttributeGet(field,name="LONG_NAME",isPresent=isPresent,rc=status)
        _VERIFY(status)
        if ( isPresent ) then
           call ESMF_AttributeGet  (FIELD, NAME="LONG_NAME",VALUE=LongName, RC=STATUS)
           _VERIFY(STATUS)
        else
           LongName = varName
        endif
        call ESMF_AttributeGet(field,name="UNITS",isPresent=isPresent,rc=status)
        _VERIFY(status)
        if ( isPresent ) then
           call ESMF_AttributeGet  (FIELD, NAME="UNITS",VALUE=units, RC=STATUS)
           _VERIFY(STATUS)
        else
           units = 'unknown'
        endif
         call MAPL_GridGet(this%output_grid,globalCellCountPerDim=global_dim,rc=status)
        _VERIFY(status)
        grid_dims = 'tile'

        if (.not. this%metadata%has_dimension('tile')) then
           call this%metadata%add_dimension('tile', global_dim(1))
        endif

        if (this%timeInfo%is_initialized) then
           
           if (fieldRank==1) then
              vdims = grid_dims//",time"
              call ESMF_FieldGet(field,farrayPtr=ptr1d, _RC)
           else if (fieldRank==2) then
              vdims=grid_dims//",unknown_dim1,time"
           else if (fieldRank==3) then
              vdims=grid_dims//",unknown_dim2,unknown_dim1,time"
           else if (fieldRank==4) then
              vdims=grid_dims//",unknown_dim3,unknown_dim2,unknown_dim1,time"
           else 
              _FAIL( 'Unsupported field rank')
           end if
        else
           if (fieldRank==1) then
              vdims = grid_dims
           elseif (fieldRank==2) then
              vdims=grid_dims//",unknown_dim1"
           else if (fieldRank==3) then
              vdims=grid_dims//",unknown_dim2,unkown_dim1"
           else
              _FAIL( 'Unsupported field rank')
           end if
        end if
        v = Variable(type=PFIO_REAL32,dimensions=vdims,chunksizes=this%chunking,deflation=this%deflateLevel,quantize_algorithm=this%quantizeAlgorithm,quantize_level=this%quantizeLevel,zstandard_level=this%zstandardLevel)
        call v%add_attribute('units',trim(units))
        call v%add_attribute('long_name',trim(longName))
        call v%add_attribute('standard_name',trim(longName))
        call v%add_attribute('missing_value',MAPL_UNDEF)
        call v%add_attribute('fmissing_value',MAPL_UNDEF)
        call v%add_attribute('_FillValue',MAPL_UNDEF)

        call this%metadata%add_variable(trim(varName),v,rc=status)
        _VERIFY(status)
        ! finally make a new field if neccessary
        newField = ESMF_FieldCreate(this%output_grid, name=trim(varName), typekind=ESMF_TYPEKIND_R4, _RC)
        call MAPL_FieldCopyAttributes(FIELD_IN=field, FIELD_OUT= newField, _RC)
        !MAPL_FieldCreate(field,this%output_grid,rc=status)
        !_VERIFY(status)
        call MAPL_FieldBundleAdd(this%output_bundle,newField,rc=status)
        _VERIFY(status)
        _RETURN(_SUCCESS)

     end subroutine CreateVariable

     subroutine CreateQuantizationInfo(this,rc)
        class (MAPL_TileGridIO), intent(inout) :: this
        integer, optional, intent(out) :: rc

        integer :: status

        _RETURN(_SUCCESS)

     end subroutine CreateQuantizationInfo

     subroutine bundlepost(this,filename,oClients,rc)
        class (MAPL_TileGridIO), target, intent(inout) :: this
        character(len=*), intent(in) :: filename
        type (ClientManager), optional, intent(inout) :: oClients
        integer, optional, intent(out) :: rc

        integer :: status
        type(ESMF_Field) :: outField
        integer :: tindex
        type(ArrayReference) :: ref

        type(GriddedIOitemVectorIterator) :: iter
        type(GriddedIOitem), pointer :: item
        logical :: have_time

        have_time = this%timeInfo%am_i_initialized()

        if (have_time) then
           this%times = this%timeInfo%compute_time_vector(this%metadata,rc=status)
           _VERIFY(status)
           ref = ArrayReference(this%times)
           call oClients%stage_nondistributed_data(this%write_collection_id,trim(filename),'time',ref)
           tindex = size(this%times)
           if (tindex==1) then
              call this%stage2DLatLon(filename,oClients=oClients,_RC)
           end if
        else
           tindex = -1
           call this%stage2DLatLon(filename,oClients=oClients,_RC)
        end if

        iter = this%items%begin()
        do while (iter /= this%items%end())
           item => iter%get()
           if (item%itemType == ItemTypeScalar) then
              call this%RegridScalar(item%xname,rc=status)
              _VERIFY(status)
              call ESMF_FieldBundleGet(this%output_bundle,item%xname,field=outField,rc=status)
              _VERIFY(status)
              call this%stageData(outField,filename,tIndex, oClients=oClients,rc=status)
              _VERIFY(status)
           else if (item%itemType == ItemTypeVector) then
              _FAIL('NO Vector for redistribution')
              !call this%RegridVector(item%xname,item%yname,rc=status)
              !_VERIFY(status)
              !call ESMF_FieldBundleGet(this%output_bundle,item%xname,field=outField,rc=status)
              !_VERIFY(status)
              !if (this%vdata%regrid_type==VERTICAL_METHOD_ETA2LEV .and. (this%vdata%extrap_below_surf .eqv. .false.)) then
              !   call this%vdata%correct_topo(outField,rc=status)
              !   _VERIFY(status)
              !end if
              !call this%stageData(outField,filename,tIndex,oClients=oClients,rc=status)
              !_VERIFY(status)
              !call ESMF_FieldBundleGet(this%output_bundle,item%yname,field=outField,rc=status)
              !_VERIFY(status)
              !if (this%vdata%regrid_type==VERTICAL_METHOD_ETA2LEV .and. (this%vdata%extrap_below_surf .eqv. .false.)) then
              !   call this%vdata%correct_topo(outField,rc=status)
              !   _VERIFY(status)
              !end if
              !call this%stageData(outField,filename,tIndex,oClients=oClients,rc=status)
              !_VERIFY(status)
              _FAIL('not yet implmented for tile vector')
           end if
           call iter%next()
        enddo

        _RETURN(ESMF_SUCCESS)

     end subroutine bundlepost

     subroutine RegridScalar(this,itemName,rc)
        class (MAPL_TileGridIO), intent(inout) :: this
        character(len=*), intent(in) :: itemName
        integer, optional, intent(out) :: rc

        integer :: status

        type(ESMF_Field) :: field,outField
        integer :: fieldRank, i
        real, pointer :: ptr3d(:,:,:),outptr3d(:,:,:)
        real, pointer :: ptr2d(:,:), outptr2d(:,:), ptr1d(:), outptr1d(:)
        real, allocatable, target :: ptr3d_inter(:,:,:)
        type(ESMF_Grid) :: gridIn,gridOut
        logical :: hasDE_in, hasDE_out, isPresent
        character(len=ESMF_MAXSTR) :: long_name

        ptr3d => null()

        call ESMF_FieldBundleGet(this%output_bundle,itemName,field=outField,rc=status)
        _VERIFY(status)
        call ESMF_FieldBundleGet(this%input_bundle,itemName,field=field,rc=status)
        _VERIFY(status)
        call ESMF_FieldGet(field,rank=fieldRank,rc=status)
        _VERIFY(status)

        
        if (fieldRank==1) then
           call ESMF_FieldRedist(field, outField, this%routeHandle, rc=status)
           _VERIFY(status)
        else if (fieldRank==2) then
           _FAIL('NO 2d for tile redistribution')
          !call MAPL_FieldGetPointer(Field,    ptr2d,rc=status)
          ! _VERIFY(status)
          ! call MAPL_FieldGetPointer(outField, outptr2d,rc=status)
          ! _VERIFY(status)
          ! call MAPL_FieldGetPointer(this%field_in,ptr1d,rc=status)
          ! _VERIFY(status)
          ! call MAPL_FieldGetPointer(this%field_out,outptr1d,rc=status)
          ! _VERIFY(status)
          ! do i =1, size(ptr2d, 2)
          !    ptr1d(:) = ptr2d(:,i)
          !    call ESMF_FieldRedist(this%field_in, this%field_out, this%routeHandle, rc=status)
          !    _VERIFY(status)
          !    outptr2d(:,i) = outptr1d(:)
          ! enddo

        else if (fieldRank==3) then

           _FAIL('rank not supported')
        end if

        if (allocated(ptr3d_inter)) deallocate(ptr3d_inter)
        _RETURN(_SUCCESS)

     end subroutine RegridScalar

     subroutine RegridVector(this,xName,yName,rc)
        class (MAPL_TileGridIO), intent(inout) :: this
        character(len=*), intent(in) :: xName
        character(len=*), intent(in) :: yName
        integer, optional, intent(out) :: rc
        _FAIL("No Vector for tile")
   end subroutine RegridVector

   ! this subroutine inherit form GriddedIO
   ! Now it is used to stage 1d latlon and II, JJ
   subroutine stage2DLatLon(this, fileName, oClients, rc)
     class (MAPL_TileGridIO), target, intent(inout) :: this
     character(len=*), intent(in) :: fileName
     type (ClientManager), optional, target, intent(inout) :: oClients
     integer, optional, intent(out) :: rc

     integer :: status
     integer :: i1, j1, in, jn, global_dim(3)
     type(ArrayReference), target :: ref
     integer, allocatable :: localStart(:),globalStart(:),globalCount(:)

     if (allocated(this%tilelons)) then
        call MAPL_GridGet(this%output_grid,globalCellCountPerDim=global_dim,_RC)
        call MAPL_GridGetInterior(this%output_grid,i1,in,j1,jn)
        allocate(localstart,source=[i1])
        allocate(globalstart,source=[1])
        allocate(globalcount,source=[global_dim(1)])
        ref = ArrayReference(this%tilelons)
        call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lon', &
             ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount)

        ref = ArrayReference(this%tilelats)
        call oClients%collective_stage_data(this%write_collection_id,trim(filename),'lat', &
             ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount)

        ref = ArrayReference(this%i_index)
        call oClients%collective_stage_data(this%write_collection_id,trim(filename),'IG', &
             ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount)
        
        ref = ArrayReference(this%j_index)
        call oClients%collective_stage_data(this%write_collection_id,trim(filename),'JG', &
             ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount)

     endif

     _RETURN(_SUCCESS)

   end subroutine stage2DLatLon

  subroutine stageData(this, field, fileName, tIndex, oClients, rc)
     class (MAPL_TileGridIO), intent(inout) :: this
     type(ESMF_Field), intent(inout) :: field
     character(len=*), intent(in) :: fileName
     integer, intent(in) :: tIndex
     type (ClientManager), optional, intent(inout) :: oClients
     integer, optional, intent(out) :: rc

     integer :: status
     integer :: fieldRank
     character(len=ESMF_MAXSTR) :: fieldName
     real, pointer :: ptr1d(:) => null()
     type(ArrayReference) :: ref
     logical :: hasDE
     integer, allocatable :: localStart(:),globalStart(:),globalCount(:)
     integer, allocatable :: gridLocalStart(:),gridGlobalStart(:),gridGlobalCount(:)
     real, allocatable :: temp_1d(:)
     type(ESMF_VM) :: vm
     integer :: mpi_comm, i1, in, j1, jn, global_dim(3)

     call ESMF_VMGetCurrent(vm,_RC)
     call ESMF_VMGet(vm,mpiCommunicator=mpi_comm,_RC)
     call MAPL_GridGet(this%output_grid,globalCellCountPerDim=global_dim,_RC)
     call MAPL_GridGetInterior(this%output_grid,i1,in,j1,jn)
     call ESMF_FieldGet(field,rank=fieldRank,name=fieldName,rc=status)
     _VERIFY(status)
     hasDE = MAPL_GridHasDE(this%output_grid, _RC)

     if (fieldRank == 1) then
       allocate(localstart,source=[i1])
       allocate(globalstart,source=[1])
       allocate(globalcount,source=[global_dim(1)])
       if ( hasDE ) then
         call ESMF_FieldGet(Field,farrayPtr=ptr1d, _RC)
         if (this%nbits_to_keep < MAPL_NBITS_UPPER_LIMIT) then
            allocate(temp_1d,source=ptr1d)
            call DownBit(temp_1d,ptr1d,this%nbits_to_keep,undef=MAPL_undef,mpi_comm=mpi_comm,rc=status)
            _VERIFY(status)
          end if
       else
         allocate(ptr1d(0))
       endif
       ref = ArrayReference(ptr1d)
     else
       _FAIL('only 1d so far')
     endif
     if (tindex > -1) then
        localstart  = [localstart,1]
        globalstart = [globalstart, tindex]
        globalcount = [globalcount, 1]
     endif
     call oClients%collective_stage_data(this%write_collection_id,trim(filename),trim(fieldName), &
           ref,start=localStart, global_start=GlobalStart, global_count=GlobalCount)
      _RETURN(_SUCCESS)

  end subroutine stageData

  subroutine request_data_from_file(this,filename,timeindex,rc)
     class(MAPL_TileGridIO), intent(inout) :: this
     character(len=*), intent(in) :: filename
     integer, intent(in) :: timeindex
     integer, intent(out), optional :: rc

     integer :: status
     integer :: num_vars,i,rank
     type(ArrayReference) :: ref
     character(len=ESMF_MAXSTR), allocatable :: names(:)
     type(ESMF_Field) :: field
     type(ESMF_Grid) :: grid
     integer :: counts(3)
     integer, allocatable :: local_start(:), global_start(:), global_count(:)


     call ESMF_FieldBundleGet(this%bundle, fieldCount=num_vars, _RC)
     allocate(this%tile_buffer(num_vars))
     allocate(names(num_vars))
     call ESMF_FieldBundleGet(this%bundle, fieldNameList=names, _RC)
     do i=1,num_vars
        call ESMF_FieldBundleGet(this%bundle,names(i),field=field,_RC)
        call ESMF_FieldGet(field,rank=rank,grid=grid,_RC)
        call MAPL_GridGet(grid,globalCellCountPerDim=counts,_RC)
        if (rank==1) then
           allocate(local_start(2),global_start(2),global_count(2))
           local_start = [1,timeindex]
           global_start = [1,timeindex]
           global_count = [counts(1),1]
           if (mapl_am_I_root()) then
              allocate(this%tile_buffer(i)%ptr(counts(1)),_STAT)
           else
              allocate(this%tile_buffer(i)%ptr((0)),_STAT)
           end if
           ref = ArrayReference(this%tile_buffer(i)%ptr)
           call i_clients%collective_prefetch_data(this%read_collection_id, filename, trim(names(i)), ref,  &
              start=local_start, global_start=global_start, global_count = global_count, _RC)
           deallocate(local_start,global_start,global_count)
        else
           _FAIL("rank >1 tile fields not supported")
        end if
     end do

     _RETURN(_SUCCESS)   

  end subroutine request_data_from_file

  subroutine process_data_from_file(this,rc)
     class(MAPL_TileGridIO), intent(inout) :: this
     integer, intent(out), optional :: rc

     integer :: status
     integer :: i,num_vars,rank
     type(ESMF_Field) :: field
     character(len=ESMF_MAXSTR), allocatable :: names(:)
     type(ESMF_Grid) :: grid
     integer, pointer :: mask(:)
     real, pointer :: ptr1d(:)

     call ESMF_FieldBundleGet(this%bundle, fieldCount=num_vars, _RC)
     allocate(names(num_vars))
     call ESMF_FieldBundleGet(this%bundle, fieldNameList=names, _RC)
     do i=1,num_vars
        call ESMF_FieldBundleGet(this%bundle,names(i),field=field,_RC)
        call ESMF_FieldGet(field,rank=rank,grid=grid,_RC)
        call MAPL_TileMaskGet(grid,mask,_RC)
        if (rank==1) then
           call ESMF_FieldGet(field,localDE=0,farrayPtr=ptr1d,_RC)
           call ArrayScatter(ptr1d,this%tile_buffer(i)%ptr,grid,mask=mask,_RC)
           deallocate(this%tile_buffer(i)%ptr)
        else
           _FAIL("rank not supported for tile io")
        end if
     enddo
     deallocate(this%tile_buffer)
     _RETURN(_SUCCESS)

  end subroutine process_data_from_file

  subroutine swap_undef_value(this,fname,rc)
     class (MAPL_TileGridIO), intent(inout) :: this
     character(len=*), intent(in) :: fname
     integer, optional, intent(out) :: rc

     integer :: status

     type(ESMF_Field) :: field
     integer :: fieldRank
     real, pointer :: ptr3d(:,:,:)
     real, pointer :: ptr2d(:,:)
     real, pointer :: ptr1d(:)
     type(ESMF_Grid) :: gridIn
     logical :: hasDE_in
     real(REAL32) :: fill_value

     if ( .not. this%current_file_metadata%var_has_missing_value(fname) ) then
        _RETURN(_SUCCESS)
     endif

     fill_value = this%current_file_metadata%var_get_missing_value(fname,_RC)

     call ESMF_FieldBundleGet(this%input_bundle,fname,field=field,_RC)
     call ESMF_FieldBundleGet(this%input_bundle,grid=gridIn,_RC)
     call ESMF_FieldGet(field,rank=fieldRank,_RC)
     hasDE_in = MAPL_GridHasDE(gridIn,_RC)

     if (fieldRank==1) then
        if (hasDE_in) then
           call MAPL_FieldGetPointer(field,ptr1d,_RC)
        else
           allocate(ptr1d(0))
        end if

        if (isnan(fill_value)) then
           where(isnan(ptr1d)) ptr1d=MAPL_UNDEF
        else
           where(ptr1d==fill_value) ptr1d=MAPL_UNDEF
        endif
     else if (fieldRank==2) then
        if (hasDE_in) then
           call MAPL_FieldGetPointer(field,ptr2d,_RC)
        else
           allocate(ptr2d(0,0))
        end if

        if (isnan(fill_value)) then
           where(isnan(ptr2d)) ptr2d=MAPL_UNDEF
        else
           where(ptr2d==fill_value) ptr2d=MAPL_UNDEF
        endif

     else if (fieldRank==3) then
        if (hasDE_in) then
           call ESMF_FieldGet(field,farrayPtr=ptr3d,_RC)
        else
           allocate(ptr3d(0,0,0))
        end if

        if (isnan(fill_value)) then
           where(isnan(ptr3d)) ptr3d=MAPL_UNDEF
        else
           where(ptr3d==fill_value) ptr3d=MAPL_UNDEF
        endif

     else
        _FAIL('rank not supported')
     end if

     _RETURN(_SUCCESS)

  end subroutine swap_undef_value

  subroutine destroy(this, rc)
     class (MAPL_TileGridIO), intent(inout) :: this
     integer, intent(out), optional :: rc
     integer :: status
     if(allocated(this%chunking)) deallocate(this%chunking)
     call ESMF_FieldRedistRelease(this%routeHandle, _RC)
     call MAPL_FieldBundleDestroy(this%output_bundle, _RC)
     call ESMF_FieldDestroy(this%field_in, noGarbage=.true., _RC)
     call ESMF_FieldDestroy(this%field_out,noGarbage=.true., _RC)
     _RETURN(_SUCCESS)
  end subroutine destroy

  subroutine InitRedistHandle(this, rc)
     class (MAPL_TileGridIO), intent(inout) :: this
     integer, intent(out), optional :: rc


     type(ESMF_Grid) :: tilegrid, ordered_tilegrid
     integer, pointer :: local_id(:), local_i(:), local_j(:)
     real, pointer    :: tilelons(:), tilelats(:), ptr1d(:), outptr1d(:)
     integer, allocatable :: global_id(:)
     integer              :: nt_global, i1, i2, j1, j2, status
     type (ESMF_DistGrid)              :: distgrid
     integer                           :: arbIndexCount
     integer, allocatable              :: arbIndex(:,:)
     integer(kind=INT64)               :: ADDR
     type (MAPL_LocStream)             :: locstream
     character(len=ESMF_MAXSTR)        :: gname
     type(ESMF_GRID)                   :: attachedgrid  

     call ESMF_FieldBundleGet(this%input_bundle,grid=tilegrid,rc=status)
     _VERIFY(status)
     call ESMF_AttributeGet(tilegrid, name='TILEGRID_LOCSTREAM_ADDR', &
              value=ADDR, _RC)
     call c_MAPL_LocStreamRestorePtr(locstream, ADDR)
     call MAPL_LocStreamGet(locstream, nt_global = nt_global, local_id = local_id, &
                            local_i  = local_i, local_j  = local_j,                &
                            tilelons = tilelons,    tilelats = tilelats, _RC)

     allocate(global_id(nt_global))
     call ESMFL_FCollect(tilegrid, global_id, local_id, _RC)
     call MAPL_grid_interior(tilegrid, i1, i2, j1, j2)
     call MAPL_Sort(global_id)  
     call ESMF_GridGet(tilegrid, name=gname, _RC)

     distgrid = ESMF_DistGridCreate( & 
         arbSeqIndexList=global_id(i1:i2), rc=status)
     _VERIFY(STATUS)

     ordered_TILEGRID = ESMF_GridEmptyCreate(rc=status)
     _VERIFY(STATUS)
     arbIndexCount = i2-i1 +1
     allocate(arbIndex(arbIndexCount,1))
     arbIndex(:,1) = global_id(i1:i2)
     gname = 'ordered_'//trim(gname)
     call ESMF_GridSet(ordered_tilegrid,  &
         name=trim(gname),        &
         distgrid=distgrid, &
         indexFlag=ESMF_INDEX_DELOCAL, &
         distDim = (/1/), &
         localArbIndexCount=arbIndexCount, &
         localArbIndex=arbIndex, &
         minIndex=(/1/), &
         maxIndex=(/NT_GLOBAL/), &
         rc=status)
     _VERIFY(STATUS)
      
     call ESMF_GridCommit(ordered_tilegrid, rc=status)
    _VERIFY(STATUS)   
     this%field_in  = ESMF_FieldCreate(grid=tilegrid,  typekind=ESMF_TYPEKIND_R4, _RC)
     this%field_out = ESMF_FieldCreate(grid=ordered_tilegrid, typekind=ESMF_TYPEKIND_R4, _RC)
     this%output_grid = ordered_tilegrid
   
     call ESMF_FieldRedistStore(srcField= this%field_in, dstField=this%field_out, &
                routehandle=this%routehandle, _RC)

     ! reordered lat-lon, II, and JJ
     if (associated(tilelons) .and. associated(tilelats) .and. associated(local_i) .and. associated(local_j)) then 
        allocate(this%tilelons(arbIndexCount), this%tilelats(arbIndexCount))
        allocate(this%i_index(arbIndexCount),  this%j_index(arbIndexCount))
        call MAPL_FieldGetPointer(this%field_in, ptr1d,rc=status)
        call MAPL_FieldGetPointer(this%field_out,outptr1d,rc=status)

        call MAPL_LocStreamGet(locstream, attachedgrid=attachedgrid, _RC)
        call MAPL_grid_interior(attachedgrid, i1, i2, j1, j2)
        call ESMF_GridGet(attachedgrid, name=gname, _RC)

        ptr1d(:) = tilelons(:)
        call ESMF_FieldRedist(this%field_in, this%field_out, this%routeHandle, rc=status)
        this%tilelons = outptr1d*MAPL_RADIANS_TO_DEGREES

        ptr1d(:) = tilelats(:)
        call ESMF_FieldRedist(this%field_in, this%field_out, this%routeHandle, rc=status)
        this%tilelats = outptr1d*MAPL_RADIANS_TO_DEGREES

        ptr1d(:) = local_i(:) + i1 -1
        if (index(gname, 'EASE') /=0) ptr1d = ptr1d - 1
        call ESMF_FieldRedist(this%field_in, this%field_out, this%routeHandle, rc=status)
        this%i_index = nint(outptr1d)

        ptr1d(:) = local_j(:) + j1 -1
        if (index(gname, 'EASE') /=0) ptr1d = ptr1d - 1
        call ESMF_FieldRedist(this%field_in, this%field_out, this%routeHandle, rc=status)
        this%j_index = nint(outptr1d) 
     endif
     _RETURN(_SUCCESS)
     
  end subroutine  

end module MAPL_TileGridIOMod