ExtDataGridCompMod.F90 Source File


This file depends on

sourcefile~~extdatagridcompmod.f90~~EfferentGraph sourcefile~extdatagridcompmod.f90 ExtDataGridCompMod.F90 sourcefile~base_base.f90 Base_Base.F90 sourcefile~extdatagridcompmod.f90->sourcefile~base_base.f90 sourcefile~cfiocollection.f90 CFIOCollection.F90 sourcefile~extdatagridcompmod.f90->sourcefile~cfiocollection.f90 sourcefile~clientmanager.f90 ClientManager.F90 sourcefile~extdatagridcompmod.f90->sourcefile~clientmanager.f90 sourcefile~constants.f90 Constants.F90 sourcefile~extdatagridcompmod.f90->sourcefile~constants.f90 sourcefile~datacollection.f90 DataCollection.F90 sourcefile~extdatagridcompmod.f90->sourcefile~datacollection.f90 sourcefile~datacollectionmanager.f90 DataCollectionManager.F90 sourcefile~extdatagridcompmod.f90->sourcefile~datacollectionmanager.f90 sourcefile~esmf_cfiofilemod.f90 ESMF_CFIOFileMod.F90 sourcefile~extdatagridcompmod.f90->sourcefile~esmf_cfiofilemod.f90 sourcefile~esmf_cfiomod.f90 ESMF_CFIOMod.F90 sourcefile~extdatagridcompmod.f90->sourcefile~esmf_cfiomod.f90 sourcefile~esmf_cfioutilmod.f90 ESMF_CFIOUtilMod.F90 sourcefile~extdatagridcompmod.f90->sourcefile~esmf_cfioutilmod.f90 sourcefile~esmfl_mod.f90 ESMFL_Mod.F90 sourcefile~extdatagridcompmod.f90->sourcefile~esmfl_mod.f90 sourcefile~extdata_iobundlemod.f90 ExtData_IOBundleMod.F90 sourcefile~extdatagridcompmod.f90->sourcefile~extdata_iobundlemod.f90 sourcefile~extdata_iobundlevectormod.f90 ExtData_IOBundleVectorMod.F90 sourcefile~extdatagridcompmod.f90->sourcefile~extdata_iobundlevectormod.f90 sourcefile~filemetadatautilities.f90 FileMetadataUtilities.F90 sourcefile~extdatagridcompmod.f90->sourcefile~filemetadatautilities.f90 sourcefile~griddedioitem.f90 GriddedIOitem.F90 sourcefile~extdatagridcompmod.f90->sourcefile~griddedioitem.f90 sourcefile~mapl_cfio.f90 MAPL_CFIO.F90 sourcefile~extdatagridcompmod.f90->sourcefile~mapl_cfio.f90 sourcefile~mapl_comms.f90 MAPL_Comms.F90 sourcefile~extdatagridcompmod.f90->sourcefile~mapl_comms.f90 sourcefile~mapl_config.f90 MAPL_Config.F90 sourcefile~extdatagridcompmod.f90->sourcefile~mapl_config.f90 sourcefile~mapl_exceptionhandling.f90 MAPL_ExceptionHandling.F90 sourcefile~extdatagridcompmod.f90->sourcefile~mapl_exceptionhandling.f90 sourcefile~mapl_generic.f90 MAPL_Generic.F90 sourcefile~extdatagridcompmod.f90->sourcefile~mapl_generic.f90 sourcefile~mapl_gridmanager.f90 MAPL_GridManager.F90 sourcefile~extdatagridcompmod.f90->sourcefile~mapl_gridmanager.f90 sourcefile~mapl_io.f90 MAPL_IO.F90 sourcefile~extdatagridcompmod.f90->sourcefile~mapl_io.f90 sourcefile~mapl_newarthparser.f90 MAPL_NewArthParser.F90 sourcefile~extdatagridcompmod.f90->sourcefile~mapl_newarthparser.f90 sourcefile~mapl_simplealarm.f90 MAPL_SimpleAlarm.F90 sourcefile~extdatagridcompmod.f90->sourcefile~mapl_simplealarm.f90 sourcefile~mapl_verticalinterpmod.f90 MAPL_VerticalInterpMod.F90 sourcefile~extdatagridcompmod.f90->sourcefile~mapl_verticalinterpmod.f90 sourcefile~pflogger_stub.f90 pflogger_stub.F90 sourcefile~extdatagridcompmod.f90->sourcefile~pflogger_stub.f90 sourcefile~regridmethods.f90 RegridMethods.F90 sourcefile~extdatagridcompmod.f90->sourcefile~regridmethods.f90 sourcefile~shmem.f90 Shmem.F90 sourcefile~extdatagridcompmod.f90->sourcefile~shmem.f90 sourcefile~stringtemplate.f90 StringTemplate.F90 sourcefile~extdatagridcompmod.f90->sourcefile~stringtemplate.f90 sourcefile~varspec.f90 VarSpec.F90 sourcefile~extdatagridcompmod.f90->sourcefile~varspec.f90

Files dependent on this one

sourcefile~~extdatagridcompmod.f90~~AfferentGraph sourcefile~extdatagridcompmod.f90 ExtDataGridCompMod.F90 sourcefile~extdatadrivergridcomp.f90 ExtDataDriverGridComp.F90 sourcefile~extdatadrivergridcomp.f90->sourcefile~extdatagridcompmod.f90 sourcefile~mapl_capgridcomp.f90 MAPL_CapGridComp.F90 sourcefile~mapl_capgridcomp.f90->sourcefile~extdatagridcompmod.f90 sourcefile~ut_extdata.f90 ut_ExtData.F90 sourcefile~ut_extdata.f90->sourcefile~extdatagridcompmod.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 sourcefile~mapl.f90 MAPL.F90 sourcefile~mapl.f90->sourcefile~mapl_gridcomps.f90

Source Code

!------------------------------------------------------------------------------
!               Global Modeling and Assimilation Office (GMAO)                !
!                    Goddard Earth Observing System (GEOS)                    !
!                                 MAPL Component                              !
!------------------------------------------------------------------------------
!
!#include "MAPL_Exceptions.h"
#include "MAPL_Generic.h"
#include "unused_dummy.H"
!
!>
!### MODULE: `MAPL_ExtDataGridCompMod`
!
! Author: GMAO SI-Team
!
! `MAPL_ExtDataGridCompMod` - Implements Interface to External Data.
!
! This module is an ESMF gridded component implementing
! an interface to boundary conditions and other types of external data
! files.
!
! It was developed for GEOS-5 release Fortuna 2.0 and later.
!
!#### History
!- 12Dec2009  da Silva  Design and first implementation.
!
   MODULE MAPL_ExtDataGridCompMod
!
! !USES:
!
   USE ESMF
   use MAPL_GenericMod, only: MAPL_GenericSetServices, MAPL_GenericInitialize, MAPL_GenericFinalize
   use MAPL_GenericMod, only: MAPL_TimerOn, MAPL_TimerOff, MAPL_GetLogger
   use MAPL_GenericMod, only: MAPL_MetaComp, MAPL_GetObjectFromGC, MAPL_GridCompSetEntryPoint
   use MAPL_BaseMod
   use MAPL_CommsMod
   use MAPL_ShmemMod
   use ESMFL_Mod
   use MAPL_VarSpecMod
   use ESMF_CFIOFileMod
   use ESMF_CFIOMod
   use ESMF_CFIOUtilMod
   use MAPL_CFIOMod
   use MAPL_NewArthParserMod
   use MAPL_Constants, only: MAPL_PI,MAPL_PI_R8,MAPL_RADIANS_TO_DEGREES,MAPL_CF_COMPONENT_SEPARATOR
   use MAPL_IOMod, only: MAPL_NCIOParseTimeUnits
   use mapl_RegridMethods
   use, intrinsic :: iso_fortran_env, only: REAL64
   use linearVerticalInterpolation_mod
   use ESMF_CFIOCollectionVectorMod
   use ESMF_CFIOCollectionMod
   use MAPL_ConfigMod
   use MAPL_GridManagerMod
   use MAPL_ExtData_IOBundleMod
   use MAPL_ExtData_IOBundleVectorMod
   use MAPL_ExceptionHandling
   use MAPL_DataCollectionMod
   use MAPL_CollectionVectorMod
   use MAPL_DataCollectionManagerMod
   use MAPL_FileMetadataUtilsMod
   use pFIO_ClientManagerMod, only : i_Clients
   use MAPL_GriddedIOItemMod
   use MAPL_GriddedIOItemVectorMod
   use MAPL_SimpleAlarm
   use MAPL_StringTemplate
   use pFlogger

   IMPLICIT NONE
   PRIVATE
!
! !PUBLIC MEMBER FUNCTIONS:

   PUBLIC SetServices
!
!-------------------------------------------------------------------------

  character(len=ESMF_MAXSTR) :: Ext_TilePath
  integer, parameter         :: MAPL_ExtDataVectorItem    = 32
  integer, parameter         :: MAPL_ExtDataNullFrac      = -9999
  integer, parameter         :: MAPL_ExtDataLeft          = 1
  integer, parameter         :: MAPL_ExtDataRight         = 2
  logical                    :: hasRun
  character(len=ESMF_MAXSTR) :: error_msg_str

  type BracketingFields
     ! fields to store endpoints for interpolation of a vector pair
     type(ESMF_Field)             :: v1_finterp1, v1_finterp2
     type(ESMF_Field)             :: v2_finterp1, v2_finterp2
     ! if vertically interpolating vector fields
     type(ESMF_Field)             :: v1_faux1, v1_faux2
     type(ESMF_Field)             :: v2_faux1, v2_faux2
  end type BracketingFields

! Primary Exports
! ---------------
  type PrimaryExport
     PRIVATE
     character(len=ESMF_MAXSTR)   :: name
     character(len=ESMF_MAXSTR)   :: units
     integer                      :: dim
     integer                      :: vloc
     character(len=ESMF_MAXSTR)   :: cyclic
     character(len=ESMF_MAXSTR)   :: refresh_template
     integer                      :: Trans
     real                         :: scale, offset
     logical                      :: do_offset, do_scale
     character(len=ESMF_MAXSTR)   :: var
     character(len=ESMF_MAXPATHLEN)   :: file
     logical                      :: hasFileReffTime
     character(len=ESMF_MAXSTR)   :: FileReffTime

     type(ESMF_Time), pointer     :: refresh_time => null()
     logical                      :: doInterpolate = .true.
     logical                      :: isConst
     real                         :: Const
     integer                      :: vartype !! MAPL_FieldItem or MAPL_BundleItem

     type(ESMF_FieldBundle)       :: binterp1, binterp2
     type(ESMF_Time)              :: time1, time2
     type(ESMF_Time)              :: interp_time1, interp_time2
     integer                      :: tindex1,tindex2
     integer                      :: climyear
     type(ESMF_TimeInterval)      :: frequency
     type(ESMF_Time)              :: reff_time

     ! if primary export represents a pair of vector fields
     logical                      :: isVector, foundComp1, foundComp2
     type(BracketingFields)       :: modelGridFields
     type(BracketingFields)       :: fileLevelFields

     ! names of the two vector components in the gridded component where import is declared
     character(len=ESMF_MAXSTR)   :: vcomp1, vcomp2
     ! the corresponding names of the two vector components on file
     character(len=ESMF_MAXSTR)   :: fcomp1, fcomp2
     type(GriddedIOitem)            :: fileVars
     type(SimpleAlarm)            :: update_alarm

     integer                      :: collection_id
     integer                      :: pfioCollection_id
     integer                      :: iclient_collection_id

     logical                      :: ExtDataAlloc
     ! time shifting during continuous update
     type(ESMF_TimeInterval)      :: tshift
     logical                      :: alarmIsEnabled = .false.
     integer                      :: FracVal = MAPL_ExtDataNullFrac
     ! do we have to do vertical interpolation
     logical                      :: do_VertInterp = .false.
     logical                      :: do_Fill = .false.
     integer                      :: LM
     real, allocatable            :: levs(:)
     character(len=4)             :: importVDir = "down"
     character(len=4)             :: fileVDir = "down"
     character(len=ESMF_MAXSTR)   :: levUnit
     logical                      :: havePressure = .false.
  end type PrimaryExport

  type PrimaryExports
     PRIVATE
     integer :: nItems = 0
     logical :: have_phis
     type(PrimaryExport), pointer :: item(:) => null()
  end type PrimaryExports

  type DerivedExport
     PRIVATE
     character(len=ESMF_MAXSTR)     :: name
     character(len=ESMF_MAXPATHLEN) :: expression
     character(len=ESMF_MAXSTR)     :: refresh_template
     logical                        :: ExtDataAlloc
     logical                        :: masking
     type(ESMF_Time), pointer       :: refresh_time => null()
     ! time shifting during continuous update
     type(ESMF_TimeInterval)      :: tshift
     type(SimpleAlarm)            :: update_alarm
     logical                      :: alarmIsEnabled = .false.
  end type DerivedExport

  type DerivedExports
     PRIVATE
     integer :: nItems = 0
     type(DerivedExport), pointer :: item(:) => null()
  end type DerivedExports

! Legacy state
! ------------
  type MAPL_ExtData_State
     PRIVATE
     type(PrimaryExports) :: Primary
     type(DerivedExports) :: Derived
     ! will add fields from export state to this state
     ! will also add new fields that could be mask
     ! or primary exports that were not in the export
     ! state recieved by ExtData, i.e. fields that are
     ! needed by a derived field where the primary fields
     ! are not actually required
     type(ESMF_State)     :: ExtDataState
     type(ESMF_Config)    :: CF
     logical              :: active
     logical              :: ignoreCase
     logical              :: AllowExtrap
     integer, allocatable :: PrimaryOrder(:)
     integer              :: blocksize
     logical              :: prefetch
     logical              :: distributed_trans
     logical              :: use_file_coords
  end type MAPL_ExtData_State

! Hook for the ESMF
! -----------------
  type MAPL_ExtData_Wrap
     type (MAPL_ExtData_State), pointer :: PTR => null()
  end type MAPL_ExtData_WRAP

  class(Logger), pointer :: lgr


CONTAINS


!-------------------------------------------------------------------------
!     NASA/GSFC, Global Modeling and Assimilation Office, Code 910.1     !
!-------------------------------------------------------------------------
!>
! `SetServices` --- Sets IRF services for the MAPL_ExtData
!
! Sets Initialize, Run and Finalize services.
!
!#### History
!- 12Dec2009  da Silva  Design and first implementation.
!
   SUBROUTINE SetServices ( GC, RC )

    type(ESMF_GridComp), intent(INOUT) :: GC  !! gridded component
    integer, optional                  :: RC  !! return code
!
!-------------------------------------------------------------------------

!   Local derived type aliases
!   --------------------------
    type (MAPL_ExtData_State), pointer  :: self   ! internal, that is
    type (MAPL_ExtData_wrap)            :: wrap

    character(len=ESMF_MAXSTR)          :: comp_name
    character(len=ESMF_MAXSTR)          :: Iam
    integer                             :: status

!                              ------------

!   Get my name and set-up traceback handle
!   ---------------------------------------
    Iam = 'SetServices'
    call ESMF_GridCompGet( GC, name=comp_name, _RC )
    Iam = trim(comp_name) // '::' // trim(Iam)

!   Wrap internal state for storing in GC; rename legacyState
!   -------------------------------------
    allocate ( self, stat=STATUS )
    _VERIFY(STATUS)
    wrap%ptr => self

!                       ------------------------
!                       ESMF Functional Services
!                       ------------------------

!   Set the Initialize, Run, Finalize entry points
!   ----------------------------------------------
    call MAPL_GridCompSetEntryPoint ( GC, ESMF_METHOD_INITIALIZE,  Initialize_, _RC )
    call MAPL_GridCompSetEntryPoint ( GC, ESMF_METHOD_RUN,   Run_,        _RC )
    call MAPL_GridCompSetEntryPoint ( GC, ESMF_METHOD_FINALIZE, Finalize_,   _RC )

!   Store internal state in GC
!   --------------------------
    call ESMF_UserCompSetInternalState ( GC, 'MAPL_ExtData_state', wrap, STATUS )
    _VERIFY(STATUS)


!   Generic Set Services
!   --------------------
    call MAPL_GenericSetServices ( GC, _RC )

!   All done
!   --------

    _RETURN(ESMF_SUCCESS)

  END SUBROUTINE SetServices


!-------------------------------------------------------------------------
!     NASA/GSFC, Global Modeling and Assimilation Office, Code 610.1     !
!-------------------------------------------------------------------------
!>
!  `Initialize_` --- Initialize MAPL_ExtData
!
! This is a simple ESMF wrapper.
!
!#### History
!- 12Dec2009  da Silva  Design and first implementation.
!
   SUBROUTINE Initialize_ ( GC, IMPORT, EXPORT, CLOCK, rc )

! !USES:

   implicit NONE

! !INPUT PARAMETERS:

   type(ESMF_Clock),  intent(inout)   :: CLOCK   ! The clock

! !OUTPUT PARAMETERS:

   type(ESMF_GridComp), intent(inout) :: GC      !! Grid Component
   type(ESMF_State), intent(inout)    :: IMPORT  !! Import State
   type(ESMF_State), intent(inout)    :: EXPORT  !! Export State
   integer, intent(out)               :: rc      !! Error return code:
                                                 !!  0 - all is well
                                                 !!  1 -
!
!-------------------------------------------------------------------------

   type(MAPL_ExtData_state), pointer :: self        ! Legacy state
   type(ESMF_Grid)                   :: GRID        ! Grid
   type(ESMF_Config)                 :: CF_main          ! Universal Config

   character(len=ESMF_MAXSTR)        :: comp_name
   character(len=ESMF_MAXSTR)        :: Iam
   integer                           :: Status
   character(len=ESMF_MAXSTR)        :: buffer

   type(PrimaryExports)              :: Primary
   type(PrimaryExport), pointer      :: item
   type(DerivedExports)              :: Derived
   type(DerivedExport), pointer      :: derivedItem
   integer                           :: nLines
   integer                           :: i
   integer                           :: ItemCount, itemCounter, j
   integer                           :: PrimaryItemCount, DerivedItemCount
   logical                           :: found

   type(ESMF_Time)                   :: time
   character(len=ESMF_MAXSTR)        :: VarName

   type (ESMF_Field)                 :: field,fieldnew
   integer                           :: fieldRank, lm
   type (ESMF_FieldBundle)           :: bundle
   integer                           :: fieldcount
   type (ESMF_StateItem_Flag), pointer    :: ITEMTYPES(:)
   character(len=ESMF_MAXSTR), allocatable   :: ITEMNAMES(:)

   character(len=ESMF_MAXSTR),allocatable    :: PrimaryVarNames(:)
   character(len=ESMF_MAXSTR),allocatable    :: VarNames(:)
   integer                                   :: NumVarNames

!  logical to keep track of primary variables needed by derived fields, that ARE NOT in export state
   logical, allocatable              :: PrimaryVarNeeded(:)
   logical, allocatable              :: DerivedVarNeeded(:)
   logical, allocatable              :: LocalVarNeeded(:)

   type(FileMetadataUtils), pointer  :: metadata
   integer                           :: counter
   real, pointer                     :: ptr2d(:,:) => null()
   real, pointer                     :: ptr3d(:,:,:) => null()
   integer                           :: k, ios
   character(len=ESMF_MAXSTR)        :: c_offset, c_scale
   character(len=ESMF_MAXSTR)        :: EXTDATA_CF
   type(ESMF_Config) :: CFtemp
   integer           :: totalPrimaryEntries
   integer           :: totalDerivedEntries
   logical           :: caseSensitiveVarNames
   character(len=ESMF_MAXSTR) :: component1,component2
   character(len=ESMF_MAXPATHLEN) :: expression
   integer           :: idx,nhms,ihr,imn,isc,tsteps
   logical           :: isNegative
   character(len=ESMF_MAXPATHLEN) :: thisLine
   logical           :: inBlock
   type(ESMF_VM) :: vm
   type(MAPL_MetaComp),pointer :: MAPLSTATE
   type(ESMF_StateItem_Flag)   :: itemType


!  Get my name and set-up traceback handle
!  ---------------------------------------
   Iam = 'Initialize_'
   call ESMF_GridCompGet( GC, name=comp_name, config=CF_main, _RC )
   Iam = trim(comp_name) // '::' // trim(Iam)

!  Extract relevant runtime information
!  ------------------------------------
   call extract_ ( GC, self, CF_main, _RC)
   self%CF = CF_main

!  Get the GC pFlogger
!  -------------------
   call MAPL_GetLogger(gc, lgr, _RC)

!  Start Some Timers
!  -----------------
   call MAPL_GetObjectFromGC ( gc, MAPLSTATE, RC=STATUS)
   _VERIFY(STATUS)
   call MAPL_TimerOn(MAPLSTATE,"Initialize")

! Get information from export state
!----------------------------------
    call ESMF_StateGet(EXPORT, ITEMCOUNT=ItemCount, RC=STATUS)
    _VERIFY(STATUS)

    ! set ExtData on by default, let user turn it off if they want
    call ESMF_ConfigGetAttribute(CF_main,self%active, Label='USE_EXTDATA:',default=.true.,rc=status)

    ! set extdata to ignore case on variable names in files
    call ESMF_ConfigGetAttribute(CF_main,caseSensitiveVarNames, Label='CASE_SENSITIVE_VARIABLE_NAMES:',default=.false.,rc=status)
    self%ignoreCase = .not. caseSensitiveVarNames

    ! no need to run ExtData if there are no imports to fill
    if (ItemCount == 0) then
       self%active = .false.
    end if

    if (.not.self%active) then
       call MAPL_TimerOff(MAPLSTATE,"Initialize")
       _RETURN(ESMF_SUCCESS)
    end if

!   Greetings
    !   ---------
    call lgr%info('%a~: ACTIVE \n', Iam)

    allocate(ITEMNAMES(ITEMCOUNT), STAT=STATUS)
    _VERIFY(STATUS)
    allocate(ITEMTYPES(ITEMCOUNT), STAT=STATUS)
    _VERIFY(STATUS)

    call ESMF_StateGet(EXPORT, ITEMNAMELIST=ITEMNAMES, &
                       ITEMTYPELIST=ITEMTYPES, RC=STATUS)
    _VERIFY(STATUS)

!                               --------
!  Initialize MAPL Generic
!  -----------------------
   call MAPL_GenericInitialize ( GC, IMPORT, EXPORT, clock,  _RC )


!                         ---------------------------
!                         Parse ExtData Resource File
!                         ---------------------------

   call ESMF_ConfigGetAttribute(CF_main,value=EXTDATA_CF,Label="CF_EXTDATA:",rc=status)
   _VERIFY(STATUS)
   call ESMF_ConfigGetAttribute(CF_main,value=self%allowExtrap,Label="Ext_AllowExtrap:", default=.false., rc=status)
   _VERIFY(STATUS)
   call ESMF_ConfigGetAttribute(CF_main,value=self%blocksize,label="BlockSize:",default=1,rc=status)
   call ESMF_ConfigGetAttribute(CF_main,value=self%prefetch,label="Prefetch:",default=.true.,rc=status)

   call ESMF_ConfigGetAttribute(CF_main,value=self%distributed_trans,Label="CONSERVATIVE_DISTRIBUTED_TRANS:",default=.false., rc=status)
   _VERIFY(STATUS)
   call ESMF_ConfigGetAttribute(CF_main,value=self%use_file_coords,Label="Use_File_Coords:",default=.false., rc=status)
   _VERIFY(status)

   CFtemp = ESMF_ConfigCreate (rc=STATUS )
   _VERIFY(STATUS)
   call ESMF_ConfigLoadFile(CFtemp,EXTDATA_CF,rc=status)
   _VERIFY(STATUS)

   totalPrimaryEntries=0
   totalDerivedEntries=0
   call ESMF_ConfigNextLine(CFtemp,_RC)
   do while (status == ESMF_SUCCESS)
      call ESMF_ConfigNextLine(CFtemp,rc=status)
      if (status == ESMF_SUCCESS) then
         call ESMF_ConfigGetAttribute(CFtemp,thisLine,rc=status)
         _VERIFY(STATUS)
         if (trim(thisLine) == "PrimaryExports%%" .or. trim(thisLine) == "DerivedExports%%" ) then
             call advanceAndCount(CFtemp,nLines,rc=status)
             _VERIFY(STATUS)
            select case (trim(thisLine))
               case ("PrimaryExports%%")
                   totalPrimaryEntries = totalPrimaryEntries + nLines
               case ("DerivedExports%%")
                   totalDerivedEntries = totalDerivedEntries + nLines
            end select
         end if
      end if
   enddo
   ! destroy the config and reopen since there is no rewind function
   call ESMF_ConfigDestroy(CFtemp,rc=status)
   _VERIFY(STATUS)

   call lgr%debug('ExtData Initialize_(): Start')

   primary%nItems = totalPrimaryEntries
   if (totalPrimaryEntries > 0) then
      allocate (PrimaryVarNames(totalPrimaryEntries), stat=STATUS)
      _VERIFY(STATUS)
      allocate (PrimaryVarNeeded(totalPrimaryEntries), stat=STATUS)
      _VERIFY(STATUS)
      PrimaryVarNeeded = .false.
      allocate(primary%item(totalPrimaryEntries), stat=STATUS)
      _VERIFY(STATUS)
   end if

   derived%nItems = totalDerivedEntries
   if (totalDerivedEntries > 0) then
      Allocate(DerivedVarNeeded(totalDerivedEntries),stat=status)
      _VERIFY(STATUS)
      DerivedVarNeeded = .false.
      allocate(derived%item(totalDerivedEntries),stat=status)
      _VERIFY(STATUS)
   end if

!  Primary Exports
!  ---------------

   totalPrimaryEntries = 0
   totalDerivedEntries = 0
   ! reload file and parse it
   CFtemp = ESMF_ConfigCreate (rc=STATUS )
   _VERIFY(STATUS)
   call ESMF_ConfigLoadFile(CFtemp,EXTDATA_CF,rc=status)
   _VERIFY(STATUS)
   call ESMF_ConfigNextLine(CFtemp,_RC)
   do while(status == ESMF_SUCCESS)

      call ESMF_ConfigNextLine(CFtemp,rc=status)
      if (status == ESMF_SUCCESS) then
         call ESMF_ConfigGetAttribute(CFtemp,thisLine,rc=status)
         if (trim(thisLine) == "PrimaryExports%%" .or. trim(thisLine) == "DerivedExports%%" ) then
            select case (trim(thisLine))
               case ("PrimaryExports%%")
                  inBlock = .true.
                  do while(inBLock)
                     call ESMF_ConfigNextLine(CFtemp, _RC)
                     call ESMF_ConfigGetAttribute(CFtemp,thisLine,_RC)
                     if (trim(thisLine) == "%%") then
                        inBlock = .false.
                     else

                        totalPrimaryEntries = totalPrimaryEntries + 1
                        ! name entry
                        primary%item(totalPrimaryEntries)%name = trim(thisLine)
                        !call ESMF_ConfigGetAttribute(CFtemp, primary%item(totalPrimaryEntries)%name,  _RC)
                        PrimaryVarNames(totalPrimaryEntries) = primary%item(totalPrimaryEntries)%name
                        ! check if this represents a vector by looking for semicolon
                        primary%item(totalPrimaryEntries)%isVector = ( index(primary%item(totalPrimaryEntries)%name,';').ne.0 )
                        if ( index(primary%item(totalPrimaryEntries)%name,';').ne.0 ) then
                           primary%item(totalPrimaryEntries)%fileVars%itemType = ItemTypeVector
                        else
                           primary%item(totalPrimaryEntries)%fileVars%itemType = ItemTypeScalar
                        end if
                        primary%item(totalPrimaryEntries)%vartype = MAPL_ExtDataVectorItem
                        primary%item(totalPrimaryEntries)%foundComp2 = .false.
                        primary%item(totalPrimaryEntries)%foundComp1 = .false.

                        ! units entry
                        call ESMF_ConfigGetAttribute(CFtemp, primary%item(totalPrimaryEntries)%units, _RC)

                        ! climatology entry
                        call ESMF_ConfigGetAttribute(CFtemp, buffer, _RC)
                        buffer = ESMF_UtilStringLowerCase(buffer, _RC)
                        primary%item(totalPrimaryEntries)%cyclic=buffer

                        ! regridding keyword, controls what type of regridding is performed
                        ! options are
                        ! N - conventional bilinear regridding
                        ! Y - conservative regridding
                        ! H - conservative horizontal flux regridding
                        ! E - nearest neighbor regridding
                        ! V - voting, tile based
                        ! F;val - fractional, returns the fraction of the input cells with value, val
                        !         that overlap the target cell
                        call ESMF_ConfigGetAttribute(CFtemp, buffer, _RC)
                        buffer = ESMF_UtilStringLowerCase(buffer, _RC)
                        buffer = trim(buffer)
                        if (trim(buffer) == 'y') then
                           primary%item(totalPrimaryEntries)%trans = REGRID_METHOD_CONSERVE
                        else if (trim(buffer) == 'n') then
                           primary%item(totalPrimaryEntries)%trans = REGRID_METHOD_BILINEAR
                        else if (trim(buffer) == 'h') then
                           primary%item(totalPrimaryEntries)%trans = REGRID_METHOD_CONSERVE_HFLUX
                        else if (trim(buffer) == 'e') then
                           primary%item(totalPrimaryEntries)%trans = REGRID_METHOD_NEAREST_STOD
                        else if (trim(buffer) == 'v') then
                           primary%item(totalPrimaryEntries)%trans = REGRID_METHOD_VOTE
                        else if (index(trim(buffer),'f') ==1 ) then
                           primary%item(totalPrimaryEntries)%trans = REGRID_METHOD_FRACTION
                           k = index(buffer,';')
                           _ASSERT(k > 0,'ERROR: MAPL fractional regridding requires semi-colon in ExtData.rc entry: '//trim(primary%item(totalPrimaryEntries)%name))
                           read(buffer(k+1:),*,iostat=ios) primary%item(totalPrimaryEntries)%FracVal
                        else
                           __raise__(MAPL_RC_ERROR, "the regridding keyword for extdata primary export must be E, H, N, Y, V, or F")
                        end if

                        ! refresh template entry
                        call ESMF_ConfigGetAttribute(CFtemp, buffer, _RC)
                        ! check if first entry is an F for no interpolation
                        buffer = trim(buffer)
                        if (buffer(1:1) == 'F') then
                           primary%item(totalPrimaryEntries)%refresh_template = buffer(2:)
                           primary%item(totalPrimaryEntries)%doInterpolate = .false.
                        else
                           primary%item(totalPrimaryEntries)%refresh_template = buffer
                           primary%item(totalPrimaryEntries)%doInterpolate = .true.
                        end if
                        ! offset entry
                        call ESMF_ConfigGetAttribute(CFtemp, c_offset, _RC)
                        if (trim(c_offset) == "none") then
                           primary%item(totalPrimaryEntries)%do_offset = .false.
                        else
                           primary%item(totalPrimaryEntries)%do_offset = .true.
                           read(c_offset,*,iostat=ios) primary%item(totalPrimaryEntries)%offset
                        end if
                        ! scaling entry
                        call ESMF_ConfigGetAttribute(CFtemp, c_scale, _RC)
                        if (trim(c_scale) == "none") then
                           primary%item(totalPrimaryEntries)%do_scale = .false.
                        else
                           primary%item(totalPrimaryEntries)%do_scale = .true.
                           read(c_scale,*,iostat=ios) primary%item(totalPrimaryEntries)%scale
                        end if

                        ! variable name on file entry
                        call ESMF_ConfigGetAttribute(CFtemp, primary%item(totalPrimaryEntries)%var,    _RC)
                        ! file template entry
                        call ESMF_ConfigGetAttribute(CFtemp, primary%item(totalPrimaryEntries)%file,   _RC)

                        ! the next  three are optional entries to describe the time information about the file template
                        ! these are what is the first valid time you can apply to the file template to get a file that exists
                        ! then you can specify the frequnecy of the file and the units of the frequency
                        call ESMF_ConfigGetAttribute(CFtemp, primary%item(totalPrimaryEntries)%fileReffTime, rc=status)
                        if (status /= ESMF_SUCCESS) then
                           primary%item(totalPrimaryEntries)%FileReffTime = ""
                           primary%item(totalPrimaryEntries)%hasFileReffTime = .false.
                        else
                           primary%item(totalPrimaryEntries)%hasFileReffTime = .true.
                        end if

              !         assume we will allocate
                        primary%item(totalPrimaryEntries)%ExtDataAlloc = .true.
              !         check if this is going to be a constant
                        primary%item(totalPrimaryEntries)%isConst = .false.
                        if (primary%item(totalPrimaryEntries)%file(1:9) == '/dev/null') then
                           primary%item(totalPrimaryEntries)%isConst = .true.
                           ios = -1
                           k = index(primary%item(totalPrimaryEntries)%file,':')
                           if ( k > 9 ) then
                                read(primary%item(totalPrimaryEntries)%file(k+1:),*,iostat=ios) &
                                     & primary%item(totalPrimaryEntries)%const
                           end if
                           if ( ios /= 0 ) primary%item(totalPrimaryEntries)%const = 0.0
                           ! finally override whatever the cyclic arguement is
                           primary%item(totalPrimaryEntries)%cyclic='n'
                        end if

                     end if
                  enddo
               !  Derived Exports
               !  ---------------
               case ("DerivedExports%%")
                  inBlock = .true.
                  do while(inBlock)
                     call ESMF_ConfigNextLine(CFtemp, _RC)
                     call ESMF_ConfigGetAttribute(CFtemp,thisLine,_RC)
                     if (trim(thisLine) == "%%") then
                        inBlock = .false.
                     else
                        totalDerivedEntries = totalDerivedEntries + 1
                        derived%item(totalDerivedEntries)%name = trim(thisLine)
                        call ESMF_ConfigGetAttribute(CFtemp,derived%item(totalDerivedEntries)%expression,_RC)
                        call ESMF_ConfigGetAttribute(CFtemp,derived%item(totalDerivedEntries)%refresh_template, _RC)
                        derived%item(totalDerivedEntries)%ExtDataAlloc = .true.
                     end if
                  enddo
            end select
         end if
      end if
   end do
   !Done parsing resource file

   PrimaryItemCount = 0
   DerivedItemCount = 0
   itemCounter = 0

!   find items in primary and derived to fullfill Export state
!   once we find primary or derived put in namespace
    self%ExtDataState = ESMF_StateCreate(Name="ExtDataNameSpace",_RC)
    do I = 1, ItemCount

       found = .false.
       do J = 1, primary%nItems
          ! special handling if it is a vector
          if (primary%item(J)%isVector) then
             idx = index(primary%item(J)%name,";")
             component1 = primary%item(J)%name(1:idx-1)
             component2 = primary%item(J)%name(idx+1:)
             if ( trim(ItemNames(I)) == trim(component1) ) then
                primary%item(j)%vcomp1 = component1
                idx = index(primary%item(j)%var,";")
                primary%item(j)%fcomp1 = primary%item(j)%var(1:idx-1)
                primary%item(j)%fileVars%xname=trim(primary%item(j)%fcomp1)
                itemCounter = itemCounter + 1
                found = .true.
                primary%item(j)%foundComp1 = .true.
                PrimaryVarNeeded(j) = .true.
                primary%item(j)%ExtDataAlloc = .false.
                if ( primary%item(j)%foundComp1 .and. primary%item(j)%foundComp2 ) PrimaryItemCount = PrimaryItemCount + 1
                call ESMF_StateGet(Export,component1,field,_RC)
                call MAPL_StateAdd(self%ExtDataState,field,_RC)
                ! put protection in, if you are filling vector pair, they must be fields, no bundles
                _ASSERT( ITEMTYPES(I) == ESMF_StateItem_Field ,'Vector pair must be fields')
                exit
             else if ( trim(ItemNames(I)) == trim(component2) ) then
                primary%item(j)%vcomp2 = component2
                idx = index(primary%item(j)%var,";")
                primary%item(j)%fcomp2 = primary%item(j)%var(idx+1:)
                primary%item(j)%fileVars%yname=trim(primary%item(j)%fcomp2)
                itemCounter = itemCounter + 1
                found = .true.
                primary%item(j)%foundComp2 = .true.
                PrimaryVarNeeded(j) = .true.
                primary%item(j)%ExtDataAlloc = .false.
                if ( primary%item(j)%foundComp1 .and. primary%item(j)%foundComp2 ) PrimaryItemCount = PrimaryItemCount + 1
                call ESMF_StateGet(Export,component2,field,_RC)
                call MAPL_StateAdd(self%ExtDataState,field,_RC)
                ! put protection in, if you are filling vector pair, they must be fields, no bundles
                _ASSERT( ITEMTYPES(I) == ESMF_StateItem_Field ,'Vector pair must be fields')
                exit
             end if
          else
             if (ItemNames(I) == primary%item(J)%name) then
                itemCounter = itemCounter + 1
                found = .true.
                if (primary%item(j)%isConst .and. ITEMTYPES(I) == ESMF_StateItem_FieldBundle) then
                   _FAIL( 'Can not have constant bundle in ExtData.rc file')
                end if
                PrimaryItemCount = PrimaryItemCount + 1
                PrimaryVarNeeded(j) = .true.
                primary%item(j)%ExtDataAlloc = .false.
                VarName=trim(primary%item(J)%name)
                primary%item(j)%fileVars%xname=trim(primary%item(J)%var)

                if (ITEMTYPES(I) == ESMF_StateItem_Field) then
                   primary%item(J)%vartype = MAPL_FieldItem
                   call ESMF_StateGet(Export,VarName,field,_RC)
                   call MAPL_StateAdd(self%ExtDataState,field,_RC)
                else if (ITEMTYPES(I) == ESMF_StateItem_FieldBundle) then
                   primary%item(J)%vartype = MAPL_BundleItem
                   call ESMF_StateGet(Export,VarName,bundle,_RC)
                   call MAPL_StateAdd(self%ExtDataState,bundle,_RC)
                end if
                exit

             end if
          end if
       end do
       if ( (.not.found) .and. (derived%nItems > 0) ) then
          do J = 1, derived%nItems
             if (ItemNames(I) == derived%item(J)%name) then

                if (ITEMTYPES(I) == ESMF_StateItem_FieldBundle) then
                   _FAIL('Derived items cannot be field bundle')
                end if
                found = .true.
                DerivedVarNeeded(j) = .true.
                itemCounter = itemCounter + 1
                DerivedItemCount = DerivedItemCount + 1
                derived%item(j)%ExtDataAlloc = .false.
                VarName=derived%item(j)%name
                call ESMF_StateGet(Export,VarName,field,_RC)
                call MAPL_StateAdd(self%ExtDataState,field,_RC)
                exit

             end if
          end do
       end if
       if (.not.found) then
          call lgr%info('ExtData could not satisfy import %a',trim(ItemNames(I)))
       end if
    end do

    call ESMF_VMGetCurrent(VM)
    call ESMF_VMBarrier(VM)

    ! we have better found all the items in the export in either a primary or derived item
    if (itemCounter /= ItemCount) then
       write(error_msg_str, '(A6,I3,A31)') 'Found ', ItemCount-itemCounter,' unfulfilled imports in extdata'
       _FAIL( error_msg_str)
    end if

    NumVarNames=primary%nItems
    allocate(VarNames(NumVarNames))
    allocate(LocalVarNeeded(NumVarNames))
    do i=1,primary%nItems
       VarNames(i)=PrimaryVarNames(i)
    end do

    call lgr%info('*******************************************************')
    call lgr%info('** Variables to be provided by the ExtData Component **')
    call lgr%info('*******************************************************')
    do i = 1, ItemCount
       call lgr%info('---- %i0.5~: %a', i, trim(ItemNames(i)))
    end do
    call lgr%info('*******************************************************\n')

!   search for other primary variables we may need to fill derived types that were not in the export state
!   if we find them allocate them based on grid of variable we are trying to fill
    do i=1, derived%nItems
       if (DerivedVarNeeded(i)) then
          LocalVarNeeded=.false.

          ! first check if it is a non-arithmetic function
          expression = derived%item(i)%expression
          expression = ESMF_UtilStringLowerCase(expression, _RC)
          if ( index(expression,"mask") /=0  ) then
             derived%item(i)%masking = .true.
          else
             derived%item(i)%masking = .false.
          end if
          if (derived%item(i)%masking) then
             call GetMaskName(derived%item(i)%expression,VarNames,LocalVarNeeded,_RC)
          else
             call CheckSyntax(derived%item(i)%expression,VarNames,LocalVarNeeded,_RC)
          end if

          do j=1, primary%nItems
             if (LocalVarNeeded(j)) then
                VarName = trim(primary%item(j)%name)
                call ESMF_StateGet(self%ExtDataState,VarName,itemType=itemType,_RC)
                if (itemType == ESMF_STATEITEM_FIELD) then
                   call ESMF_StateGet(self%ExtDataState,VarName,field,_RC)
                else
                   VarName = trim(derived%item(i)%name)
                   call ESMF_StateGet(self%ExtDataState,VarName,field,_RC)
                   VarName=trim(primary%item(j)%name)
                   fieldnew = MAPL_FieldCreate(field,varname,doCopy=.true.,_RC)
                   primary%item(j)%fileVars%xname=trim(primary%item(j)%var)
                   call MAPL_StateAdd(self%ExtDataState,fieldnew,_RC)
                   PrimaryVarNeeded(j) = .true.
                   primary%item(j)%ExtDataAlloc = .true.
                   primary%item(j)%vartype = MAPL_FieldItem
                   PrimaryItemCount = PrimaryItemCount + 1
                end if
             end if
          end do
       end if
    end do

    self%primary%nItems = count(PrimaryVarNeeded)
    if (DerivedItemCount > 0) self%derived%nItems = count(DerivedVarNeeded)

    allocate(self%primary%item(PrimaryItemCount),__STAT__)
    if (DerivedItemCount > 0) allocate(self%derived%item(DerivedItemCount),__STAT__)

    counter = 0
    do i=1,primary%nItems
       if (PrimaryVarNeeded(i)) then
          counter = counter + 1
          self%primary%item(counter) = primary%item(i)
          ! put in a special check if it is a vector item
          ! both components must have bubbled up
          if (self%primary%item(counter)%isVector) then
             _ASSERT( self%primary%item(counter)%foundComp1, 'Did not find Component 1 vector item')
             _ASSERT( self%primary%item(counter)%foundComp2 ,'Did not find both Component 2 vector item')
          end if
       end if
    end do
    _ASSERT(counter==PrimaryItemCount,'Not all needed primary vars found')

    if (DerivedItemCount > 0) then
       counter = 0
       do i=1,derived%nItems
          if (derivedVarNeeded(i)) then
             counter = counter + 1
             self%derived%item(counter) = derived%item(i)
          end if
       end do
       _ASSERT(counter==DerivedItemCount,'Not all needed derived vars found')
    end if

   call ESMF_ClockGet(CLOCK, currTIME=time, _RC)
   PrimaryLoop: do i = 1, self%primary%nItems

      item => self%primary%item(i)

      call lgr%debug('ExtData Initialize_(): PrimaryLoop: ')

      if ( .not. item%isConst )  then
         call CreateTimeInterval(item,clock,_RC)
      end if

      item%pfioCollection_id = MAPL_DataAddCollection(item%file,use_file_coords=self%use_file_coords)

      ! parse refresh template to see if we have a time shift during constant updating
      k = index(item%refresh_template,';')
      call ESMF_TimeIntervalSet(item%tshift,_RC)
      if (k.ne.0) then
         _ASSERT(trim(item%refresh_template(:k-1))=="0",'Refresh template must start with 0 when offset is present')
         if (item%refresh_template(k+1:k+1) == '-' ) then
            isNegative = .true.
            read(item%refresh_template(k+2:),*,iostat=ios)nhms
         else
            isNegative = .false.
            read(item%refresh_template(k+1:),*,iostat=ios)nhms
         end if
         call MAPL_UnpackTime(nhms,ihr,imn,isc)
         if (isNegative) then
            ihr = -ihr
            imn = -imn
            isc = -isc
         end if
         call ESMF_TimeIntervalSet(item%tshift,h=ihr,m=imn,s=isc,_RC)
         item%refresh_template = "0"
      end if
      call SetRefreshAlarms(clock,primaryItem=item,_RC)

      if (item%vartype == MAPL_BundleItem) then

         call ESMF_StateGet(self%ExtDataState, trim(item%name), bundle,_RC)
         ! let us check that bundle is empty
         call ESMF_FieldBundleGet(bundle, fieldcount = fieldcount , _RC)
         _ASSERT(fieldcount == 0,'Bundle must be empty')
         call MAPL_CFIORead(item%file,time,bundle,noread=.true.,ignorecase=self%ignorecase, only_vars=item%var,_RC)

      end if

!  Read the single step files (read interval equal to zero)
!  --------------------------------------------------------

      if (item%isConst) then

         if (item%vartype == MAPL_FieldItem) then
            call ESMF_StateGet(self%ExtDataState,trim(item%name),field,_RC)
            call ESMF_FieldGet(field,dimCount=fieldRank,_RC)
            if (fieldRank == 2) then
                  call MAPL_GetPointer(self%ExtDataState, ptr2d, trim(item%name),_RC)
                  ptr2d = item%const
            else if (fieldRank == 3) then
                  call MAPL_GetPointer(self%ExtDataState, ptr3d, trim(item%name), _RC)
                  ptr3d = item%const
            endif
         else if (item%vartype == MAPL_BundleItem) then
            _FAIL('Cannot assign constant to field bundle')
         else if (item%vartype == MAPL_ExtDataVectorItem) then
            call ESMF_StateGet(self%ExtDataState,trim(item%vcomp1),field,_RC)
            call ESMF_FieldGet(field,dimCount=fieldRank,_RC)
            if (fieldRank == 2) then
                  call MAPL_GetPointer(self%ExtDataState, ptr2d, trim(item%vcomp1),_RC)
                  ptr2d = item%const
            else if (fieldRank == 3) then
                  call MAPL_GetPointer(self%ExtDataState, ptr3d, trim(item%vcomp1), _RC)
                  ptr3d = item%const
            endif
            call ESMF_StateGet(self%ExtDataState,trim(item%vcomp2),field,_RC)
            call ESMF_FieldGet(field,dimCount=fieldRank,_RC)
            if (fieldRank == 2) then
                  call MAPL_GetPointer(self%ExtDataState, ptr2d, trim(item%vcomp2),_RC)
                  ptr2d = item%const
            else if (fieldRank == 3) then
                  call MAPL_GetPointer(self%ExtDataState, ptr3d, trim(item%vcomp2), _RC)
                  ptr3d = item%const
            endif
         end if
         cycle
      end if

      ! check if this is a single piece of data if user put - for refresh template
      ! by that it is an untemplated file with one time that could not possibly be time interpolated
      if (PrimaryExportIsConstant_(item)) then
         if (index(item%file,'%') == 0) then
            call MakeMetadata(item%file,item%pfioCollection_id,metadata,_RC)
            call metadata%get_coordinate_info('time',coordSize=tsteps,_RC)
            if (tsteps == 1) then
               item%cyclic = 'single'
               item%doInterpolate = .false.
            end if
         end if
      end if

      ! get clim year if this is cyclic
      call GetClimYear(item,_RC)
      ! get levels, other information
      call GetLevs(item,time,self%ExtDataState,self%allowExtrap,_RC)
      call ESMF_VMBarrier(vm)
      ! register collections
      item%iclient_collection_id=i_clients%add_ext_collection(trim(item%file))
      ! create interpolating fields, check if the vertical levels match the file
      if (item%vartype == MAPL_FieldItem) then

         call ESMF_StateGet(self%ExtDataState, trim(item%name), field,_RC)
         call ESMF_FieldGet(field,grid=grid,rank=fieldRank,_RC)

         lm=0
         if (fieldRank==3) then
            call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC)
            lm = size(ptr3d,3)
         end if
         if (item%lm /= lm .and. lm /= 0 .and. item%havePressure) then
            item%do_VertInterp = .true.
         else if (item%lm /= lm .and. lm /= 0) then
            item%do_Fill = .true.
         end if
         item%modelGridFields%v1_finterp1 = MAPL_FieldCreate(field,item%var,doCopy=.true.,_RC)
         item%modelGridFields%v1_finterp2 = MAPL_FieldCreate(field,item%var,doCopy=.true.,_RC)
         if (item%do_fill .or. item%do_vertInterp) then
            call createFileLevBracket(item,cf_main,_RC)
         end if

      else if (item%vartype == MAPL_BundleItem) then

         call ESMF_StateGet(self%ExtDataState, trim(item%name), bundle,_RC)
         call ESMF_FieldBundleGet(bundle,grid=grid,_RC)
         call ESMF_ClockGet(CLOCK, currTIME=time, _RC)
         item%binterp1 = ESMF_FieldBundleCreate( _RC)
         call ESMF_FieldBundleSet(item%binterp1, GRID=GRID, _RC)
         item%binterp2 = ESMF_FieldBundleCreate( _RC)
         call ESMF_FieldBundleSet(item%binterp2, GRID=GRID, _RC)
         call MAPL_CFIORead(item%file,time,item%binterp1,noread=.true.,ignorecase=self%ignorecase,only_vars=item%var,_RC)
         call MAPL_CFIORead(item%file,time,item%binterp2,noread=.true.,ignorecase=self%ignorecase,only_vars=item%var,_RC)

      else if (item%vartype == MAPL_ExtDataVectorItem) then

         ! Only some methods are supported for vector regridding
         _ASSERT(any(item%Trans /= [REGRID_METHOD_BILINEAR,REGRID_METHOD_CONSERVE_HFLUX]), 'Regrid method unsupported for vectors.')

         block
            integer :: gridRotation1, gridRotation2
            call ESMF_StateGet(self%ExtDataState, trim(item%vcomp1), field,_RC)
            call ESMF_AttributeGet(field, NAME='ROTATION', value=gridRotation1, _RC)
            call ESMF_StateGet(self%ExtDataState, trim(item%vcomp2), field,_RC)
            call ESMF_AttributeGet(field, NAME='ROTATION', value=gridRotation2, _RC)
            _ASSERT(GridRotation1 == gridRotation2,'Grid rotations must match when performing vector re-gridding')
         end block

         call ESMF_StateGet(self%ExtDataState, trim(item%vcomp1), field,_RC)
         call ESMF_FieldGet(field,grid=grid,rank=fieldRank,_RC)

         lm = 0
         if (fieldRank==3) then
            call ESMF_FieldGet(field,0,farrayPtr=ptr3d,_RC)
            lm = size(ptr3d,3)
         end if
         if (item%lm /= lm .and. item%havePressure) then
            item%do_VertInterp = .true.
         else if (item%lm /= lm .and. lm /= 0) then
            item%do_Fill = .true.
         end if
         item%modelGridFields%v1_finterp1 = MAPL_FieldCreate(field, item%fcomp1,doCopy=.true.,_RC)
         item%modelGridFields%v1_finterp2 = MAPL_FieldCreate(field, item%fcomp1,doCopy=.true.,_RC)
         call ESMF_StateGet(self%ExtDataState, trim(item%vcomp2), field,_RC)
         item%modelGridFields%v2_finterp1 = MAPL_FieldCreate(field, item%fcomp2,doCopy=.true.,_RC)
         item%modelGridFields%v2_finterp2 = MAPL_FieldCreate(field, item%fcomp2,doCopy=.true.,_RC)
         if (item%do_fill .or. item%do_vertInterp) then
            call createFileLevBracket(item,cf_main,_RC)
         end if

      end if

      allocate(item%refresh_time,__STAT__)

      call ESMF_TimeSet(item%refresh_time, yy=0, _RC)
   end do PrimaryLoop

   DerivedLoop: do i =1, self%derived%nItems
      allocate(self%derived%item(i)%refresh_time,__STAT__)

      derivedItem => self%derived%item(i)

      ! parse refresh template to see if we have a time shift during constant updating
      k = index(derivedItem%refresh_template,';')
      call ESMF_TimeIntervalSet(derivedItem%tshift,_RC)
      if (k.ne.0) then
         _ASSERT(trim(derivedItem%refresh_template(:k-1))=="0",'Refresh template must start with 0 when offset is present')
         if (derivedItem%refresh_template(k+1:k+1) == '-' ) then
            isNegative = .true.
            read(derivedItem%refresh_template(k+2:),*,iostat=ios)nhms
         else
            isNegative = .false.
            read(derivedItem%refresh_template(k+1:),*,iostat=ios)nhms
         end if
         call MAPL_UnpackTime(nhms,ihr,imn,isc)
         if (isNegative) then
            ihr = -ihr
            imn = -imn
            isc = -isc
         end if
         call ESMF_TimeIntervalSet(derivedItem%tshift,h=ihr,m=imn,s=isc,_RC)
         derivedItem%refresh_template = "0"
      end if

      call SetRefreshAlarms(clock,derivedItem=derivedItem,_RC)

      call ESMF_TimeSet(self%derived%item(i)%refresh_time, yy=0, _RC)
   end do DerivedLoop

#ifdef DEBUG
   if (MAPL_AM_I_ROOT()) then
      print *, trim(Iam)//': IMPORT   State during Initialize():'
      call ESMF_StatePrint ( IMPORT )
      print *
      print *, trim(Iam)//': EXPORT   State during Initialize():'
      call ESMF_StatePrint ( EXPORT )
   end if
#endif

! Check if we have any files that would need to be vertically interpolated
! if so ensure that PS is done first
   allocate(self%primaryOrder(size(self%primary%item)),__STAT__)
   do i=1,size(self%primary%item)
      self%primaryOrder(i)=i
   enddo
!  check for PS
   idx = -1
   if (any(self%primary%item%do_VertInterp .eqv. .true.)) then
      do i=1,size(self%primary%item)
         if (self%primary%item(i)%name=='PS') then
            idx =i
         end if
         if (self%primary%item(i)%vartype==MAPL_BundleItem) then
            _FAIL('Cannot perform vertical interpolation on field bundle')
         end if
      enddo
      _ASSERT(idx/=-1,'Surface pressure not present for vertical interpolation')
      self%primaryOrder(1)=idx
      self%primaryOrder(idx)=1
      self%primary%item(idx)%units = ESMF_UtilStringUppercase(self%primary%item(idx)%units,rc=status)
      _ASSERT(trim(self%primary%item(idx)%units)=="PA",'PS must be in units of PA')
   end if
!  check for PHIS
   idx = -1
   if (any(self%primary%item%do_VertInterp .eqv. .true.)) then
      do i=1,size(self%primary%item)
         if (self%primary%item(i)%name=='PHIS') then
            idx =i
         end if
         if (self%primary%item(i)%vartype==MAPL_BundleItem) then
            _FAIL('Cannot perform vertical interpolation on field bundle')
         end if
      enddo
      if (idx/=-1) then
         self%primaryOrder(2)=idx
         self%primaryOrder(idx)=2
         self%primary%have_phis=.true.
      end if
   end if

! Clean up
! --------
   if (associated(primary%item)) deallocate(primary%item)
   if (associated(derived%item)) deallocate(derived%item)
   deallocate(ItemTypes)
   deallocate(ItemNames)
   if (allocated(PrimaryVarNames)) deallocate(PrimaryVarNames)
   if (allocated(PrimaryVarNeeded)) deallocate(PrimaryVarNeeded)
   if (allocated(VarNames)) deallocate(VarNames)
   if (allocated(DerivedVarNeeded)) deallocate(DerivedVarNeeded)
   if (allocated(LocalVarNeeded)) deallocate(LocalVarNeeded)

   !Done parsing resource file

!  Set has run to false to we know when we first go to run method it is first call
   hasRun = .false.

   call MAPL_TimerOff(MAPLSTATE,"Initialize")
!  All done
!  --------

   call lgr%debug('ExtData Initialize_(): End')

   _RETURN(ESMF_SUCCESS)

   END SUBROUTINE Initialize_


!-------------------------------------------------------------------------
!     NASA/GSFC, Global Modeling and Assimilation Office, Code 610.1     !
!-------------------------------------------------------------------------
!>
! `Run_` --- Runs MAPL_ExtData
!
! This is a simple ESMF wrapper.
!
!#### History
!- 12Dec2009  da Silva  Design and first implementation.
!
   SUBROUTINE Run_ ( GC, IMPORT, EXPORT, CLOCK, rc )

! !USES:

  implicit NONE

! !INPUT PARAMETERS:

   type(ESMF_Clock),  intent(inout) :: CLOCK     !! The clock

! !OUTPUT PARAMETERS:

   type(ESMF_GridComp), intent(inout)  :: GC     !! Grid Component
   type(ESMF_State), intent(inout) :: IMPORT     !! Import State
   type(ESMF_State), intent(inout) :: EXPORT     !! Export State
   integer, intent(out) ::  rc                   !! Error return code:
                                                 !!  0 - all is well
                                                 !!  1 -
!
!-------------------------------------------------------------------------

   type(MAPL_ExtData_state), pointer :: self        ! Legacy state
   type(ESMF_Field)                  :: field ! Field
   type(ESMF_FieldBundle)            :: bundle
   type(ESMF_Config)                 :: CF          ! Universal Config

   character(len=ESMF_MAXSTR)        :: comp_name
   character(len=ESMF_MAXSTR)        :: Iam
   integer                           :: status

   type(PrimaryExport), pointer      :: item
   type(DerivedExport), pointer      :: derivedItem
   integer                           :: i, j

   type(ESMF_Time)                   :: time, time0
   type(MAPL_MetaComp), pointer      :: MAPLSTATE

   logical                           :: doUpdate_
   integer                           :: fieldCount
   character(len=ESMF_MAXSTR), ALLOCATABLE  :: NAMES (:)
   character(len=ESMF_MAXPATHLEN)    :: file_processed, file_processed1, file_processed2
   logical                           :: NotSingle
   logical                           :: updateL, updateR, swap
   logical, allocatable              :: doUpdate(:)
   type(ESMF_Time), allocatable      :: useTime(:)

   integer                           :: bracket_side
   integer                           :: entry_num
   type(IOBundleVector), target     :: IOBundles
   type(IOBundleVectorIterator) :: bundle_iter
   type(ExtData_IOBundle), pointer :: io_bundle

   _UNUSED_DUMMY(IMPORT)
   _UNUSED_DUMMY(EXPORT)

!  Declare pointers to IMPORT/EXPORT/INTERNAL states
!  -------------------------------------------------
!  #include "MAPL_ExtData_DeclarePointer___.h"

!  Get my name and set-up traceback handle
!  ---------------------------------------
   Iam = 'Run_'
   call ESMF_GridCompGet( GC, name=comp_name, _RC )
   Iam = trim(comp_name) // '::' // trim(Iam)


!  Call Run for every Child
!  -------------------------
!ALT   call MAPL_GenericRunChildren ( GC, IMPORT, EXPORT, CLOCK,  _RC)


!  Extract relevant runtime information
!  ------------------------------------
   call extract_ ( GC, self, CF, _RC )

   if (.not. self%active) then
      _RETURN(ESMF_SUCCESS)
   end if

   call MAPL_GetObjectFromGC ( gc, MAPLSTATE, RC=STATUS)
   _VERIFY(STATUS)
   call MAPL_TimerOn(MAPLSTATE,"Run")

   call ESMF_ClockGet(CLOCK, currTIME=time0, _RC)


!  Fill in the internal state with data from the files
!  ---------------------------------------------------

   allocate(doUpdate(self%primary%nitems),stat=status)
   _VERIFY(STATUS)
   doUpdate = .false.
   allocate(useTime(self%primary%nitems),stat=status)
   _VERIFY(STATUS)

   call MAPL_TimerOn(MAPLSTATE,"-Read_Loop")

   call lgr%debug('ExtData Rune_(): Start')
   call lgr%debug('ExtData Run_(): READ_LOOP: Start')

   READ_LOOP: do i = 1, self%primary%nItems

      item => self%primary%item(self%primaryOrder(i))

      call lgr%debug('ExtData Run_(): READ_LOOP: variable %i0 of %i0~: %a', i, self%primary%nItems, trim(item%var))
      call lgr%debug('   ==> file: %a', trim(item%file))
      call lgr%debug('   ==> cyclic: %a', trim(item%cyclic))
      call lgr%debug('   ==> isConst:: %l1', item%isConst)

      if (item%isConst) then
         call lgr%debug('   ==> Break loop since isConst is true')
         cycle
      endif


      NotSingle = .true.
      if (trim(item%cyclic) == 'single') NotSingle = .false.

      call MAPL_TimerOn(MAPLSTATE,"--CheckUpd")

      call CheckUpdate(doUpdate_,time,time0,hasRun,primaryItem=item,_RC)
      doUpdate(i) = doUpdate_
      call MAPL_TimerOff(MAPLSTATE,"--CheckUpd")

      DO_UPDATE: if (doUpdate_) then

         call lgr%debug('   ExtData Run_: DO_UPDATE: Start. doUpdate_ is true.')

         HAS_RUN: if ( hasRun .eqv. .false.) then

            call lgr%debug('   ExtData Run_: Has_Run: Start. hasRun is false. Update time.')

            call MAPL_TimerOn(MAPLSTATE,"--Bracket")
            if (NotSingle) then

               ! update left time
               call lgr%debug('   ExtData Run_: HAS_RUN: NotSingle is true. Update left time (bracket L)')
               call UpdateBracketTime(item,time,"L",item%interp_time1, &
                    item%time1,file_processed1,self%allowExtrap,rc=status)
               _VERIFY(status)
               call IOBundle_Add_Entry(IOBundles,item,self%primaryOrder(i),file_processed1,MAPL_ExtDataLeft,item%tindex1,_RC)

               ! update right time
               call lgr%debug('      ExtData Run_: HAS_RUN: NotSingle is true. Update right time (bracket R)')
               call UpdateBracketTime(item,time,"R",item%interp_time2, &
                    item%time2,file_processed2,self%allowExtrap,rc=status)
               _VERIFY(STATUS)
               call IOBundle_Add_Entry(IOBundles,item,self%primaryOrder(i),file_processed2,MAPL_ExtDataRight,item%tindex2,_RC)

            else

               call lgr%debug('      ExtData Run_: HAS_RUN: NotSingle is false. Just get time on file.')

               ! just get time on the file
               item%time1 = MAPL_ExtDataGetFStartTime(item,trim(item%file),_RC)
               item%interp_time1 = item%time1
               file_processed1 = item%file
               call IOBundle_Add_Entry(IOBundles,item,self%primaryOrder(i),file_processed1,MAPL_ExtDataLeft,1,_RC)
            end if
            call MAPL_TimerOff(MAPLSTATE,"--Bracket")

            call lgr%debug('      ExtData Run_: HAS_RUN: End')

         endif HAS_RUN

         ! now update bracketing times if neccessary

         NOT_SINGLE: if (NotSingle) then

            call lgr%debug('      ExtData Run_: NOT_SINGLE: Start. Update bracketing times?')

            if (time >= item%interp_time2) then
               ! normal flow assume clock is moving forward
               updateR = .true.
               updateL = .false.
               swap    = .true.
            else if (time < item%interp_time1) then
               ! the can only happen if clock was rewound like in replay update both
               updateR = .true.
               updateL = .true.
               swap    = .false.
            else
               updateR = .false.
               updateL = .false.
               swap    = .false.
            end if

            call lgr%debug('         ==> updateR: %L1', updateR)
            call lgr%debug('         ==> updateL: %L1', updateL)
            call lgr%debug('         ==> swap: %L1', swap)

            call MAPL_TimerOn(MAPLSTATE,'--Swap')
            DO_SWAP: if (swap) then

               call lgr%debug('            DO_SWAP: Swapping prev and next')

               call swapBracketInformation(item,_RC)

            end if DO_SWAP

            call MAPL_TimerOff(MAPLSTATE,'--Swap')

            UPDATE_R: if (updateR) then

               call lgr%debug('         UPDATE_R: updating right bracket')

               call MAPL_TimerOn(MAPLSTATE,'--Bracket')

               call UpdateBracketTime(item,time,"R",item%interp_time2, &
                    item%time2,file_processed,self%allowExtrap,rc=status)
               _VERIFY(STATUS)
               call IOBundle_Add_Entry(IOBundles,item,self%primaryOrder(i),file_processed,MAPL_ExtDataRight,item%tindex2,_RC)

               call MAPL_TimerOff(MAPLSTATE,'--Bracket')

            end if UPDATE_R

            UPDATE_L: if (updateL) then

               call lgr%debug('         UPDATE_L: updating left bracket')

               call MAPL_TimerOn(MAPLSTATE,'--Bracket')

               call UpdateBracketTime(item,time,"L",item%interp_time1, &
                    item%time1,file_processed,self%allowExtrap,rc=status)
               _VERIFY(STATUS)
               call IOBundle_Add_Entry(IOBundles,item,self%primaryOrder(i),file_processed,MAPL_ExtDataLeft,item%tindex1,_RC)

               call MAPL_TimerOff(MAPLSTATE,'--Bracket')

            end if UPDATE_L

            call lgr%debug('      ExtData Run_: NOT_SINGLE: End')

         endif NOT_SINGLE

         useTime(i) = time

         call lgr%debug('   ExtData Run_: DO_UPDATE: End')

      end if DO_UPDATE

      if (PrimaryExportIsConstant_(item) .and. associated(item%refresh_time)) then
         deallocate(item%refresh_time)
         item%refresh_time => null()
      end if

   end do READ_LOOP

   call lgr%debug('ExtData Run_: READ_LOOP: Done')

   if (IOBundles%size() == 0) then
      deallocate(doUpdate)
      deallocate(useTime)
      if (hasRun .eqv. .false.) hasRun = .true.
      call MAPL_TimerOff(MAPLSTATE,"-Read_Loop")
      call MAPL_TimerOff(MAPLSTATE,"Run")
      _RETURN(ESMF_SUCCESS)
   endif

   bundle_iter = IOBundles%begin()
   do while (bundle_iter /= IoBundles%end())
      io_bundle => bundle_iter%get()
      bracket_side = io_bundle%bracket_side
      entry_num = io_bundle%entry_index
      file_Processed = io_bundle%file_name
      item => self%primary%item(entry_num)

      io_bundle%pbundle = ESMF_FieldBundleCreate(rc=status)
      _VERIFY(STATUS)

      call MAPL_ExtDataPopulateBundle(item,bracket_side,io_bundle%pbundle,rc=status)
      _VERIFY(status)
      call bundle_iter%next()
   enddo

   call MAPL_TimerOn(MAPLSTATE,"--PRead")
   call MAPL_TimerOn(MAPLSTATE,"---CreateCFIO")
   call MAPL_ExtDataCreateCFIO(IOBundles, rc=status)
   _VERIFY(status)
   call MAPL_TimerOff(MAPLSTATE,"---CreateCFIO")

   call MAPL_TimerOn(MAPLSTATE,"---prefetch")
   call MAPL_ExtDataPrefetch(IOBundles, rc=status)
   _VERIFY(status)
   call MAPL_TimerOff(MAPLSTATE,"---prefetch")
   _VERIFY(STATUS)
   call MAPL_TimerOn(MAPLSTATE,"---IclientDone")

   call i_Clients%done_collective_prefetch(_RC)
   call i_Clients%wait(_RC)

   call MAPL_TimerOff(MAPLSTATE,"---IclientDone")
   _VERIFY(STATUS)

   call MAPL_TimerOn(MAPLSTATE,"---read-prefetch")
   call MAPL_ExtDataReadPrefetch(IOBundles,rc=status)
   _VERIFY(status)
   call MAPL_TimerOff(MAPLSTATE,"---read-prefetch")
   call MAPL_TimerOff(MAPLSTATE,"--PRead")

   bundle_iter = IOBundles%begin()
   do while (bundle_iter /= IOBundles%end())
      io_bundle => bundle_iter%get()
      bracket_side = io_bundle%bracket_side
      entry_num = io_bundle%entry_index
      item => self%primary%item(entry_num)
      call MAPL_ExtDataVerticalInterpolate(self,item,bracket_side,rc=status)
      _VERIFY(status)
      call bundle_iter%next()
   enddo
   call MAPL_ExtDataDestroyCFIO(IOBundles,rc=status)
   _VERIFY(status)

   call MAPL_TimerOff(MAPLSTATE,"-Read_Loop")

   call MAPL_TimerOn(MAPLSTATE,"-Interpolate")

   call lgr%debug('ExtData Run_: INTERP_LOOP: Start')

   INTERP_LOOP: do i = 1, self%primary%nItems

      item => self%primary%item(self%primaryOrder(i))

      if (doUpdate(i)) then

         call lgr%debug('ExtData Run_: INTERP_LOOP: interpolating between bracket times, variable: %a, file: %a', &
              & trim(item%var), trim(item%file))

         ! finally interpolate between bracketing times

         if (item%vartype == MAPL_FieldItem) then

               call ESMF_StateGet(self%ExtDataState, item%name, field, _RC)
               call MAPL_ExtDataInterpField(item,useTime(i),field,_RC)

         else if (item%vartype == MAPL_BundleItem) then

               call ESMF_StateGet(self%ExtDataState, item%name, bundle, _RC)
               call ESMF_FieldBundleGet(bundle, fieldCount = fieldCount, _RC)
               allocate(names(fieldCount),__STAT__)
               call ESMF_FieldBundleGet(bundle, fieldNameList = Names, _RC)
               do j = 1,fieldCount
                  call ESMF_FieldBundleGet(bundle,names(j), field=field, _RC)
                  call MAPL_ExtDataInterpField(item,useTime(i),field,_RC)
               enddo
               deallocate(names)

         else if (item%vartype == MAPL_ExtDataVectorItem) then

               call ESMF_StateGet(self%ExtDataState, item%vcomp1, field, _RC)
               call MAPL_ExtDataInterpField(item,useTime(i),field,vector_comp=1,_RC)
               call ESMF_StateGet(self%ExtDataState, item%vcomp2, field, _RC)
               call MAPL_ExtDataInterpField(item,useTime(i),field,vector_comp=2,_RC)

         end if

      endif

      nullify(item)

   end do INTERP_LOOP

   call lgr%debug('ExtData Run_: INTERP_LOOP: Done')

   call MAPL_TimerOff(MAPLSTATE,"-Interpolate")

   ! now take care of derived fields
   do i=1,self%derived%nItems

      derivedItem => self%derived%item(i)

      call CheckUpdate(doUpdate_,time,time0,hasRun,derivedItem=deriveditem,_RC)

      if (doUpdate_) then

         call CalcDerivedField(self%ExtDataState,derivedItem%name,derivedItem%expression, &
              derivedItem%masking,_RC)

      end if

      if (DerivedExportIsConstant_(derivedItem) .and. associated(derivedItem%refresh_time)) then
          deallocate(self%derived%item(i)%refresh_time)
          self%derived%item(i)%refresh_time => null()
      end if

   end do

   call lgr%debug('ExtData Run_: End')

!  All done
!  --------
   deallocate(doUpdate)
   deallocate(useTime)

   if (hasRun .eqv. .false.) hasRun = .true.
   call MAPL_TimerOff(MAPLSTATE,"Run")

   _RETURN(ESMF_SUCCESS)

   END SUBROUTINE Run_

!-------------------------------------------------------------------------
!     NASA/GSFC, Global Modeling and Assimilation Office, Code 610.1     !
!-------------------------------------------------------------------------
!>
! `Finalize_` --- Finalize MAPL_ExtData
!
! This is a simple ESMF wrapper.
!
!#### History
!- 12Dec2009  da Silva  Design and first implementation.
!
   SUBROUTINE Finalize_ ( GC, IMPORT, EXPORT, CLOCK, rc )

! !USES:

  implicit NONE

! !INPUT PARAMETERS:

   type(ESMF_Clock),  intent(inout) :: CLOCK      !! The clock

! !OUTPUT PARAMETERS:

   type(ESMF_GridComp), intent(inout)  :: GC     !! Grid Component
   type(ESMF_State), intent(inout) :: IMPORT     !! Import State
   type(ESMF_State), intent(inout) :: EXPORT     !! Export State
   integer, intent(out) ::  rc                   !! Error return code:
                                                 !!  0 - all is well
                                                 !!  1 -
!
!-------------------------------------------------------------------------

   type(MAPL_ExtData_state), pointer :: self        ! Legacy state
   type(ESMF_Config)                 :: CF          ! Universal Config

   character(len=ESMF_MAXSTR)        :: comp_name
   character(len=ESMF_MAXSTR)        :: Iam
   integer                           :: status

   integer                           :: i


!  Get my name and set-up traceback handle
!  ---------------------------------------
   Iam = 'Finalize_'
   call ESMF_GridCompGet( GC, name=comp_name, _RC )
   Iam = trim(comp_name) // trim(Iam)

!  Finalize MAPL Generic
!  ---------------------
   call MAPL_GenericFinalize ( GC, IMPORT, EXPORT, CLOCK,  _RC )

!  Extract relevant runtime information
!  ------------------------------------
   call extract_ ( GC, self, CF, _RC)

!  Free the memory used for the bracketing arrays
!  -----------------------------------------------------------
   if (self%active) then
      do i = 1, self%primary%nItems

         if (self%primary%item(i)%isConst) cycle

         if (associated(self%primary%item(i)%refresh_time)) then
            deallocate(self%primary%item(i)%refresh_time)
         end if

      end do


!  Free the memory used to hold the primary export items
!  -----------------------------------------------------
      if (associated(self%primary%item)) then
         deallocate(self%primary%item)
      end if
   end if


!  All done
!  --------
   _RETURN(ESMF_SUCCESS)

 end SUBROUTINE Finalize_

!.......................................................................

 subroutine extract_ ( GC, self, CF, rc)

    type(ESMF_GridComp), intent(INout)  :: GC           ! Grid Comp object

    type(MAPL_ExtData_state), pointer   :: self         ! Legacy state
    type(ESMF_Config),   intent(out)    :: CF           ! Universal Config

    integer, intent(out), optional      :: rc

!                            ---

    character(len=ESMF_MAXSTR) :: comp_name
    character(len=ESMF_MAXSTR) :: Iam
    integer                    :: status

    type(MAPL_ExtData_Wrap)  :: wrap

!   Get my name and set-up traceback handle
!   ---------------------------------------
    Iam = 'extract_'
    call ESMF_GridCompGet( GC, NAME=comp_name, _RC )
    Iam = trim(COMP_NAME) // '::' // trim(Iam)

    If (present(rc))  rc=ESMF_SUCCESS

!   Get my internal state
!   ---------------------
    call ESMF_UserCompGetInternalState(gc, 'MAPL_ExtData_state', WRAP, STATUS)
    _VERIFY(STATUS)
    self => wrap%ptr

!   Get the configuration
!   ---------------------
    call ESMF_GridCompGet ( GC, config=CF, _RC )


    _RETURN(ESMF_SUCCESS)

  end subroutine extract_

! ............................................................................

   logical function PrimaryExportIsConstant_(item)

      type(PrimaryExport), intent(in) :: item

      if ( trim(item%refresh_template) == '-' .or. &
           trim(item%file) == '/dev/null' ) then
          PrimaryExportIsConstant_ = .true.
      else
          PrimaryExportIsConstant_ = .false.
      end if

   end function PrimaryExportIsConstant_

! ............................................................................

   logical function DerivedExportIsConstant_(item)

      type(DerivedExport), intent(in) :: item

      if ( trim(item%refresh_template) == '-') then
          DerivedExportIsConstant_ = .true.
      else
          DerivedExportIsConstant_ = .false.
      end if

   end function DerivedExportIsConstant_

! ............................................................................

  subroutine scale_field_(offset, scale_factor, field, rc)
     real, intent(in)                  :: scale_factor
     real, intent(in)                  :: offset
     type (ESMF_Field), intent(inout)  :: field
     integer, optional, intent (inout) :: rc

        integer       :: fieldRank
        real, pointer :: xy(:,:)    => null()
        real, pointer :: xyz(:,:,:) => null()

        integer :: status


        call ESMF_FieldGet(field, dimCount=fieldRank, _RC)

        _ASSERT(fieldRank == 2 .or. fieldRank == 3,'Field rank must be 2 or 3')

        if (fieldRank == 2) then
           call ESMF_FieldGet(field, farrayPtr=xy, _RC)

           if (associated(xy)) then
              xy = offset + scale_factor*xy
           end if
        else if (fieldRank == 3) then
           call ESMF_FieldGet(field, farrayPtr=xyz, _RC)

           if (associated(xyz)) then
              xyz = offset + scale_factor*xyz
           end if
        end if

        _RETURN(_SUCCESS)
     end subroutine scale_field_

   ! ............................................................................

     type (ESMF_Time) function timestamp_(time, template, rc)
        type(ESMF_Time), intent(inout)         :: time
        character(len=ESMF_MAXSTR), intent(in) :: template
        integer, optional, intent(inout)       :: rc

        ! locals
        integer, parameter :: DATETIME_MAXSTR_ = 32
        integer :: yy, mm, dd, hs, ms, ss
        character(len=DATETIME_MAXSTR_) :: buff, buff_date, buff_time
        character(len=DATETIME_MAXSTR_) :: str_yy, str_mm, str_dd
        character(len=DATETIME_MAXSTR_) :: str_hs, str_ms, str_ss

        integer :: i, il, ir
        integer :: status

        ! test the length of the timestamp template
        _ASSERT(len_trim(template) < DATETIME_MAXSTR_,'Timestamp template is greater than Maximum allowed len')

        buff = trim(template)
        buff = ESMF_UtilStringLowerCase(buff, _RC)

        ! test if the template is empty and return the current time as result
        if (buff == '-'  .or. buff == '--'   .or. buff == '---' .or. &
            buff == 'na' .or. buff == 'none' .or. buff == 'n/a') then

           timestamp_ = time
        else
           ! split the time stamp template into a date and time strings
           i = scan(buff, 't')
           If (.not.(i > 3)) Then
              _FAIL('ERROR: Time stamp ' // trim(template) // ' uses the fixed format, and must therefore contain a T')
           End If

           buff_date = buff(1:i-1)
           buff_time = buff(i+1:)

           ! parse the date string
           il = scan(buff_date, '-', back=.false.)
           ir = scan(buff_date, '-', back=.true. )
           str_yy = trim(buff_date(1:il-1))
           str_mm = trim(buff_date(il+1:ir-1))
           str_dd = trim(buff_date(ir+1:))

           ! parse the time string
           il = scan(buff_time, ':', back=.false.)
           ir = scan(buff_time, ':', back=.true. )
           str_hs = trim(buff_time(1:il-1))
           str_ms = trim(buff_time(il+1:ir-1))
           str_ss = trim(buff_time(ir+1:))

           ! remove the trailing 'Z' from the seconds string
           i = scan(str_ss, 'z')
           if (i > 0) then
              str_ss = trim(str_ss(1:i-1))
           end if

           ! apply the timestamp template
           call ESMF_TimeGet(time, yy=yy, mm=mm, dd=dd, h=hs, m=ms, s=ss, _RC)

           i = scan(str_yy, '%'); if (i == 0) read (str_yy, '(I4)') yy
           i = scan(str_mm, '%'); if (i == 0) read (str_mm, '(I2)') mm
           i = scan(str_dd, '%'); if (i == 0) read (str_dd, '(I2)') dd
           i = scan(str_hs, '%'); if (i == 0) read (str_hs, '(I2)') hs
           i = scan(str_ms, '%'); if (i == 0) read (str_ms, '(I2)') ms
           i = scan(str_ss, '%'); if (i == 0) read (str_ss, '(I2)') ss

           call ESMF_TimeSet(timestamp_, yy=yy, mm=mm, dd=dd, h=hs, m=ms, s=ss, _RC)
        end if

        _RETURN(ESMF_SUCCESS)

     end function timestamp_

     subroutine CreateTimeInterval(item,clock,rc)
        type(PrimaryExport)      , intent(inout) :: item
        type(ESMF_Clock)          , intent(in   ) :: clock
        integer, optional         , intent(out  ) :: rc

        integer                    :: iyy,imm,idd,ihh,imn,isc
        integer                    :: lasttoken
        character(len=2)           :: token
        type(ESMF_Time)            :: time,start_time
        integer                    :: cindex,pindex
        character(len=ESMF_MAXSTR) :: creffTime, ctInt

        integer :: status
        logical :: found

        creffTime = ''
        ctInt     = ''
        call ESMF_ClockGet (CLOCK, currTIME=time, startTime=start_time, _RC)
        if (.not.item%hasFileReffTime) then
           ! if int_frequency is less than zero than try to guess it from the file template
           ! if that fails then it must be a single file or a climatology

           call ESMF_TimeGet(time, yy=iyy, mm=imm, dd=idd,h=ihh, m=imn, s=isc  ,_RC)
           !=======================================================================
           ! Using "now" as a reference time makes it difficult to find a file if
           ! we need to extrapolate, and doesn't make an awful lot of sense anyway.
           ! Instead, use the start of (current year - 20) or 1985, whichever is
           ! earlier (SDE 2016-12-30)
           iyy = Min(iyy-20,1985)
           imm = 1
           idd = 1
           ihh = 0
           imn = 0
           isc = 0
           !=======================================================================
           lasttoken = index(item%file,'%',back=.true.)
           if (lasttoken.gt.0) then
              token = item%file(lasttoken+1:lasttoken+2)
              select case(token)
              case("y4")
                 call ESMF_TimeSet(item%reff_time,yy=iyy,mm=1,dd=1,h=0,m=0,s=0,_RC)
                 call ESMF_TimeIntervalSet(item%frequency,startTime=start_time,yy=1,_RC)
              case("m2")
                 call ESMF_TimeSet(item%reff_time,yy=iyy,mm=imm,dd=1,h=0,m=0,s=0,_RC)
                 call ESMF_TimeIntervalSet(item%frequency,startTime=start_time,mm=1,_RC)
              case("d2")
                 call ESMF_TimeSet(item%reff_time,yy=iyy,mm=imm,dd=idd,h=0,m=0,s=0,_RC)
                 call ESMF_TimeIntervalSet(item%frequency,startTime=start_time,d=1,_RC)
              case("h2")
                 call ESMF_TimeSet(item%reff_time,yy=iyy,mm=imm,dd=idd,h=ihh,m=0,s=0,_RC)
                 call ESMF_TimeIntervalSet(item%frequency,startTime=start_time,h=1,_RC)
              case("n2")
                 call ESMF_TimeSet(item%reff_time,yy=iyy,mm=imm,dd=idd,h=ihh,m=imn,s=0,_RC)
                 call ESMF_TimeIntervalSet(item%frequency,startTime=start_time,m=1,_RC)
              end select
           else
              ! couldn't find any tokens so all the data must be on one file
              call ESMF_TimeIntervalSet(item%frequency,_RC)

              ! check if non-token file exists
              inquire(file=trim(item%file),EXIST=found)
              _ASSERT(found,'File ' // trim(item%file) // ' not found')
           end if
        else
           ! Reference time should look like:
           ! YYYY-MM-DDThh:mm:ssPYYYY-MM-DDThh:mm:ss
           ! The date before the P is the reference time, from which future times
           ! will be taken. The date after the P is the frequency with which the
           ! file changes. For example, if the data is referenced to 1985 and
           ! there is 1 file per year, the reference time should be
           ! 1985-01-01T00:00:00P0001-00-00T00:00:00
           ! Get refference time, if not provided use current model date
           pindex=index(item%FileReffTime,'P')
           if (pindex==0) then
              _FAIL( 'ERROR: File template ' // item%file // ' has invalid reference date format')
           end if
           cReffTime = item%FileReffTime(1:pindex-1)
           if (trim(cReffTime) == '') then
              item%reff_time = Time
           else
              call MAPL_NCIOParseTimeUnits(cReffTime,iyy,imm,idd,ihh,imn,isc,status)
              _VERIFY(STATUS)
              call ESMF_TimeSet(item%reff_time,yy=iyy,mm=imm,dd=idd,h=ihh,m=imn,s=isc,rc=status)
              _VERIFY(STATUS)
           end if
           ! now get time interval. Put 0000-00-00 in front if not there so parsetimeunits doesn't complain
           ctInt = item%FileReffTime(pindex+1:)
           cindex = index(ctInt,'T')
           if (cindex == 0) ctInt = '0000-00-00T'//trim(ctInt)
           call MAPL_NCIOParseTimeUnits(ctInt,iyy,imm,idd,ihh,imn,isc,status)
           _VERIFY(STATUS)
           call ESMF_TimeIntervalSet(item%frequency,yy=iyy,mm=imm,d=idd,h=ihh,m=imn,s=isc,rc=status)
           _VERIFY(STATUS)
        end if

        if (lgr%isEnabledFor(DEBUG)) then
           call lgr%debug(' >> REFFTIME for %a~: %a',trim(item%file), '<'//trim(item%FileReffTime)//'>')
           call ESMF_TimeGet(item%reff_time,yy=iyy,mm=imm,dd=idd,h=ihh,m=imn,s=isc,rc=status)
           call lgr%debug(' >> Reference time: %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iYy, iMm, iDd, iHh, iMn, iSc)
           call ESMF_TimeIntervalGet(item%frequency,yy=iyy,mm=imm,d=idd,h=ihh,m=imn,s=isc,rc=status)
           call lgr%debug(' >> Frequency     : %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iYy, iMm, iDd, iHh, iMn, iSc)
        endif
        _RETURN(ESMF_SUCCESS)

     end subroutine CreateTimeInterval

     subroutine GetClimYear(item, rc)

        type(PrimaryExport)      , intent(inout) :: item
        integer, optional        , intent(out  ) :: rc

        integer(ESMF_KIND_I4)      :: iyr
        type(ESMF_TimeInterval)    :: zero
        integer                    :: lasttoken
        character(len=ESMF_MAXPATHLEN) :: file
        character(len=2)           :: token
        integer                    :: nymd, nhms, climYear
        character(len=ESMF_MAXSTR) :: buffer
        logical                    :: inRange
        type(FileMetadataUtils), pointer :: metadata
        integer :: status

        buffer = trim(item%cyclic)

        if (trim(buffer) == 'n') then

           item%cyclic = "n"
           _RETURN(ESMF_SUCCESS)

        else if (trim(buffer) == 'single') then

           _RETURN(ESMF_SUCCESS)
        else if (trim(buffer) == 'y') then

           item%cyclic = "y"

           call ESMF_TimeIntervalSet(zero,_RC)

           if (item%frequency == zero) then
              file = item%file
           else
              lasttoken = index(item%file,'%',back=.true.)
              token = item%file(lasttoken+1:lasttoken+2)
              _ASSERT(token == "m2",'Clim year must be month template "%m2"')
              ! just put a time in so we can evaluate the template to open a file
              nymd = 20000101
              nhms = 0
              call fill_grads_template(file,item%file,nymd=nymd,nhms=nhms,_RC)
           end if
           call MakeMetadata(file,item%pfioCollection_id,metadata,_RC)
           call metadata%get_time_info(startYear=iyr)
           item%climYear=iYr
           _RETURN(ESMF_SUCCESS)
        else
           read(buffer,'(I4)') climYear
           inRange = 0 <= climYear .and. climYear <= 3000
           if (inRange) then
              item%cyclic = "y"
              item%climYear = climYear
              _RETURN(ESMF_SUCCESS)
           else
              _FAIL( 'cyclic keyword was not y, n, or a valid year (0 < year < 3000)')
           end if
        end if

     end subroutine GetClimYear

     subroutine GetLevs(item, time, state, allowExtrap, rc)

        type(PrimaryExport)      , intent(inout) :: item
        type(ESMF_Time)          , intent(inout) :: time
        type(ESMF_State)         , intent(in   ) :: state
        logical                  , intent(in   ) :: allowExtrap
        integer, optional        , intent(out  ) :: rc

        integer :: status

        integer(ESMF_KIND_I4)      :: iyr,imm,idd,ihr,imn,iss,i,n,refYear
        character(len=ESMF_MAXPATHLEN) :: file
        integer                    :: nymd, nhms, rank
        type(ESMF_Time)            :: fTime
        type(ESMF_Field)           :: field
        real, allocatable          :: levFile(:)
        character(len=ESMF_MAXSTR) :: buff,levunits,tlevunits,temp_name
        logical                    :: found,lFound,intOK
        integer                    :: maxOffset
        character(len=:), allocatable :: levname
        character(len=:), pointer :: positive
        type(FileMetadataUtils), pointer :: metadata
        type(Variable), pointer :: var
        type(ESMF_TimeInterval)    :: zero
        integer :: vect_semi

        positive=>null()

        call ESMF_TimeIntervalSet(zero,_RC)

        vect_semi=index(item%name,";")
        if (vect_semi/=0) then
           temp_name=item%name(:vect_semi-1)
        else
           temp_name=item%name
        end if
        call ESMF_StateGet(state,trim(temp_name),field,_RC)
        call ESMF_FieldGet(field,rank=rank,_RC)
        if (rank==2) then
           item%lm=0
           _RETURN(_SUCCESS)
        end if

        if (item%frequency == zero) then

           file = item%file
           Inquire(file=trim(file),EXIST=found)

        else
           buff = trim(item%refresh_template)
           buff = ESMF_UtilStringLowerCase(buff, _RC)
           if ( index(buff,'t')/=0) then
              if (index(buff,'p') == 0) then
                 ftime = timestamp_(time,buff,_RC)
              else
                 ftime = time
              end if
           else
              ftime = time
           end if

           call ESMF_TimeGet(fTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=iss,_RC)
           if (item%cyclic == 'y') then
              iyr = item%climyear
           end if
          call MAPL_PackTime(nymd,iyr,imm,idd)
          call MAPL_PackTime(nhms,ihr,imn,iss)
          call fill_grads_template(file,item%file,nymd=nymd,nhms=nhms,_RC)
          Inquire(file=trim(file),EXIST=found)

        end if

        if (found) then
           call MakeMetadata(file,item%pfioCollection_id,metadata,_RC)
        else
           if (allowExtrap .and. (item%cyclic == 'n') ) then

              ftime = item%reff_time
              n = 0
              maxOffSet = 100
              call ESMF_TimeGet(item%reff_time,yy=refYear)
              lfound = .false.
              intOK = .true.
              do while (intOK .and. (.not.lfound))
                 call ESMF_TimeGet(fTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=iss,_RC)
                 call MAPL_PackTime(nymd,iyr,imm,idd)
                 call MAPL_PackTime(nhms,ihr,imn,iss)
                 call fill_grads_template(file,item%file,nymd=nymd,nhms=nhms,_RC)
                 Inquire(file=trim(file),exist=lfound)
                 intOK = (abs(iYr-refYear)<maxOffset)
                 if (.not.lfound) then
                    n = n + 1
                    ftime = ftime + item%frequency
                 else
                    call MakeMetadata(file,item%pfioCollection_id,metadata,_RC)
                 end if
              enddo

              if (.not.lfound) then
                 _FAIL( 'From ' // trim(item%file) // ' could not find file with extrapolation')
              end if
           else
              _FAIL('From ' // trim(item%file) // ' could not find time no extrapolation')
           end if

        end if

        var => null()
        if (item%isVector) then
           var=>metadata%get_variable(trim(item%fcomp1))
           _ASSERT(associated(var),"Variable "//TRIM(item%fcomp1)//" not found in file "//TRIM(item%file))
           var => null()
           var=>metadata%get_variable(trim(item%fcomp2))
           _ASSERT(associated(var),"Variable "//TRIM(item%fcomp2)//" not found in file "//TRIM(item%file))
        else
           var=>metadata%get_variable(trim(item%var))
           _ASSERT(associated(var),"Variable "//TRIM(item%var)//" not found in file "//TRIM(item%file))
        end if

        levName = metadata%get_level_name(rc=status)
        _VERIFY(status)
        if (trim(levName) /='') then
           call metadata%get_coordinate_info(levName,coordSize=item%lm,coordUnits=tLevUnits,coords=levFile,_RC)
           levUnits=MAPL_TrimString(tlevUnits)
           ! check if pressure
           item%levUnit = ESMF_UtilStringLowerCase(levUnits)
           if (trim(item%levUnit) == 'hpa' .or. trim(item%levUnit)=='pa') then
              item%havePressure = .true.
           end if
           if (item%havePressure) then
              if (levFile(1)>levFile(size(levFile))) item%fileVDir="up"
           else
              positive => metadata%get_variable_attribute(levName,'positive',_RC)
              if (associated(positive)) then
                 if (MAPL_TrimString(positive)=='up') item%fileVDir="up"
              end if
           end if

           allocate(item%levs(item%lm),__STAT__)
           item%levs=levFile
           if (trim(item%fileVDir)/=trim(item%importVDir)) then
              do i=1,size(levFile)
                 item%levs(i)=levFile(size(levFile)-i+1)
              enddo
           end if
           if (trim(item%levunit)=='hpa') item%levs=item%levs*100.0
           if (item%isVector) then
              item%units = metadata%get_variable_attribute(trim(item%fcomp1),"units",rc=status)
              _VERIFY(status)
           else
              item%units = metadata%get_variable_attribute(trim(item%var),"units",rc=status)
              _VERIFY(status)
           end if

        else
           item%LM=0
        end if

        _RETURN(ESMF_SUCCESS)

     end subroutine GetLevs

     subroutine UpdateBracketTime(item,cTime,bSide,interpTime,fileTime,file_processed,allowExtrap,rc)
        type(PrimaryExport),                 intent(inout) :: item
        type(ESMF_Time),                     intent(inout) :: cTime
        character(len=1),                    intent(in   ) :: bSide
        type(ESMF_TIME),                     intent(inout) :: interpTime
        type(ESMF_TIME),                     intent(inout) :: fileTime
        character(len=*),                    intent(inout) :: file_processed
        logical,                             intent(in   ) :: allowExtrap
        integer, optional,                   intent(out  ) :: rc

        integer :: status

        type(ESMF_Time)                            :: newTime
        integer                                    :: curDate,curTime,n,tindex
        integer(ESMF_KIND_I4)                      :: iyr, imm, idd, ihr, imn, isc, oldYear
        integer(ESMF_KIND_I4)                      :: fyr, fmm, fdd, fhr, fmn, fsc
        type(ESMF_TimeInterval)                    :: zero
        type(ESMF_Time)                            :: fTime
        logical                                    :: UniFileClim
        type(ESMF_Time)                            :: readTime

        ! Allow for extrapolation.. up to a limit
        integer                                    :: yrOffset,yrOffsetStamp
        integer(ESMF_KIND_I4)                      :: cYearOff, refYear
        character(len=ESMF_MAXSTR)                 :: buff
        integer, parameter                         :: maxOffset=10000
        logical                                    :: found, newFile
        logical                                    :: LExtrap, RExtrap, LExact, RExact
        logical                                    :: LSide, RSide, intOK, bracketScan

        type(ESMF_Time), allocatable               :: xTSeries(:)
        type(FileMetaDataUtils), pointer           :: fdata

        call lgr%info('Updating %a1 bracket for %a',bside, trim(item%name))
        call ESMF_TimeIntervalSet(zero,_RC)

        ! Default
        fTime = cTime
        bracketScan = .False.

        ! Is there only one file for this dataset?
        if (item%frequency == zero) then

           call lgr%debug('            UpdateBracketTime: Scanning fixed file %a for side %a1', trim(item%file), bSide)

           UniFileClim = .false.
           ! if the file is constant, i.e. no tokens in in the template
           ! but it was marked as cyclic we must have a year long climatology
           ! on one file, set UniFileClim to true
           if (trim(item%cyclic)=='y') UniFileClim = .true.
           file_processed = item%file
           call MakeMetadata(file_processed,item%pfioCollection_id,fdata,_RC)
           ! Retrieve the time series
           call fdata%get_time_info(timeVector=xTSeries,rc=status)
           if (status /= ESMF_SUCCESS) then
              call lgr%error('Time vector retrieval failed on fixed file %a',trim(item%file))
              _RETURN(ESMF_FAILURE)
           end if
           call GetBracketTimeOnSingleFile(fdata,xTSeries,cTime,bSide,UniFileClim,interpTime,fileTime,tindex,allowExtrap,item%climYear,rc=status)
           if (status /= ESMF_SUCCESS) then
              call lgr%error('Bracket timing request failed on fixed file %a for side %a', trim(item%file), bSide)
              _RETURN(ESMF_FAILURE)
           end if
        else

           if (lgr%isEnabledFor(DEBUG)) then
              call lgr%debug('            UpdateBracketTime: Scanning template %a for side %a1',trim(item%file), bSide)
              call ESMF_TimeGet(ctime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,rc=status)
              call lgr%debug('       UpdateBracketTime: Target time   : %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, imm, idd, ihr, imn, isc)
              call ESMF_TimeGet(item%reff_time,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,rc=status)
              call lgr%debug('       UpdateBracketTime: Reference time: %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, imm, idd, ihr, imn, isc)
           endif
           UniFileClim = .false.
           found = .false.
           ! Start by assuming the file we want exists
           if (trim(item%cyclic)=='y') then
              ! if climatology compute year offset
              call ESMF_TimeGet(cTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
              yrOffset = item%climYear - iyr
              call OffsetTimeYear(cTime,yrOffset,fTime,rc)
           else
              yrOffset = 0
              if (item%reff_time > cTime) then
                 _FAIL('Reference time for file ' // trim(item%file) // ' is too late')
              end if
              ! This approach causes a problem if cTime and item%reff_time are too far
              ! apart - do it the hard way instead...
              ftime = item%reff_time
              n = 0
              ! SDE DEBUG: This caused problems in the past but the
              ! alternative is far too slow... need to keep an eye
              ! on this but the Max(0,...) should help.
              n = max(0,floor((cTime-item%reff_time)/item%frequency))
              if (n>0) fTime = fTime + (n*item%frequency)
              do while (.not.found)
                 ! SDE: This needs to be ">"
                 found = ((ftime + item%frequency) > ctime)
                 if (.not.found) then
                    n = n + 1
                    ftime = fTime+item%frequency
                 end if
              end do

              if (lgr%isEnabledFor(DEBUG)) then
                 call lgr%debug('            UpdateBracketTime: untemplating %a',trim(item%file))
                 call ESMF_TimeGet(cTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,rc=status)
                 call lgr%debug('     ==> Target time    : %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, iMm, iDd, ihr, iMn, iSc)
                 call ESMF_TimeGet(fTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,rc=status)
                 call lgr%debug('     ==> Target time    : %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, iMm, iDd, ihr, iMn, iSc)
                 call ESMF_TimeIntervalGet(item%frequency,yy=iyr,mm=imm,d=idd,h=ihr,m=imn,s=isc,rc=status)
                 call lgr%debug('     ===> item%%frequency: Reference time: %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, iMm, iDd, ihr, iMn, iSc)
                 call lgr%debug('     ===> # iterations until found %i5', n)
              endif

           end if
           readTime = cTime
           call ESMF_TimeGet(fTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
           call MAPL_PackTime(curDate,iyr,imm,idd)
           call MAPL_PackTime(curTime,ihr,imn,isc)
           call fill_grads_template(file_processed,item%file,nymd=curDate,nhms=curTime,_RC)
           Inquire(FILE=trim(file_processed),EXIST=found)
           if (found) then
              call lgr%debug(' Target file for %a found and is %a', trim(item%file), trim(file_processed))
              !yrOffset = 0
           Else if (allowExtrap) then

              if (lgr%isEnabledFor(DEBUG)) then
                 call lgr%debug('            UpdateBracketTime: Target file not found: %a', trim(item%file))
                 call lgr%debug('            ==> Propagating forwards in file from reference time')
                 call ESMF_TimeGet(item%reff_time,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 call lgr%debug('            ==> Reference time: %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, imm, idd, ihr, imn, isc)
              end if

              ! Go back to the reference time, and propagate forwards until we find
              ! the first valid file
              ftime = item%reff_time
              call ESMF_TimeGet(item%reff_time,yy=refYear,_RC)
              if (refYear.lt.1850) then
                 call lgr%info('            UpdateBracketTime: Reference year too early (%i0.4~). Aborting search for data from %a', refYear, trim(item%file))
                 _RETURN(ESMF_FAILURE)
              End If
              intOK = .True.
              found = .false.
              ! yrOffset currently tracking how far we are from the reference year
              n = 0
              yrOffset = 0
              ftime = item%reff_time
              Do While (intOK.and.(.not.found))
                 call ESMF_TimeGet(fTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 call MAPL_PackTime(curDate,iyr,imm,idd)
                 call MAPL_PackTime(curTime,ihr,imn,isc)
                 call fill_grads_template(file_processed,item%file,nymd=curDate,nhms=curTime,_RC)
                 Inquire(FILE=trim(file_processed),EXIST=found)
                 yrOffset = iYr-refYear
                 intOK = (abs(yrOffset)<maxOffset)
                 if (.not.found) then
                    n = n + 1
                    ftime = ftime + item%frequency
                 end if
              End Do
              if (.not.found) then
                 call lgr%error('UpdateBracketTime: Could not find data within maximum offset range from %a ',trim(item%file))
                 call lgr%error('            ==> Test year: %i0 and reference year: %i0 ', iYr, refYear)
                 call ESMF_TimeGet(item%reff_time,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 call lgr%error('            ==> Reference time: %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, imm, idd, ihr, imn, isc)
                 call ESMF_TimeGet(fTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 call lgr%error('            ==> Last check    : %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, imm, idd, ihr, imn, isc)
                 _RETURN(ESMF_FAILURE)
              End If
              call MakeMetadata(file_processed,item%pfioCollection_id,fdata,_RC)
              ! Retrieve the time series
              if (allocated(xTseries)) deallocate(xTseries)
              call fdata%get_time_info(timeVector=xTseries,_RC)
              ! Is this before or after our target time?
              LSide   = (bSide == "L")
              RSide   = (.not.LSide)
              LExact  = (cTime == xTSeries(1))
              LExtrap = (cTime <  xTSeries(1))
              RExact  = (cTime == xTSeries(size(xTSeries)))
              RExtrap = (cTime >  xTSeries(size(XTSeries)))
              found = .false.
              If (LExtrap.or.(LExact.and.RSide)) Then

                 call lgr%debug('            UpdateBracketTime: Extrapolating BACKWARD for bracket %a1 for file %a', bSide, trim(item%file))

                 ! We have data from future years
                 ! Advance the target time until we can have what we want
                 call ESMF_TimeGet(cTime,yy=cYearOff,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 iYr = refYear + yrOffset
                 ! Convert year offset to the future value
                 yrOffset = iYr - cYearOff
                 ! Determine the template time
                 call OffsetTimeYear(cTime,yrOffset,newTime,_RC)
                 ftime = item%reff_time
                 n = 0
                 do while (.not.found)
                    found = ((ftime + item%frequency) > newtime)
                    if (.not.found) then
                       n = n + 1
                       ftime = fTime+item%frequency
                    end if
                 end do
                 ! untemplate file
                 call ESMF_TimeGet(fTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 ! Build file name
                 call MAPL_PackTime(curDate,iyr,imm,idd)
                 call MAPL_PackTime(curTime,ihr,imn,isc)
                 call fill_grads_template(file_processed,item%file,nymd=curDate,nhms=curTime,_RC)
                 call lgr%debug('            UpdateBracketTime: Testing for file %a for target time %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', &
                      & trim(file_processed), iyr, iMm, iDd, iHr, iMn, iSc)

                 Inquire(FILE=trim(file_processed),EXIST=found)
                 if (.not.found) then
                    call lgr%error('Failed to project data from %a for side %a', trim(item%file), bside)
                    _RETURN(ESMF_FAILURE)
                 End If
              ElseIf (RExtrap.or.(RExact.and.RSide)) Then

                 call lgr%debug('            UpdateBracketTime: Extrapolating FORWARD for bracket %a1 for file %a', bSide, trim(item%file))

                 ! We have data from past years
                 ! Rewind the target time until we can have what we want
                 call ESMF_TimeGet(cTime,yy=refYear,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 yrOffset = 0
                 fTime = cTime
                 ! yrOffset: Number of years added from current time to get file time
                 Do While ((.not.found).and.(abs(yrOffset).lt.maxOffset))
                    yrOffset = yrOffset - 1
                    call OffsetTimeYear(cTime,yrOffset,newTime,_RC)

                    ! Error check - if the new time is before the first file time,
                    ! all is lost
                    If (newTime.lt.xTSeries(1)) exit
                    do while (ftime > newTime)
                       fTime = fTime - item%frequency
                       n = n - 1
                    end do
                    ! untemplate file
                    call ESMF_TimeGet(fTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                    call MAPL_PackTime(curDate,iyr,imm,idd)
                    call MAPL_PackTime(curTime,ihr,imn,isc)
                    call fill_grads_template(file_processed,item%file,nymd=curDate,nhms=curTime,_RC)
                    Inquire(FILE=trim(file_processed),EXIST=found)
                 End Do
                 if (.not.found) then
                    call lgr%error('Could not determine upper bounds on %a for side %a', trim(item%file), bSide)
                    _RETURN(ESMF_FAILURE)
                 End If
              Else
                 call lgr%error('Could not find appropriate file from file template %a for side %a', trim(item%file), bSide)
                 _RETURN(ESMF_FAILURE)
              End If
           End If

           ! Should now have the "correct" time
           call lgr%debug('            UpdateBracketTime: Making metadata for %a', trim(file_processed))
           call MakeMetadata(file_processed,item%pfioCOllection_id,fdata,_RC)
           ! Retrieve the time series
           if (allocated(xTseries)) deallocate(xTseries)
           call fdata%get_time_info(timeVector=xTSeries,_RC)

           ! We now have a time which, when passed to the FILE TEMPLATE, returns a valid file
           ! However, if the file template does not include a year token, then the file in
           ! question could actually be for a different year. We therefore feed the file time
           ! into the refresh template and see if the result has the same year. If it doesn't,
           ! then we can assume that the year is actually fixed, and the times in the file will
           ! correspond to the year in the refresh template. In this case, an additional year
           ! offset must be applied.
           yrOffsetStamp = 0
           buff = trim(item%refresh_template)
           buff = ESMF_UtilStringLowerCase(buff, _RC)
           If (buff /= "0" .and. index(buff,"p")==0) Then
              newTime = timestamp_(fTime,item%refresh_template,_RC)
              if (newTime .ne. fTime) Then
                 call ESMF_TimeGet(fTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 call ESMF_TimeGet(newTime,yy=fyr,mm=fmm,dd=fdd,h=fhr,m=fmn,s=fsc,_RC)
                 yrOffsetStamp = fYr - iYr
              End If
           End If

           ! try to get bracketing time on file using current time
           call GetBracketTimeOnFile(fdata,xTSeries,readTime,bSide,UniFileClim,interpTime,fileTime,tindex,yrOffsetInt=yrOffset+yrOffsetStamp,rc=status)
           found = (status==ESMF_SUCCESS)

           call lgr%debug('            UpdateBracketTime: Found status of %a~: %l1', trim(file_processed), found)

           ! if we didn't find the bracketing time look forwards or backwards depending on
           ! whether it is the right or left time
           if (.not.found) then

              call lgr%debug('            UpdateBracketTime: Scanning for bracket %a1 of %a~. RSide: %l1', bSide, trim(file_processed), (bSide=="R"))

              bracketScan = .True.
              newTime = fTime
              if (bSide == "R") then
                 found=.false.
                 newFile=allowExtrap
                 status = ESMF_SUCCESS

                 call lgr%debug('            UpdateBracketTime: Sanity check on file %a with flags: %i5 %2L1', &
                      & trim(file_processed), status, wrapArray([status==ESMF_SUCCESS, found]))

                 do while ((status==ESMF_SUCCESS).and.(.not.found))
                    ! check next time
                    newTime = fTime + item%frequency
                    if (trim(item%cyclic)=='y') then
                       call ESMF_TimeGet(fTime,yy=OldYear)
                       call ESMF_TimeGet(newTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                       if (oldyear/=iyr) then
                          call ESMF_TimeSet(newTime,yy=oldyear,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                          yrOffset = yrOffset - 1
                          call lgr%info('            UpdateBracketTime: IN clim after %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2',Oldyear,iMm,iDd,iHr,Imn,iSc)
                       end if
                    end if
                    ! untemplate file
                    call ESMF_TimeGet(newTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)

                    call MAPL_PackTime(curDate,iyr,imm,idd)
                    call MAPL_PackTime(curTime,ihr,imn,isc)
                    call fill_grads_template(file_processed,item%file,nymd=curDate,nhms=curTime,_RC)

                    call lgr%debug('            UpdateBracketTime: Testing for file %a for target time %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', trim(file_processed), iYr, iMm, iDd, iHr, iMn, iSc)

                    Inquire(FILE=trim(file_processed),EXIST=found)
                    If (found) Then
                       fTime = newTime
                    Else If (newFile) Then
                       ! We went RIGHT - cycle round by SUBTRACTING a year
                       yrOffset = yrOffset - 1
                       newFile = .False. ! Only one attempt
                       call OffsetTimeYear(fTime,-1,newTime,rc)
                       fTime = newTime
                    Else
                       status = ESMF_FAILURE
                    End If
                 End Do
                 if (status /= ESMF_SUCCESS) then
                    call lgr%error('ExtData could not find appropriate file from file template %a for side %a1', trim(item%file), bSide)
                    _RETURN(ESMF_FAILURE)
                 end if
              else if (bSide == "L") then
                 found=.false.
                 newFile=allowExtrap
                 status = ESMF_SUCCESS
                 do while ((status==ESMF_SUCCESS).and.(.not.found))
                    ! check next time
                    newTime = fTime - item%frequency
                    if (trim(item%cyclic)=='y') then
                       call ESMF_TimeGet(fTime,yy=OldYear)
                       call ESMF_TimeGet(newTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                       if (oldyear/=iyr) then
                          call ESMF_TimeSet(newTime,yy=oldyear,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                          yrOffset = yrOffset + 1
                       end if
                    end if
                    ! untemplate file
                    call ESMF_TimeGet(newTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)

                    call MAPL_PackTime(curDate,iyr,imm,idd)
                    call MAPL_PackTime(curTime,ihr,imn,isc)
                    call fill_grads_template(file_processed,item%file,nymd=curDate,nhms=curTime,_RC)
                    Inquire(FILE=trim(file_processed),EXIST=found)
                    If (found) Then
                       fTime = newTime
                    Else If (newFile) Then
                       ! We went LEFT - cycle round by ADDING a year
                       yrOffset = yrOffset + 1
                       newFile = .False. ! Only one attempt
                       call OffsetTimeYear(fTime,+1,newTime,rc)
                       fTime = newTime
                    Else
                       status = ESMF_FAILURE
                    End If
                 End Do
                 if (status /= ESMF_SUCCESS) then
                    call lgr%error('ExtData could not find appropriate file from file template %a for side %a1', trim(item%file), bSide)
                    _RETURN(ESMF_FAILURE)
                 end if
              end if

              ! fTime is now ALWAYS the time which was applied to the file template to get the current file
              call MakeMetadata(file_processed,item%pfioCollection_id,fdata,rc=status)
              if (allocated(xTSeries)) deallocate(xTSeries)
              call fdata%get_time_info(timeVector=xTSeries,_RC)

              !If (Mapl_Am_I_Root()) Write (*,'(a,a,x,a)') ' SUPERDEBUG: File/template: ',Trim(file_processed),Trim(item%refresh_template)
              ! The file template may be "hiding" a year offset from us
              yrOffsetStamp = 0
              buff = trim(item%refresh_template)
              buff = ESMF_UtilStringLowerCase(buff, _RC)
              If (buff /= "0" .and. index(buff,"p")==0 ) Then
                 newTime = timestamp_(fTime,item%refresh_template,_RC)

                 if (lgr%isEnabledFor(DEBUG)) then
                    call ESMF_TimeGet(fTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                    call ESMF_TimeGet(newTime,yy=fyr,mm=fmm,dd=fdd,h=fhr,m=fmn,s=fsc,_RC)
                    call lgr%debug('            UpdateBracketTime: Template %a applied: %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2 ', &
                         & trim(item%refresh_template), iyr, imm, idd, ihr, imn, isc)
                    call lgr%debug('                                                 -> %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2 on file %a', &
                         fyr, fmm, fdd, fhr, fmn, fsc, trim(file_processed))
                 End If

                 if (newTime .ne. fTime) Then
                    call ESMF_TimeGet(fTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                    call ESMF_TimeGet(newTime,yy=fyr,mm=fmm,dd=fdd,h=fhr,m=fmn,s=fsc,_RC)
                    yrOffsetStamp = fYr - iYr

                    call lgr%debug('            UpdateBracketTime: Year offset modified from %i4 to %i4 to satisfy refresh template for %a', yrOffset, yrOffset+yrOffsetStamp, trim(file_processed))
                 End If
              End If

              ! try to get bracketing time on file using new time
              call GetBracketTimeOnFile(fdata,xTSeries,readTime,bSide,UniFileClim,interpTime,fileTime,tindex,yrOffsetInt=yrOffset+yrOffsetStamp,rc=status)
              found = (status == ESMF_SUCCESS)
              if (.not.found) then
                 call lgr%error('ExtData could not find bracketing data from file template %a for side %a1', trim(item%file), bSide)
                 _RETURN(ESMF_FAILURE)

              end if

           end if

        end if


        if (lgr%isEnabledFor(DEBUG)) then
           call lgr%debug('            UpdateBracketTime: Updated bracket %a1 for %a', bside, trim(file_processed))
           call ESMF_TimeGet(cTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
           call lgr%debug('            ==> (%a1) Time Requested: %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', bside, iYr, iMm, iDd, iHr, iMn, iSc)
           call ESMF_TimeGet(fileTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
           call lgr%debug('            ==> (%a1) Record time   : %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', bside, iYr, iMm, iDd, iHr, iMn, iSc)
           call ESMF_TimeGet(interpTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
           call lgr%debug('            ==> (%a1) Effective time: %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', bside, iYr, iMm, iDd, iHr, iMn, iSc)
        End If

        ! If we made it this far, then I guess we are OK?
        if (bside =='R') then
           item%tindex2=tindex
        else if (bside =='L') then
           item%tindex1=tindex
        end if
        call lgr%info(' ... file processed: %a', trim(file_processed))

        _RETURN(ESMF_SUCCESS)

     end subroutine UpdateBracketTime

     subroutine swapBracketInformation(item,rc)
        type(PrimaryExport), intent(inout) :: item
        integer, optional, intent(out) :: rc

        integer :: status
        integer :: j, fieldRank, fieldCount
        type(ESMF_Field) :: field1, field2
        real, pointer :: var2d_prev(:,:)
        real, pointer :: var3d_prev(:,:,:)
        real, pointer :: var2d_next(:,:)
        real, pointer :: var3d_next(:,:,:)
        character(len=ESMF_MAXSTR), ALLOCATABLE  :: NAMES (:)

        item%interp_time1 = item%interp_time2

        if (item%vartype == MAPL_FieldItem) then

           call ESMF_FieldGet(item%modelGridFields%v1_finterp1, dimCount=fieldRank,_RC)
           if (fieldRank == 2) then
              call ESMF_FieldGet(item%modelGridFields%v1_finterp1, localDE=0, farrayPtr=var2d_prev, _RC)
              call ESMF_FieldGet(item%modelGridFields%v1_finterp2, localDE=0, farrayPtr=var2d_next, _RC)
              var2d_prev=var2d_next
           else if (fieldRank == 3) then
              call ESMF_FieldGet(item%modelGridFields%v1_finterp1, localDE=0, farrayPtr=var3d_prev, _RC)
              call ESMF_FieldGet(item%modelGridFields%v1_finterp2, localDE=0, farrayPtr=var3d_next, _RC)
              var3d_prev=var3d_next
           endif

        else if (item%vartype == MAPL_BundleItem) then

           call ESMF_FieldBundleGet(item%binterp2, fieldCount = fieldCount, _RC)
           allocate(names(fieldCount),__STAT__)
           call ESMF_FieldBundleGet(item%binterp2, fieldNameList = Names, _RC)
           do j = 1,fieldCount
              call ESMF_FieldBundleGet(item%binterp1, names(j), field=field1, _RC)
              call ESMF_FieldBundleGet(item%binterp2, names(j), field=field2, _RC)
              call ESMF_FieldGet(field1, dimCount=fieldRank, _RC)
              if (fieldRank == 2) then
                 call ESMF_FieldGet(field1, localDE=0, farrayPtr=var2d_prev, _RC)
                 call ESMF_FieldGet(field2, localDE=0, farrayPtr=var2d_next, _RC)
                 var2d_prev=var2d_next
              else if (fieldRank == 3) then
                 call ESMF_FieldGet(field1, localDE=0, farrayPtr=var3d_prev, _RC)
                 call ESMF_FieldGet(field2, localDE=0, farrayPtr=var3d_next, _RC)
                 var3d_prev=var3d_next
              endif
           enddo

           deallocate(names)

        else if (item%vartype == MAPL_ExtDataVectorItem) then

           call ESMF_FieldGet(item%modelGridFields%v1_finterp1, dimCount=fieldRank, _RC)
           if (fieldRank == 2) then
              call ESMF_FieldGet(item%modelGridFields%v1_finterp1, localDE=0, farrayPtr=var2d_prev, _RC)
              call ESMF_FieldGet(item%modelGridFields%v1_finterp2, localDE=0, farrayPtr=var2d_next, _RC)
              var2d_prev=var2d_next
              call ESMF_FieldGet(item%modelGridFields%v2_finterp1, localDE=0, farrayPtr=var2d_prev, _RC)
              call ESMF_FieldGet(item%modelGridFields%v2_finterp2, localDE=0, farrayPtr=var2d_next, _RC)
              var2d_prev=var2d_next
           else if (fieldRank == 3) then
              call ESMF_FieldGet(item%modelGridFields%v1_finterp1, localDE=0, farrayPtr=var3d_prev, _RC)
              call ESMF_FieldGet(item%modelGridFields%v1_finterp2, localDE=0, farrayPtr=var3d_next, _RC)
              var3d_prev=var3d_next
              call ESMF_FieldGet(item%modelGridFields%v2_finterp1, localDE=0, farrayPtr=var3d_prev, _RC)
              call ESMF_FieldGet(item%modelGridFields%v2_finterp2, localDE=0, farrayPtr=var3d_next, _RC)
              var3d_prev=var3d_next
           endif

        end if

     end subroutine swapBracketInformation

     subroutine makeMetadata(file,collection_id,metadata,rc)
        character(len=*), intent(in   ) :: file
        integer, intent(in)                       :: collection_id
        type(FileMetadataUtils), pointer, intent(inout)   :: metadata
        integer, optional,          intent(out  ) :: rc
        type(MAPLDataCollection), pointer :: collection => null()
        integer :: status

        Collection => DataCollections%at(collection_id)
        metadata => collection%find(file, _RC)
        call lgr%debug(' Retrieving formatter for: %a', trim(file))
        _RETURN(_SUCCESS)

     end subroutine makeMetadata

     subroutine GetTimesOnFile(cfio,tSeries,rc)
        type(ESMF_CFIO)                           :: cfio
        type(ESMF_Time)                           :: tSeries(:)
        integer, optional,          intent(out  ) :: rc

        integer :: status

        integer(ESMF_KIND_I4)              :: iyr,imm,idd,ihr,imn,isc
        integer                            :: i
        integer(ESMF_KIND_I8)              :: iCurrInterval
        integer                            :: nhmsB, nymdB
        integer                            :: begDate, begTime
        integer(ESMF_KIND_I8),allocatable  :: tSeriesInt(:)

        allocate(tSeriesInt(cfio%tSteps))
        call getDateTimeVec(cfio%fid,begDate,begTime,tSeriesInt,_RC)

        ! Assume success
        If (present(rc))  rc=ESMF_SUCCESS

        call lgr%debug('               GetTimesOnFile: Reading times')
        call lgr%debug('                  ==> File: %a', trim(cfio%fName))
        call lgr%debug('                  ==> File timing info: %i0.10 %i0.10 %i0.4', begDate, begTime, cfio%tSteps)

        do i=1,cfio%tSteps
           iCurrInterval = tSeriesInt(i)
           call GetDate ( begDate, begTime, iCurrInterval, nymdB, nhmsB, status )
           call MAPL_UnpackTime(nymdB,iyr,imm,idd)
           call MAPL_UnpackTime(nhmsB,ihr,imn,isc)


           if (lgr%isEnabledFor(DEBUG) .and. any(i == [1,cfio%tsteps])) then
              call lgr%debug('                  ==> STD Sample %i~: %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', i, iYr, iMm, iDd, iHr, iMn, iSc)
           end if
           call ESMF_TimeSet(tSeries(i), yy=iyr, mm=imm, dd=idd,  h=ihr,  m=imn, s=isc,_RC)
        enddo

        deallocate(tSeriesInt)
        return

     end subroutine GetTimesOnFile

     subroutine OffsetTimeYear(inTime,yrOffset,outTime,rc)

        type(ESMF_Time),            intent(in   ) :: inTime
        integer                                   :: yrOffset
        type(ESMF_Time),            intent(out  ) :: outTime
        integer, optional,          intent(out  ) :: rc

        __Iam__('OffsetTimeYear')

        integer(ESMF_KIND_I4)              :: iyr,imm,idd,ihr,imn,isc
        logical                            :: srcLeap, targLeap

        _UNUSED_DUMMY(Iam)
        call ESMF_TimeGet(inTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
        ! If the source year is a leap year but the new one isn't, modify to day 28
        iYr = iYr + yrOffset
        targLeap = ((imm.eq.2).and.(idd.eq.29))
        if (targLeap) then
           if (iyr.lt.1582) then
              srcLeap = .False.
           else if (modulo(iYr,4).ne.0) then
              srcLeap = .False.
           else if (modulo(iYr,100).ne.0) then
              srcLeap = .True.
           else if (modulo(iYr,400).ne.0) then
              srcLeap = .False.
           else
              srcLeap = .True.
           end if
        else
           srcLeap = .True.
        end if
        if (targLeap.and.(.not.srcLeap)) idd=28
        call ESMF_TimeSet(outTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)

        _RETURN(ESMF_SUCCESS)

     end subroutine OffsetTimeYear

     subroutine GetBracketTimeOnSingleFile(fdata,tSeries,cTime,bSide,UniFileClim,interpTime,fileTime,tindex,allowExtrap,climyear,rc)
        class(FileMetadataUtils),            intent(inout) :: fdata
        type(ESMF_Time),                     intent(in   ) :: tSeries(:)
        type(ESMF_Time),                     intent(inout) :: cTime
        character(len=1),                    intent(in   ) :: bSide
        logical,                             intent(in   ) :: UniFileClim
        type(ESMF_TIME),                     intent(inout) :: interpTime
        type(ESMF_TIME),                     intent(inout) :: fileTime
        integer,                             intent(inout) :: tindex
        logical,                             intent(in   ) :: allowExtrap
        integer,                             intent(in   ) :: climYear
        integer, optional,                   intent(out  ) :: rc

        __Iam__('GetBracketTimeOnSingleFile')

        integer(ESMF_KIND_I4)              :: iyr,imm,idd,ihr,imn,isc
        integer                            :: i
        type(ESMF_Time)                    :: climTime
        logical                            :: found
        logical                            :: LExtrap,RExtrap,LExact,RExact
        logical                            :: LSide, RSide
        integer                            :: yrOffset, yrOffsetNeg, targYear
        integer                            :: iEntry
        type(ESMF_Time), allocatable       :: tSeriesC(:)
        logical                            :: foundYear
        integer                            :: tSteps, curYear, nsteps

        _UNUSED_DUMMY(Iam)
        ! Store the target time which was actually requested
        yrOffset=0
        nsteps = size(tSeries)
        call ESMF_TimeGet(cTime,yy=targYear,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)


        if (lgr%isEnabledFor(DEBUG)) then
           call lgr%debug('               GetBracketTimeOnSingleFile called for %a', trim(fdata%get_file_name()))
           call lgr%debug('               GetBracketTimeOnSingleFile: Reading times from fixed (%l1) file %a', UniFileClim, trim(fdata%get_file_name()))
           call ESMF_TimeGet(tSeries(1),yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
           call lgr%debug('                  ==> File start    : %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, imm, idd, ihr, imn, isc)
           call ESMF_TimeGet(tSeries(nsteps),yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
           call lgr%debug('                  ==> File end      : %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, imm, idd, ihr, imn, isc)
           call ESMF_TimeGet(cTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
           call lgr%debug('                  ==> Time requested: %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, imm, idd, ihr, imn, isc)
        end if

        if (uniFileClim) then

           yrOffset = 0
           call ESMF_TimeGet(cTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
           iyr = climYear
           if (idd == 29 .and. imm == 2) idd = 28
           call ESMF_TimeSet(climTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)

           tsteps=0
           foundYear = .false.
           do i=1,nsteps

              call ESMF_TimeGet(tseries(i),yy=iyr,_RC)
              if (iyr==climYear) then
                 if (foundYear .eqv. .false.) then
                    iEntry = i
                    foundYear = .true.
                 end if
                 tsteps=tsteps+1
              end if

           end do

           allocate(tSeriesC(tsteps),__STAT__)
           do i=1,tsteps
              tSeriesC(i)=tSeries(iEntry+i-1)
           enddo

           found = .false.
           if (bSide == "L") then
              if ( (climTime < tSeriesC(1)) ) then
                 fileTime = tSeriesC(tSteps)
                 tindex = tSteps
                 call ESMF_TimeGet(tSeriesC(tSteps),yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 call ESMF_TimeGet(cTime,yy=curYear,_RC)
                 iyr = curYear - 1
                 call ESMF_TimeSet(interpTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 found = .true.
              else
                 do i=tSteps,1,-1
                    if (climTime >= tSeriesC(i)) then
                       fileTime = tSeriesC(i)
                       tindex = i
                       if (UniFileClim) then
                          call ESMF_TimeGet(cTime,yy=curYear,_RC)
                          call ESMF_TimeGet(fileTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                          call ESMF_TimeSet(interpTime,yy=curYear,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                       else
                          interpTime = tSeriesC(i)
                       end if
                       found = .true.
                       exit
                    end if
                 end do
              end if
           else if (bSide == "R") then
              if ( (climTime >= tSeriesC(tSteps)) ) then
                 fileTime = tSeriesC(1)
                 tindex = 1
                 call ESMF_TimeGet(tSeriesC(1),yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 call ESMF_TimeGet(cTime,yy=curYear,_RC)
                 iyr = curYear + 1
                 call ESMF_TimeSet(interpTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 found = .true.
              else
                 do i=1,tSteps
                    if (climTime < tSeriesC(i)) then
                       fileTime = tSeriesC(i)
                       tindex = i
                       if (UniFileClim) then
                          call ESMF_TimeGet(cTime,yy=curYear,_RC)
                          call ESMF_TimeGet(fileTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                          call ESMF_TimeSet(interpTime,yy=curYear,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                       else
                          interpTime = tSeriesC(i)
                       end if
                       found = .true.
                       exit
                    end if
                 end do
              end if
           end if

        else

           yrOffset = 0
           climTime = cTime

           ! Is the requested time within the range of values offered?
           LSide = (bSide == "L")
           RSide = (.not.LSide)
           LExact  = (cLimTime == tSeries(1))
           RExact  = (cLimTime == tSeries(nsteps))
           LExtrap = (cLimTime <  tSeries(1))
           RExtrap = (cLimTime >  tSeries(nsteps))
           found = .false.

           call lgr%debug('               GetBracketTimeOnSingleFile: Extrapolation flags (0) are %L1 %L1 %L1 %L1 for file %a',LExact,RExact,LExtrap,RExtrap, trim(fdata%get_file_name()))

           if (allowExtrap) then
              If (LExtrap) Then

                 call lgr%debug('               GetBracketTimeOnSingleFile: Requested time is before first available sample in file %a', trim(fdata%get_file_name()))

                 ! Increase the target time until it is within range
                 Do While (LExtrap)
                    yrOffset = yrOffset + 1
                    iYr = targYear + yrOffset
                    call OffsetTimeYear(cTime,yrOffset,cLimTime,rc)
                    If (LSide) Then
                       LExtrap = (cLimTime <  tSeries(1))
                    Else
                       LExtrap = (cLimTime <= tSeries(1))
                       ! When scanning for the right side, if we find that we
                       ! have an exact match to the first entry, then as long
                       ! as there is a second entry, we have the correct offset
                       If (LExtrap.and.(nsteps > 1)) Then
                          LExact  = (cLimTime == tSeries(1))
                          LExtrap = (LExtrap.and.(.not.LExact))
                       End If
                    End If
                 End Do
              Else If (RExtrap.or.(RExact.and.RSide)) Then

                 call lgr%debug('               GetBracketTimeOnSingleFile: Requested time is after or on last available sample in file %a', trim(fdata%get_file_name()))

                 Do While (RExtrap.or.(RExact.and.RSide))
                    yrOffset = yrOffset - 1
                    iYr = targYear + yrOffset
                    call OffsetTimeYear(cTime,yrOffset,cLimTime,rc)
                    If (LSide) Then
                       RExtrap = (cLimTime >  tSeries(nsteps))
                    Else
                       RExtrap = (cLimTime >= tSeries(nsteps))
                       RExact  = (cLimTime == tSeries(nsteps))
                    End If
                 End Do
              End If

              ! Retest for an exact match - note this is only useful if we want bracket L
              LExact  =  (cLimTime == tSeries(1))
              RExact  =  (cLimTime == tSeries(nsteps))

              call lgr%debug('            GetBracketTimeOnSingleFile: Extrapolation flags (2) are %L1 %L1 %L1 %L1 for file %a',LExact,RExact,LExtrap,RExtrap, trim(fdata%get_file_name()))

           End IF

           If (LSide.and.LExact) Then
              found = .true.
              iEntry = 1
           Else If (LSide.and.RExact) Then
              found = .true.
              iEntry = nsteps
           Else
              if (bSide == "L") then
                 do i=nsteps,1,-1
                    if (climTime >= tSeries(i)) then
                       iEntry = i
                       found = .true.
                       exit
                    end if
                 end do
              else if (bSide == "R") then
                 do i=1,nsteps
                    if (climTime < tSeries(i)) then
                       iEntry = i
                       found = .true.
                       exit
                    end if
                 end do
              end if
           end if

           if (found) then
              fileTime = tSeries(iEntry)
              tindex = iEntry
              if (yrOffset == 0) Then
                 interpTime = fileTime
              Else
                 yrOffsetNeg = -1*yrOffset
                 call OffsetTimeYear(fileTime,yrOffsetNeg,interpTime,rc)
              End If
           end if

        end if

        if (found) then


           if (lgr%isEnabledFor(DEBUG)) then
              call ESMF_TimeGet(fileTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
              call lgr%debug('               GetBracketTimeOnSingleFile: Data from time  %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2 set for bracket %a1 of file %a', &
                   & iyr, imm, idd, ihr, imn, isc, bside, trim(fdata%get_file_name()))
              if (yrOffset /= 0) then
                 call ESMF_TimeGet(interpTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 call lgr%debug('              ==> Mapped to:  %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, imm, idd, ihr, imn, isc)
                 call ESMF_TimeGet(interpTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 call lgr%debug('              ==> Target to:  %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', iyr, imm, idd, ihr, imn, isc)
              end if
           end if

           _RETURN(ESMF_SUCCESS)
        else
           call lgr%error('Requested sample not found in file %a', trim(fdata%get_file_name()))
           _RETURN(ESMF_FAILURE)
        endif

     end subroutine GetBracketTimeOnSingleFile

     subroutine GetBracketTimeOnFile(fdata,tSeries,cTime,bSide,UniFileClim,interpTime,fileTime,tindex,yrOffsetInt,rc)
        class(FileMetadataUtils),            intent(inout) :: fdata
        type(ESMF_Time),                     intent(in   ) :: tSeries(:)
        type(ESMF_Time),                     intent(inout) :: cTime
        character(len=1),                    intent(in   ) :: bSide
        logical,                             intent(in   ) :: UniFileClim
        type(ESMF_TIME),                     intent(inout) :: interpTime
        type(ESMF_TIME),                     intent(inout) :: fileTime
        integer,                             intent(inout) :: tindex
        integer, optional,                   intent(in   ) :: yrOffsetInt
        integer, optional,                   intent(out  ) :: rc

        __Iam__('GetBracketTimeOnFile')

        integer(ESMF_KIND_I4)              :: iyr,imm,idd,ihr,imn,isc
        integer                            :: i
        type(ESMF_Time)                    :: climTime
        logical                            :: found, outOfBounds
        integer                            :: yrOffset, yrOffsetNeg
        integer                            :: climSize,tsteps

        _UNUSED_DUMMY(Iam)
        tsteps = size(tSeries)
        ! Assume that the requested time is within range
        If (Present(yrOffsetInt)) Then
           yrOffset = yrOffsetInt
        Else
           yrOffset = 0
        End If

        if (UniFileClim) then
           call lgr%error('GetBracketTimeOnFile: called with UniFileClim true')
           _RETURN(ESMF_FAILURE)
        end if

        call lgr%debug('               GetBracketTimeOnFile: (%a1) called for %a', bside, trim(fdata%get_file_name()))

        if (yrOffset.ne.0) then
           ! If the source year is a leap year but this isn't, modify to day 28
           call OffsetTimeYear(cTime,yrOffset,cLimTime,rc)
        else
           climTime = cTime
        end if
        climSize = 1

        ! Debug output

        if (lgr%isEnabledFor(DEBUG)) then
           call ESMF_TimeGet(cLimTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
           call lgr%debug('              GetBracketTimeOnFile: Year offset of %i3 applied while scanning %a to give target time %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2', &
                & yrOffset, trim(fdata%get_file_name()), iyr, imm, idd, ihr, imn, isc)
        end if

        found = .false.
        ! we will have to specially handle a climatology in one file
        ! might be better way but can not think of one
        if (bSide == "L") then
           OutOfBounds = (cLimTime < tSeries(1))
           If (OutOfBounds) Then
              ! This can be an acceptable outcome - no printout
              if(present(RC)) RC = ESMF_FAILURE
              Return
           End If
           do i=tSteps,1,-1
              if (climTime >= tSeries(i)) then
                 fileTime = tSeries(i)
                 tindex = i
                 if (yrOffset .ne. 0) Then
                    yrOffsetNeg = -1*yrOffset
                    Call OffsetTimeYear(fileTime,yrOffsetNeg,interpTime,rc)
                 else
                    interpTime = fileTime
                 end if
                 found = .true.
                 exit
              end if
           end do
        else if (bSide == "R") then
           ! Is the requested time within the range of values offered?
           OutOfBounds = (cLimTime >= tSeries(tSteps))
           If (OutOfBounds) Then
              ! This can be an acceptable outcome - no printout
              if(present(RC)) RC = ESMF_FAILURE
              Return
           End If
           do i=1,tSteps
              if (climTime < tSeries(i)) then
                 fileTime = tSeries(i)
                 tindex = i
                 if (yrOffset .ne. 0) Then
                    yrOffsetNeg = -1*yrOffset
                    Call OffsetTimeYear(fileTime,yrOffsetNeg,interpTime,rc)
                 else
                    interpTime = fileTime
                 end if
                 found = .true.
                 exit
              end if
           end do
        end if

        if (found) then

           if (lgr%isEnabledFor(DEBUG)) then
              call ESMF_TimeGet(fileTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
              call lgr%debug('               GetBracketTimeOnFile: Data from time  %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2 set for bracket %a1 of file %a', &
                   & iyr, imm, idd, ihr, imn, isc, bside, trim(fdata%get_file_name()))
              if (yrOffset /= 0) then
                 call ESMF_TimeGet(interpTime,yy=iyr,mm=imm,dd=idd,h=ihr,m=imn,s=isc,_RC)
                 call lgr%debug('        GetBracketTimeOnFile:  ==> Mapped to:  %i0.4~-%i0.2~-%i0.2 %i0.2~:%i0.2~:%i0.2 offset %i0.2', iyr, imm, idd, ihr, imn, isc, yrOffset)
              end if
           end if

           _RETURN(ESMF_SUCCESS)
        else
           call lgr%error('Requested sample not found in file %a ', trim(fdata%get_file_name()))
        _RETURN(ESMF_FAILURE)
     endif
     !end if

  end subroutine GetBracketTimeOnFile

 subroutine CalcDerivedField(state,exportName,exportExpr,masking,rc)
     type(ESMF_State),        intent(inout) :: state
     character(len=*),        intent(in   ) :: exportName
     character(len=*),        intent(in   ) :: exportExpr
     logical,                 intent(in   ) :: masking
     integer, optional,       intent(out  ) :: rc

     integer :: status

     type(ESMF_Field)                   :: field

     if (masking) then
        call MAPL_ExtDataEvaluateMask(state,exportName,exportExpr,_RC)
     else
        call ESMF_StateGet(state,exportName,field,_RC)
        call MAPL_StateEval(state,exportExpr,field,_RC)
     end if
     _RETURN(ESMF_SUCCESS)
  end subroutine CalcDerivedField

  subroutine MAPL_ExtDataInterpField(item,time,field,vector_comp,rc)
     type(PrimaryExport), intent(inout) :: item
     type(ESMF_Time),     intent(in   ) :: time
     type(ESMF_Field),    intent(inout) :: field
     integer, optional,   intent(in   ) :: vector_comp
     integer, optional,   intent(out  ) :: rc

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

     type(ESMF_TimeInterval)    :: tinv1, tinv2
     real                       :: alpha
     real, pointer              :: var2d(:,:)   => null()
     real, pointer              :: var3d(:,:,:) => null()
     real, pointer              :: var2d_prev(:,:)   => null()
     real, pointer              :: var2d_next(:,:)   => null()
     real, pointer              :: var3d_prev(:,:,:) => null()
     real, pointer              :: var3d_next(:,:,:) => null()
     integer                    :: fieldRank,i,j,k
     character(len=ESMF_MAXSTR) :: name

     integer :: yr,mm,dd,hr,mn,sc,nhms1,nymd1,nhms2,nymd2

     Iam = "MAPL_ExtDataInterpField"
     alpha = 0.0
     if (item%doInterpolate) then
        tinv1 = time - item%interp_time1
        tinv2 = item%interp_time2 - item%interp_time1
        alpha = tinv1/tinv2
     end if
     call ESMF_FieldGet(FIELD, dimCount=fieldRank,name=name,_RC)

     if (lgr%isEnabledFor(DEBUG)) then
        call ESMF_TimeGet(item%interp_time1,yy=yr,mm=mm,dd=dd,h=hr,m=mn,s=sc,_RC)
        call MAPL_PackTime(nhms1,hr,mn,sc)
        call MAPL_PackTime(nymd1,yr,mm,dd)
        if (item%doInterpolate) then
           if (alpha .gt. 0.0) then
              call ESMF_TimeGet(item%interp_time2,yy=yr,mm=mm,dd=dd,h=hr,m=mn,s=sc,_RC)
              call MAPL_PackTime(nhms2,hr,mn,sc)
              call MAPL_PackTime(nymd2,yr,mm,dd)
           else
              nhms2=0
              nymd2=0
           end if
        else
           nhms2=0
           nymd2=0
        end if

        if (lgr%isEnabledFor(DEBUG) .and. .not. item%doInterpolate) then
           call lgr%debug('   MAPL_ExtDataInterpField: Uninterpolated field %a set to sample L %i0.8 %i0.6', trim(item%name),  nymd1, nhms1)
        else if (time == item%interp_time1) then
           call lgr%debug('   MAPL_ExtDataInterpField: Interpolated field %a set to sample L %i0.8 %i0.6', trim(item%name),  nymd1, nhms1)
        else if (time == item%interp_time2) then
           call lgr%debug('   MAPL_ExtDataInterpField: Interpolated field %a set to sample R %i0.8 %i0.6', trim(item%name),  nymd2, nhms2)
        else
           call lgr%debug('   MAPL_ExtDataInterpField: Interpolated field %a between %i0.8 %i0.6 and %i0.8 %i0.6 (%f10.6 fraction)', trim(item%name), nymd1, nhms1, nymd2, nhms2, alpha)
        end if
     end if

     call ESMF_FieldGet(FIELD, dimCount=fieldRank,name=name, _RC)
     if (fieldRank == 2) then

        if (item%vartype == MAPL_FieldItem) then
           call ESMF_FieldGet(item%modelGridFields%v1_finterp1, localDE=0, farrayPtr=var2d_prev, _RC)
           call ESMF_FieldGet(item%modelGridFields%v1_finterp2, localDE=0, farrayPtr=var2d_next, _RC)
        else if (item%vartype == MAPL_BundleItem) then
           call ESMFL_BundleGetPointerToData(item%binterp1,name,var2d_prev,_RC)
           call ESMFL_BundleGetPointerToData(item%binterp2,name,var2d_next,_RC)
        else if (item%vartype == MAPL_ExtDataVectorItem) then
           _ASSERT(present(vector_comp),'Vector comp must be present when performing vector interpolation')
           if (vector_comp == 1) then
              call ESMF_FieldGet(item%modelGridFields%v1_finterp1, localDE=0, farrayPtr=var2d_prev, _RC)
              call ESMF_FieldGet(item%modelGridFields%v1_finterp2, localDE=0, farrayPtr=var2d_next, _RC)
           else if (vector_comp == 2) then
              call ESMF_FieldGet(item%modelGridFields%v2_finterp1, localDE=0, farrayPtr=var2d_prev, _RC)
              call ESMF_FieldGet(item%modelGridFields%v2_finterp2, localDE=0, farrayPtr=var2d_next, _RC)
          end if
        end if
        call ESMF_FieldGet(field, localDE=0, farrayPtr=var2d, _RC)
        ! only interpolate if we have to
        if (time == item%interp_time1 .or. item%doInterpolate .eqv. .false.) then
           var2d = var2d_prev
        else if (time == item%interp_time2) then
           var2d = var2d_next
        else
           do j=1,size(var2d,2)
              do i=1,size(var2d,1)
                 if (var2d_next(i,j) /= MAPL_UNDEF .and. var2d_prev(i,j) /= MAPL_UNDEF) then
                     var2d(i,j) = var2d_prev(i,j) + alpha*(var2d_next(i,j)-var2d_prev(i,j))
                 else
                     var2d(i,j) = MAPL_UNDEF
                 end if
              enddo
           enddo
        end if
        do j=1,size(var2d,2)
           do i=1,size(var2d,1)
              if (var2d(i,j) /= MAPL_UNDEF) then
                 if (item%do_scale .and. (.not.item%do_offset)) var2d(i,j) = item%scale*var2d(i,j)
                 if ((.not.item%do_scale) .and. item%do_offset) var2d(i,j) = var2d(i,j)+item%offset
                 if (item%do_scale .and. item%do_offset) var2d(i,j) = item%offset + (item%scale * var2d(i,j))
              else
                  var2d(i,j) = MAPL_UNDEF
              end if
           enddo
        enddo

      else if (fieldRank == 3) then

        if (item%vartype == MAPL_FieldItem) then
           call ESMF_FieldGet(item%modelGridFields%v1_finterp1, localDE=0, farrayPtr=var3d_prev, _RC)
           call ESMF_FieldGet(item%modelGridFields%v1_finterp2, localDE=0, farrayPtr=var3d_next, _RC)
        else if (item%vartype == MAPL_BundleItem) then
           call ESMFL_BundleGetPointerToData(item%binterp1,name,var3d_prev,_RC)
           call ESMFL_BundleGetPointerToData(item%binterp2,name,var3d_next,_RC)
        else if (item%vartype == MAPL_ExtDataVectorItem) then
           _ASSERT(present(vector_comp),'Vector comp must be present when performing vector interpolation')
           if (vector_comp == 1) then
              call ESMF_FieldGet(item%modelGridFields%v1_finterp1, localDE=0, farrayPtr=var3d_prev, _RC)
              call ESMF_FieldGet(item%modelGridFields%v1_finterp2, localDE=0, farrayPtr=var3d_next, _RC)
           else if (vector_comp == 2) then
              call ESMF_FieldGet(item%modelGridFields%v2_finterp1, localDE=0, farrayPtr=var3d_prev, _RC)
              call ESMF_FieldGet(item%modelGridFields%v2_finterp2, localDE=0, farrayPtr=var3d_next, _RC)
           end if
        end if
        call ESMF_FieldGet(field, localDE=0, farrayPtr=var3d, _RC)
        ! only interpolate if we have to
        if (time == item%interp_time1 .or. item%doInterpolate .eqv. .false.) then
           var3d = var3d_prev
        else if (time == item%interp_time2) then
           var3d = var3d_next
        else
           do k=lbound(var3d,3),ubound(var3d,3)
              do j=1,size(var3d,2)
                 do i=1,size(var3d,1)
                    if (var3d_next(i,j,k) /= MAPL_UNDEF .and. var3d_prev(i,j,k) /= MAPL_UNDEF) then
                        var3d(i,j,k) = var3d_prev(i,j,k) + alpha*(var3d_next(i,j,k)-var3d_prev(i,j,k))


                    else
                        var3d(i,j,k) = MAPL_UNDEF
                    end if
                 enddo
              enddo
            enddo
        end if
        do k=lbound(var3d,3),ubound(var3d,3)
           do j=1,size(var3d,2)
              do i=1,size(var3d,1)
                 if (var3d(i,j,k) /= MAPL_UNDEF) then
                    if (item%do_scale .and. (.not.item%do_offset)) var3d(i,j,k) = item%scale*var3d(i,j,k)
                    if ((.not.item%do_scale) .and. item%do_offset) var3d(i,j,k) = var3d(i,j,k)+item%offset
                    if (item%do_scale .and. item%do_offset) var3d(i,j,k) = item%offset + (item%scale * var3d(i,j,k))
                 else
                     var3d(i,j,k) = MAPL_UNDEF
                 end if
              enddo
           enddo
        enddo
     endif

     _RETURN(ESMF_SUCCESS)
  end subroutine MAPL_ExtDataInterpField

  subroutine MAPL_ExtDataVerticalInterpolate(ExtState,item,filec,rc)
     type(MAPL_ExtData_State), intent(inout) :: ExtState
     type(PrimaryExport), intent(inout)     :: item
     integer,             intent(in   )     :: filec
     integer, optional,   intent(out  )     :: rc

     integer :: status
     integer :: id_ps
     type(ESMF_Field) :: field, newfield,psF

     if (item%lm==0) then
        _RETURN(_SUCCESS)
     end if
     if (item%do_VertInterp) then
        if (trim(item%importVDir)/=trim(item%fileVDir)) then
           call MAPL_ExtDataFlipVertical(item,filec,rc=status)
           _VERIFY(status)
        end if
        if (item%vartype == MAPL_fieldItem) then
           call MAPL_ExtDataGetBracket(item,filec,newField,getRL=.true.,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataGetBracket(item,filec,Field,rc=status)
           _VERIFY(STATUS)
           id_ps = ExtState%primaryOrder(1)
           call MAPL_ExtDataGetBracket(ExtState%primary%item(id_ps),filec,field=psF,rc=status)
           _VERIFY(STATUS)
           call vertInterpolation_pressKappa(field,newfield,psF,item%levs,MAPL_UNDEF,rc=status)
           _VERIFY(STATUS)

        else if (item%vartype == MAPL_ExtDataVectorItem) then

           id_ps = ExtState%primaryOrder(1)
           call MAPL_ExtDataGetBracket(ExtState%primary%item(id_ps),filec,field=psF,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataGetBracket(item,filec,newField,getRL=.true.,vcomp=1,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataGetBracket(item,filec,Field,vcomp=1,rc=status)
           _VERIFY(STATUS)
           call vertInterpolation_pressKappa(field,newfield,psF,item%levs,MAPL_UNDEF,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataGetBracket(item,filec,newField,getRL=.true.,vcomp=2,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataGetBracket(item,filec,Field,vcomp=2,rc=status)
           _VERIFY(STATUS)
           call vertInterpolation_pressKappa(field,newfield,psF,item%levs,MAPL_UNDEF,rc=status)
           _VERIFY(STATUS)

        end if

     else if (item%do_Fill) then
        if (item%vartype == MAPL_fieldItem) then
           call MAPL_ExtDataGetBracket(item,filec,newField,getRL=.true.,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataGetBracket(item,filec,Field,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataFillField(item,field,newfield,rc=status)
           _VERIFY(STATUS)
        else if (item%vartype == MAPL_ExtDataVectorItem) then
           call MAPL_ExtDataGetBracket(item,filec,newField,getRL=.true.,vcomp=1,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataGetBracket(item,filec,Field,vcomp=1,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataFillField(item,field,newfield,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataGetBracket(item,filec,newField,getRL=.true.,vcomp=2,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataGetBracket(item,filec,Field,vcomp=2,rc=status)
           _VERIFY(STATUS)
           call MAPL_ExtDataFillField(item,field,newfield,rc=status)
           _VERIFY(STATUS)
        end if
     else
        if (trim(item%importVDir)/=trim(item%fileVDir)) then
           call MAPL_ExtDataFlipVertical(item,filec,rc=status)
           _VERIFY(status)
        end if
     end if

     _RETURN(ESMF_SUCCESS)
  end subroutine MAPL_ExtDataVerticalInterpolate

  subroutine GetMaskName(FuncStr,Var,Needed,rc)
     character(len=*),               intent(in)    :: FuncStr
     character(len=*),               intent(in)    :: Var(:)
     logical,                        intent(inout) :: needed(:)
     integer, optional,              intent(out)   :: rc

     integer                         :: status
     integer                         :: i1,i2,i,ivar
     logical                         :: found,twovar
     character(len=ESMF_MAXSTR)      :: tmpstring,tmpstring1,tmpstring2,functionname

     i1 = index(Funcstr,"(")
     _ASSERT(i1 > 0,'Incorrect format for function expression: missing "("')
     functionname = adjustl(Funcstr(:i1-1))
     functionname = ESMF_UtilStringLowerCase(functionname, _RC)
     if (trim(functionname) == "regionmask") twovar = .true.
     if (trim(functionname) == "zonemask") twovar = .false.
     if (trim(functionname) == "boxmask") twovar = .false.
     tmpstring = adjustl(Funcstr(i1+1:))
     i1 = index(tmpstring,",")
     _ASSERT(i1 > 0,'Incorrect format for function expression: missing ","')
     i2 = index(tmpstring,";")
     if (twovar) then
        tmpstring1 = adjustl(tmpstring(1:i1-1))
        tmpstring2 = adjustl(tmpstring(i1+1:i2-1))
     else
        tmpstring1 = adjustl(tmpstring(1:i1-1))
     end if

     found = .false.
     do i=1,size(var)
        if ( trim(tmpstring1) == trim(var(i)) ) then
           ivar = i
           found = .true.
           exit
        end if
     end do
     _ASSERT(found,'Var ' // trim(tmpstring1) // ' not found')
     needed(ivar) = .true.

     if (twovar) then
        found = .false.
        do i=1,size(var)
           if ( trim(tmpstring2) == trim(var(i)) ) then
              ivar = i
              found = .true.
              exit
           end if
        end do
        _ASSERT(found,'Secound Var ' // trim(tmpstring2) // ' not found')
        needed(ivar) = .true.
     end if
     _RETURN(ESMF_SUCCESS)
  end subroutine GetMaskName

  subroutine MAPL_ExtDataEvaluateMask(state,exportName,exportExpr,rc)

    type(ESMF_STATE),           intent(inout) :: state
    character(len=*),           intent(in)    :: exportName
    character(len=*),           intent(in)    :: exportExpr
    integer, optional,          intent(out)   :: rc

    integer :: status

    integer :: k,i
    character(len=ESMF_MAXSTR) :: maskString,maskname,vartomask,functionname,clatS,clatN
    character(len=ESMF_MAXSTR) :: strtmp
    integer, allocatable :: regionNumbers(:), flag(:)
    integer, allocatable :: mask(:,:)
    real, pointer        :: rmask(:,:)    => null()
    real, pointer        :: rvar2d(:,:)   => null()
    real, pointer        :: rvar3d(:,:,:) => null()
    real, pointer        :: var2d(:,:)    => null()
    real, pointer        :: var3d(:,:,:)  => null()
    real(REAL64), pointer :: lats(:,:)     => null()
    real(REAL64), pointer :: lons(:,:)     => null()
    real(REAL64)         :: limitS, limitN, limitE, limitW
    real(REAL64)         :: limitE1, limitW1
    real(REAL64)         :: limitE2, limitW2
    type(ESMF_Field)     :: field
    type(ESMF_Grid)      :: grid
    integer              :: rank,ib,ie,is,i1,nargs
    integer              :: counts(3)
    logical              :: isCube, twoBox
    real, allocatable    :: temp2d(:,:)
    character(len=ESMF_MAXSTR) :: args(5)

    call ESMF_StateGet(state,exportName,field,_RC)
    call ESMF_FieldGet(field,rank=rank,grid=grid,_RC)
    i1 = index(exportExpr,"(")
    _ASSERT(i1 > 0,'Expected "(" in expression: ' // trim(exportExpr))
    functionname = adjustl(exportExpr(:i1-1))
    functionname = ESMF_UtilStringLowerCase(functionname, _RC)

    if (trim(functionname) == "regionmask") then
       ! get mask string
       ib = index(exportExpr,";")
       ie = index(exportExpr,")")
       maskString = trim(exportExpr(ib+1:ie-1))
       ! get mask name
       ie = index(exportExpr,";")
       is = index(exportExpr,"(")
       ib = index(exportExpr,",")
       vartomask = trim(exportExpr(is+1:ib-1))
       maskname = trim(exportExpr(ib+1:ie-1))
       call MAPL_GetPointer(state,rmask,maskName,_RC)
       if (rank == 2) then
          call MAPL_GetPointer(state,rvar2d,vartomask,_RC)
          call MAPL_GetPointer(state,var2d,exportName,_RC)
       else if (rank == 3) then
          call MAPL_GetPointer(state,rvar3d,vartomask,_RC)
          call MAPL_GetPointer(state,var3d,exportName,_RC)
       else
          _FAIL('Rank must be 2 or 3')
       end if

       k=32
       allocate(regionNumbers(k), flag(k), stat=status)
       _VERIFY(STATUS)
       regionNumbers = 0
       call MAPL_ExtDataExtractIntegers(maskString,k,regionNumbers,rc=status)
       _VERIFY(STATUS)
       flag(:) = 1
       WHERE(regionNumbers(:) == 0) flag(:) = 0
       k = SUM(flag)
       deallocate(flag,stat=status)
       _VERIFY(STATUS)

   !   Set local mask to 1 where gridMask matches each integer (within precision!)
   !   ---------------------------------------------------------------------------
       allocate(mask(size(rmask,1),size(rmask,2)),stat=status)
       _VERIFY(STATUS)
       mask = 0
       DO i=1,k
        WHERE(regionNumbers(i)-0.01 <= rmask .AND. &
              rmask <= regionNumbers(i)+0.01) mask = 1
       END DO

       if (rank == 2) then
          var2d = rvar2d
          where(mask == 0) var2d = 0.0
       else if (rank == 3) then
          var3d = rvar3d
          do i=1,size(var3d,3)
             where(mask == 0) var3d(:,:,i) = 0.0
          enddo
       end if
       deallocate( mask)
    elseif(trim(functionname) == "zonemask") then

       ib = index(exportExpr,"(")
       ie = index(exportExpr,",")
       vartomask = trim(exportExpr(ib+1:ie-1))
       ib = index(exportExpr,",")
       is = index(exportExpr,",",back=.true.)
       ie = index(exportExpr,")")
       clatS = trim(exportExpr(ib+1:is-1))
       clatN = trim(exportExpr(is+1:ie-1))
       READ(clatS,*,IOSTAT=status) limitS
       _VERIFY(status)
       READ(clatN,*,IOSTAT=status) limitN
       _VERIFY(status)

       call ESMF_GridGetCoord(grid, coordDim=2, localDE=0, &
            staggerloc=ESMF_STAGGERLOC_CENTER, farrayPtr=lats, rc=status)
       _VERIFY(status)
       limitN=limitN*MAPL_PI_R8/180.0d0
       limitS=limitS*MAPL_PI_R8/180.0d0

       if (rank == 2) then
          call MAPL_GetPointer(state,rvar2d,vartomask,_RC)
          call MAPL_GetPointer(state,var2d,exportName,_RC)
       else if (rank == 3) then
          call MAPL_GetPointer(state,rvar3d,vartomask,_RC)
          call MAPL_GetPointer(state,var3d,exportName,_RC)
       else
          _FAIL('Rank must be 2 or 3')
       end if

       if (rank == 2) then
          var2d = 0.0
          where(limitS <= lats .and. lats <=limitN) var2d = rvar2d
       else if (rank == 3) then
          var3d = 0.0
          do i=1,size(var3d,3)
             where(limitS <= lats .and. lats <=limitN) var3d(:,:,i) = rvar3d(:,:,i)
          enddo
       end if

    elseif(trim(functionname) == "boxmask") then
       is=index(exportExpr,'(')
       ie=index(exportExpr,')')
       strtmp = exportExpr(is+1:ie-1)
       do nargs=1,5
          is = index(strtmp,',')
          if (is >0) then
             args(nargs) = strtmp(:is-1)
          else
             args(nargs) = strtmp
          end if
          strtmp = strtmp(is+1:)
       end do

       varToMask=args(1)

       READ(args(2),*,IOSTAT=status) limitS
       _VERIFY(status)
       READ(args(3),*,IOSTAT=status) limitN
       _VERIFY(status)
       READ(args(4),*,IOSTAT=status) limitW
       _VERIFY(status)
       READ(args(5),*,IOSTAT=status) limitE
       _VERIFY(status)
       _ASSERT(limitE > limitW,'LimitE must be greater than limitW')
       _ASSERT(limitE /= limitW,'LimitE cannot equal limitW')
       _ASSERT(limitN /= limitS,'LimitN cannot equal LimitS')
       _ASSERT((limitE-limitW)<=360.0d0,'(LimitE - LimitW) must be less than or equal to 360')

       call ESMF_GridGetCoord(grid, coordDim=1, localDE=0, &
            staggerloc=ESMF_STAGGERLOC_CENTER, farrayPtr=lons, rc=status)
       _VERIFY(status)
       call ESMF_GridGetCoord(grid, coordDim=2, localDE=0, &
            staggerloc=ESMF_STAGGERLOC_CENTER, farrayPtr=lats, rc=status)
       _VERIFY(status)

       ! do some tests if cube goes from 0 to 360, lat-lon -180 to 180
       call MAPL_GridGet(grid, globalCellCountPerDim=COUNTS,rc=status)
       _VERIFY(STATUS)
       if (counts(2)==6*counts(1)) then
          isCube=.true.
       else
          isCube=.false.
       end if

       twoBox = .false.
       if (isCube) then
          if (limitW < 0.0d0 .and. limitE >=0.0d0) then
             ! need two boxes
             twoBox=.true.
             limitW1=0.0d0
             limitE1=limitE
             limitW2=limitW+360.0d0
             limitE2=360.0d0

          else if (limitW <0.0d0 .and. limitE <0.0d0) then
             ! just shift
             limitW1=limitW+360.d0
             limitE1=limitE+360.d0

          else
             ! normal case
             limitW1=limitW
             limitE1=limitE
          end if

       else

          if (limitW  <= 180.0d0 .and. limitE > 180.0d0) then
             ! need two boxes
             twoBox=.true.
             limitW1=limitW
             limitE1=180.0d0
             limitW2=-180.d0
             limitE2=limitE-360.0d0
          else if (limitW > 180.0d0 .and. limitE > 180.0d0) then
             ! just shift
             limitW1=limitW-360.d0
             limitE1=limitE-360.d0
          else
             ! normal case
             limitW1=limitW
             limitE1=limitE
          end if

       end if

       limitE1=limitE1*MAPL_PI_R8/180.0d0
       limitW1=limitW1*MAPL_PI_R8/180.0d0
       limitE2=limitE2*MAPL_PI_R8/180.0d0
       limitW2=limitW2*MAPL_PI_R8/180.0d0

       limitN=limitN*MAPL_PI_R8/180.0d0
       limitS=limitS*MAPL_PI_R8/180.0d0
       if (rank == 2) then
          call MAPL_GetPointer(state,rvar2d,vartomask,_RC)
          call MAPL_GetPointer(state,var2d,exportName,_RC)
       else if (rank == 3) then
          call MAPL_GetPointer(state,rvar3d,vartomask,_RC)
          call MAPL_GetPointer(state,var3d,exportName,_RC)
       else
          _FAIL('Rank must be 2 or 3')
       end if

       if (rank == 2) then
          var2d = 0.0
          where(limitS <= lats .and. lats <=limitN .and. limitW1 <= lons .and. lons <= limitE1 ) var2d = rvar2d
       else if (rank == 3) then
          var3d = 0.0
          do i=1,size(var3d,3)
             where(limitS <= lats .and. lats <=limitN .and. limitW1 <= lons .and. lons <= limitE1 ) var3d(:,:,i) = rvar3d(:,:,i)
          enddo
       end if

       if (twoBox) then
          allocate(temp2d(size(var2d,1),size(var2d,2)),stat=status)
          _VERIFY(STATUS)
          if (rank == 2) then
             temp2d = 0.0
             where(limitS <= lats .and. lats <=limitN .and. limitW2 <= lons .and. lons <= limitE2 ) temp2d = rvar2d
             var2d=var2d+temp2d
          else if (rank == 3) then
             do i=1,size(var3d,3)
                temp2d = 0.0
                where(limitS <= lats .and. lats <=limitN .and. limitW2 <= lons .and. lons <= limitE2 ) temp2d = rvar3d(:,:,i)
                var3d(:,:,i)=var3d(:,:,i)+temp2d
             enddo
          end if
          deallocate(temp2d)
       end if

    end if

    _RETURN(ESMF_SUCCESS)

  end subroutine MAPL_ExtDataEvaluateMask

!----------------------------------------------------------------------------------
!>
! The routine `MAPL_ExtDataExtractIntegers`
! extracts integers from a character-delimited string, for example, "-1,45,256,7,10".  In the context
! of Chem_Util, this is provided for determining the numerically indexed regions over which an
! emission might be applied.
!
! In multiple passes, the string is parsed for the delimiter, and the characters up to, but not
! including the delimiter are taken as consecutive digits of an integer.  A negative sign ("-") is
! allowed.  After the first pass, each integer and its trailing delimiter are lopped of the head of
! the (local copy of the) string, and the process is started over.
!
! The default delimiter is a comma (",").
!
! "Unfilled" iValues are zero.
!
! Return codes:
!- 1 Zero-length string.
!- 2 iSize needs to be increased.
!
! @bug
!-The routine works under the following assumptions:
!- A non-zero return code does not stop execution.
!- Allowed numerals are: 0,1,2,3,4,5,6,7,8,9.
!- A delimiter must be separated from another delimiter by at least one numeral.
!- The delimiter cannot be a numeral or a negative sign.
!- The character following a negative sign must be an allowed numeral.
!- The first character must be an allowed numeral or a negative sign.
!- The last character must be an allowed numeral.
!- The blank character (" ") cannot serve as a delimiter.
!@endbug
!
! Examples of strings that will work:
!```
!  "1"
!  "-1"
!  "-1,2004,-3"
!  "1+-2+3"
!  "-1A100A5"
!```
!
! Examples of strings that will not work:
!```
!  "1,--2,3"
!  "1,,2,3"
!  "1,A,3"
!  "1,-,2"
!  "1,2,3,4,"
!  "+1"
!  "1 3 6"
!```
!
!#### History
!- Taken from chem utilities.
!
  SUBROUTINE MAPL_ExtDataExtractIntegers(string,iSize,iValues,delimiter,verbose,rc)

! !USES:

  IMPLICIT NONE

! !INPUT/OUTPUT PARAMETERS:

  CHARACTER(LEN=*), INTENT(IN)   :: string     !! Character-delimited string of integers
  INTEGER, INTENT(IN)            :: iSize
  INTEGER, INTENT(INOUT)         :: iValues(iSize) !! Space allocated for extracted integers
  CHARACTER(LEN=*), OPTIONAL     :: delimiter      !! 1-character delimiter
  LOGICAL, OPTIONAL, INTENT(IN)  :: verbose    !! Let me know iValues as they are found.
                                      !! DEBUG directive turns on the message even
                                      !! if verbose is not present or if
                                      !! verbose = .FALSE.
  INTEGER, OPTIONAL, INTENT(OUT) :: rc            !! Return code

!
 CHARACTER(LEN=*), PARAMETER :: Iam = 'Chem_UtilExtractIntegers'

 INTEGER :: base,count,i,iDash,last,lenStr
 INTEGER :: multiplier,pos,posDelim,sign
 CHARACTER(LEN=255) :: str
 CHARACTER(LEN=1) :: char,delimChar
 LOGICAL :: Done
 LOGICAL :: tellMe

! Initializations
! ---------------
 If (present(rc))  rc=0
 count = 1
 Done = .FALSE.
 iValues(:) = 0
 base = ICHAR("0")
 iDash = ICHAR("-")

! Determine verbosity, letting the DEBUG
! directive override local specification
! --------------------------------------
  tellMe = .FALSE.
  IF(PRESENT(verbose)) THEN
   IF(verbose) tellMe = .TRUE.
 END IF
#ifdef DEBUG
  tellMe = .TRUE.
#endif
! Check for zero-length string
! ----------------------------
 lenStr = LEN_TRIM(string)
 IF(lenStr == 0) THEN
    if (present(rc))  rc=1
    call lgr%error('Found zero length string at line %i0',__LINE__)
  RETURN
 END IF

! Default delimiter is a comma
! ----------------------------
 delimChar = ","
 IF(PRESENT(delimiter)) delimChar(1:1) = delimiter(1:1)

! Work on a local copy
! --------------------
 str = TRIM(string)

! One pass for each delimited integer
! -----------------------------------
 Parse: DO

  lenStr = LEN_TRIM(str)

! Parse the string for the delimiter
! ----------------------------------
  posDelim = INDEX(TRIM(str),TRIM(delimChar))
  if(tellMe) then
     call lgr%info('%a~: Input string is >%a<',trim(Iam), trim(string))
  end if

! If the delimiter does not exist,
! one integer remains to be extracted.
! ------------------------------------
  IF(posDelim == 0) THEN
   Done = .TRUE.
   last = lenStr
  ELSE
   last = posDelim-1
  END IF
  multiplier = 10**last

! Examine the characters of this integer
! --------------------------------------
  Extract: DO pos=1,last

   char = str(pos:pos)
   i = ICHAR(char)

! Account for a leading "-"
! -------------------------
   IF(pos == 1) THEN
    IF(i == iDash) THEN
     sign = -1
    ELSE
     sign = 1
    END IF
   END IF

! "Power" of 10 for this character
! --------------------------------
   multiplier = multiplier/10

   IF(pos == 1 .AND. sign == -1) CYCLE Extract

! Integer comes from remaining characters
! ---------------------------------------
   i = (i-base)*multiplier
   iValues(count) = iValues(count)+i
   IF(pos == last) THEN
    iValues(count) = iValues(count)*sign
    if(tellMe) then
       call lgr%info('%a~:Integer number %i0 is %i0', trim(iAm), count, iValues(count))
    end if
   END IF

  END DO Extract

  IF(Done) EXIT

! Lop off the leading integer and try again
! -----------------------------------------
  str(1:lenStr-posDelim) = str(posDelim+1:lenStr)
  str(lenStr-posDelim+1:255) = " "
  count = count+1

! Check size
! ----------
  IF(count > iSize) THEN
     if (present(rc))  rc=2
     call lgr%error('%a~: - iValues does not have enough elements.')
  END IF

 END DO Parse

 _RETURN(ESMF_SUCCESS)

 END SUBROUTINE MAPL_ExtDataExtractIntegers

  function MAPL_ExtDataGetFStartTime(item,fname, rc) result(stime)

     type(PrimaryExport), intent(in) :: item
     character(len=*), intent(in   ) :: fname
     integer, optional, intent(out  ) :: rc

     type(ESMF_Time) :: stime

     integer                               :: status

     integer :: iyr,imm,idd,ihr,imn,isc
     type(FileMetadataUtils), pointer :: metadata => null()

     call MakeMetadata(fname,item%pfiocollection_id,metadata,_RC)
     call Metadata%get_time_info(startyear=iyr,startmonth=imm,startday=idd,starthour=ihr,startmin=imn,startsec=isc,rc=status)
     _VERIFY(status)
     call ESMF_TimeSet(sTime, yy=iyr, mm=imm, dd=idd,  h=ihr,  m=imn, s=isc, _RC)
     nullify(metadata)

     _RETURN(ESMF_SUCCESS)

  end function MAPL_ExtDataGetFStartTime

  subroutine AdvanceAndCount(CF,nLines,rc)

     type(ESMF_Config), intent(inout) :: cf
     integer, intent(out)             :: nLines
     integer, optional, intent(out)   :: rc

     integer :: iCnt
     logical :: inBlock
     character(len=ESMF_MAXPATHLEN) :: thisLine
     integer :: status
     character(len=ESMF_MAXSTR) :: Iam
     Iam = "AdvanceAndCount"

     inBlock = .true.
     iCnt = 0
     do while(inBlock)
         call ESMF_ConfigNextLine(CF,rc=status)
         _VERIFY(STATUS)
         call ESMF_ConfigGetAttribute(CF,thisLine,rc=status)
         _VERIFY(STATUS)
         if (trim(thisLine) == "%%") then
            inBlock = .false.
         else
            iCnt = iCnt + 1
         end if
     end do
     nLines = iCnt

     _RETURN(ESMF_SUCCESS)

  end subroutine advanceAndCount

  subroutine CheckUpdate(doUpdate,updateTime,currTime,hasRun,primaryItem,derivedItem,rc)
     logical,                       intent(out  ) :: doUpdate
     type(ESMF_Time),               intent(inout) :: updateTime
     type(ESMF_Time),               intent(inout) :: currTime
     logical        ,               intent(in   ) :: hasRun
     type(PrimaryExport), optional, intent(inout) :: primaryItem
     type(DerivedExport), optional, intent(inout) :: derivedItem
     integer,             optional, intent(out  ) :: rc

     character(len=ESMF_MAXSTR) :: Iam
     integer                    :: status
     type(ESMF_Time)            :: time,time0,refresh_time
     Iam = "CheckUpdate"

     time0 = currTime
     time  = currTime
     if (present(primaryItem)) then

        if (primaryItem%AlarmIsEnabled) then
           doUpdate = primaryItem%update_alarm%is_ringing(currTime,_RC)
           if (hasRun .eqv. .false.) doUpdate = .true.
           updateTime = currTime
        else if (trim(primaryItem%cyclic) == 'single') then
           doUpdate = .true.
        else
           if (primaryItem%refresh_template == "0") then
              doUpdate = .true.
              updateTime = time0 + PrimaryItem%tshift
           else
              updateTime = time0
              if (.not. associated(PrimaryItem%refresh_time)) then
                doUpdate = .false.
              else
                 refresh_time = timestamp_(time, PrimaryItem%refresh_template, _RC)
                 if (refresh_time /= primaryItem%refresh_time) then
                    doUpdate = .true.
                    primaryItem%refresh_time = refresh_time
                    updateTime = refresh_time
                 else
                    doUpdate = .false.
                 end if
              end if
           end if
        end if
     else if (present(derivedItem)) then
        if (DerivedItem%AlarmIsEnabled) then
           doUpdate = derivedItem%update_alarm%is_ringing(currTime,_RC)
           updateTime = currTime
        else
           if (derivedItem%refresh_template == "0") then
              doUpdate = .true.
              updateTime = time0 + derivedItem%tshift
           else
              updateTime = time0
              if (.not. associated(derivedItem%refresh_time)) then
                doUpdate = .false.
              else
                 refresh_time = timestamp_(time, derivedItem%refresh_template, _RC)
                 if (refresh_time /= derivedItem%refresh_time) then
                    doUpdate = .true.
                    derivedItem%refresh_time = refresh_time
                    time = refresh_time
                 else
                    doUpdate = .false.
                 end if
              end if
           end if
        end if
     end if

     _RETURN(ESMF_SUCCESS)
  end subroutine CheckUpdate

  subroutine SetRefreshAlarms(clock,primaryItem,derivedItem,rc)
     type(ESMF_Clock),              intent(inout) :: Clock
     type(PrimaryExport), optional, intent(inout) :: primaryItem
     type(DerivedExport), optional, intent(inout) :: derivedItem
     integer,             optional, intent(out  ) :: rc

     integer                    :: pindex,cindex,iyy,imm,idd,ihh,imn,isc
     character(len=ESMF_MAXSTR) :: refresh_template,ctInt
     character(len=ESMF_MAXSTR) :: Iam
     type(ESMF_TimeInterval)    :: tInterval
     type(ESMF_Time)            :: current_time
     integer                    :: status
     Iam = "SetRefreshAlarms"

     if (present(primaryItem)) then
        refresh_template = primaryItem%refresh_template
     else if (present(derivedItem)) then
        refresh_template = derivedItem%refresh_template
     end if
     pindex = index(refresh_template,'P')
     if (pindex > 0) then
        call ESMF_ClockGet(Clock,currTime=current_time,rc=status)
        _VERIFY(status)
        ! now get time interval. Put 0000-00-00 in front if not there so parsetimeunits doesn't complain
        ctInt = refresh_template(pindex+1:)
        cindex = index(ctInt,'T')
        if (cindex == 0) ctInt = '0000-00-00T'//trim(ctInt)
        call MAPL_NCIOParseTimeUnits(ctInt,iyy,imm,idd,ihh,imn,isc,status)
        _VERIFY(STATUS)
        call ESMF_TimeIntervalSet(tInterval,yy=iyy,mm=imm,d=idd,h=ihh,m=imn,s=isc,rc=status)
        _VERIFY(STATUS)
        if (present(primaryItem)) then
           primaryItem%update_alarm = simpleAlarm(current_time,tInterval,rc=status)
           _VERIFY(status)
           primaryItem%alarmIsEnabled = .true.
        else if (present(derivedItem)) then
           DerivedItem%update_alarm = simpleAlarm(current_time,tInterval,rc=status)
           _VERIFY(status)
           derivedItem%alarmIsEnabled = .true.
        end if
     end if

     _RETURN(ESMF_SUCCESS)
  end subroutine SetRefreshAlarms

  function MAPL_ExtDataGridChangeLev(Grid,CF,lm,rc) result(NewGrid)

     type(ESMF_Grid), intent(inout) :: Grid
     type(ESMF_Config), intent(inout) :: CF
     integer,         intent(in)    :: lm
     integer, optional, intent(out) :: rc

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

     character(len=ESMF_MAXSTR) :: gname, comp_name
     integer :: counts(3)
     integer :: NX,NY
     type(ESMF_Grid)           :: newGrid
     type(ESMF_Config)         :: cflocal
     real :: temp_real
     logical :: isPresent

     IAM = "MAPL_ExtDataGridChangeLev"

     call MAPL_GridGet(grid,globalCellCountPerDim=counts,_RC)
     call ESMF_GridGet(grid,name=gName,_RC)
     call ESMF_ConfigGetAttribute(CF, value = NX, Label="NX:", _RC)
     call ESMF_ConfigGetAttribute(CF, value = NY, Label="NY:", _RC)

     comp_name = "ExtData"
     cflocal = MAPL_ConfigCreate(rc=status)
     _VERIFY(status)
     call MAPL_ConfigSetAttribute(cflocal,value=NX, label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"NX:",rc=status)
     _VERIFY(status)
     call MAPL_ConfigSetAttribute(cflocal,value=lm, label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"LM:",rc=status)
     _VERIFY(status)

     if (counts(2) == 6*counts(1)) then
        call MAPL_ConfigSetAttribute(cflocal,value="Cubed-Sphere", label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"GRID_TYPE:",rc=status)
        _VERIFY(status)
        call MAPL_ConfigSetAttribute(cflocal,value=6, label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"NF:",rc=status)
        _VERIFY(status)
        call MAPL_ConfigSetAttribute(cflocal,value=counts(1), label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"IM_WORLD:",rc=status)
        _VERIFY(status)
        call MAPL_ConfigSetAttribute(cflocal,value=ny/6, label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"NY:",rc=status)
        _VERIFY(status)
        call MAPL_ConfigSetAttribute(cflocal,value=trim(gname), label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"GRIDNAME:",rc=status)
        _VERIFY(status)

        call ESMF_AttributeGet(grid, name='STRETCH_FACTOR', isPresent=isPresent, rc=status)
        _VERIFY(status)
        if (isPresent) then
           call ESMF_AttributeGet(grid, name='STRETCH_FACTOR', value=temp_real, rc=status)
           _VERIFY(status)
           call MAPL_ConfigSetAttribute(cflocal,value=temp_real, label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"STRETCH_FACTOR:",rc=status)
           _VERIFY(status)
        endif

        call ESMF_AttributeGet(grid, name='TARGET_LON', isPresent=isPresent, rc=status)
        _VERIFY(status)
        if (isPresent) then
           call ESMF_AttributeGet(grid, name='TARGET_LON', value=temp_real, rc=status)
           _VERIFY(status)
           call MAPL_ConfigSetAttribute(cflocal,value=temp_real*MAPL_RADIANS_TO_DEGREES, label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"TARGET_LON:",rc=status)
           _VERIFY(status)
        endif

        call ESMF_AttributeGet(grid, name='TARGET_LAT', isPresent=isPresent, rc=status)
        _VERIFY(status)
        if (isPresent) then
           call ESMF_AttributeGet(grid, name='TARGET_LAT', value=temp_real, rc=status)
           _VERIFY(status)
           call MAPL_ConfigSetAttribute(cflocal,value=temp_real*MAPL_RADIANS_TO_DEGREES, label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"TARGET_LAT:",rc=status)
           _VERIFY(status)
        endif
     else
        call MAPL_ConfigSetAttribute(cflocal,value=counts(1), label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"IM_WORLD:",rc=status)
        _VERIFY(status)
        call MAPL_ConfigSetAttribute(cflocal,value=counts(2), label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"JM_WORLD:",rc=status)
        _VERIFY(status)
        call MAPL_ConfigSetAttribute(cflocal,value=ny, label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"NY:",rc=status)
        _VERIFY(status)
        call MAPL_ConfigSetAttribute(cflocal,value=trim(gname), label=trim(COMP_Name)//MAPL_CF_COMPONENT_SEPARATOR//"GRIDNAME:",rc=status)
        _VERIFY(status)
     end if
     newgrid = grid_manager%make_grid(cflocal, prefix=trim(COMP_Name)//".", rc=status)
     _VERIFY(status)

     _RETURN(ESMF_SUCCESS)

  end function MAPL_ExtDataGridChangeLev

  subroutine MAPL_ExtDataGetBracket(item,Bside,field,bundle,getRL,vcomp,rc)

     type(PrimaryExport),              intent(inout) :: item
     integer,                          intent(in   ) :: bside
     type(ESMF_Field),       optional, intent(inout) :: field
     type(ESMF_FieldBundle), optional, intent(inout) :: bundle
     logical,                optional, intent(in   ) :: getRL
     integer,                optional, intent(in   ) :: vcomp
     integer,                optional, intent(out  ) :: rc

     character(len=ESMF_MAXSTR) :: Iam

     logical :: getRL_

     Iam = "MAPL_ExtDataGetBracket"

     if (present(getRL)) then
        getRL_=getRL
     else
        getRL_=.false.
     end if

     if (present(vcomp)) then

        if (present(field)) then

           if (Bside == MAPL_ExtDataLeft .and. vcomp == 1) then
              if (getRL_) then
                 field = item%modelGridFields%v1_faux1
                 _RETURN(ESMF_SUCCESS)
              else
                 field = item%modelGridFields%v1_finterp1
                 _RETURN(ESMF_SUCCESS)
              end if
           else if (Bside == MAPL_ExtDataLeft .and. vcomp == 2) then
              if (getRL_) then
                 field = item%modelGridFields%v2_faux1
                 _RETURN(ESMF_SUCCESS)
              else
                 field = item%modelGridFields%v2_finterp1
                 _RETURN(ESMF_SUCCESS)
              end if
           else if (Bside == MAPL_ExtDataRight .and. vcomp == 1) then
              if (getRL_) then
                 field = item%modelGridFields%v1_faux2
                 _RETURN(ESMF_SUCCESS)
              else
                 field = item%modelGridFields%v1_finterp2
                 _RETURN(ESMF_SUCCESS)
              end if
           else if (Bside == MAPL_ExtDataRight .and. vcomp == 2) then
              if (getRL_) then
                 field = item%modelGridFields%v2_faux2
                 _RETURN(ESMF_SUCCESS)
              else
                 field = item%modelGridFields%v2_finterp2
                 _RETURN(ESMF_SUCCESS)
              end if

           end if

        else if (present(bundle)) then
           _RETURN(ESMF_FAILURE)
        end if

     else

        if (present(field)) then
           if (Bside == MAPL_ExtDataLeft) then
              if (getRL_) then
                 field = item%modelGridFields%v1_faux1
                 _RETURN(ESMF_SUCCESS)
              else
                 field = item%modelGridFields%v1_finterp1
                 _RETURN(ESMF_SUCCESS)
              end if
           else if (Bside == MAPL_ExtDataRight) then
              if (getRL_) then
                 field = item%modelGridFields%v1_faux2
                 _RETURN(ESMF_SUCCESS)
              else
                 field = item%modelGridFields%v1_finterp2
                 _RETURN(ESMF_SUCCESS)
              end if
           end if
        else if (present(bundle)) then
           if (Bside == MAPL_ExtDataLeft) then
              bundle = item%binterp1
              _RETURN(ESMF_SUCCESS)
           else if (Bside == MAPL_ExtDataRight) then
              bundle = item%binterp2
              _RETURN(ESMF_SUCCESS)
           end if

        end if

     end if
     _RETURN(ESMF_FAILURE)

  end subroutine MAPL_ExtDataGetBracket

  subroutine MAPL_ExtDataFillField(item,FieldF,FieldR,rc)

  type(PrimaryExport), intent(inout) :: item
  type(ESMF_Field), intent(inout) :: FieldF
  type(ESMF_Field), intent(inout) :: FieldR
  integer, optional, intent(out)  :: rc

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

  real, pointer :: ptrF(:,:,:),ptrR(:,:,:)
  integer :: lm_in,lm_out,i

  Iam = "MAPL_ExtDataFillField"

  call ESMF_FieldGet(FieldF,0,farrayPtr=ptrF,rc=status)
  _VERIFY(STATUS)
  call ESMF_FieldGet(FieldR,0,farrayPtr=ptrR,rc=status)
  _VERIFY(STATUS)
  ptrF = 0.0
  lm_in= size(ptrR,3)
  lm_out = size(ptrF,3)
  if (trim(item%importVDir)=="down") then

     if (trim(item%fileVDir)=="down") then
        do i=1,lm_in
           ptrF(:,:,lm_out-lm_in+i)=ptrR(:,:,i)
        enddo
     else if (trim(item%fileVDir)=="up") then
        do i=1,lm_in
           ptrF(:,:,lm_out-i+1)=ptrR(:,:,i)
        enddo
     end if
  else if (trim(item%importVDir)=="up") then
     if (trim(item%fileVDir)=="down") then
        do i=1,lm_in
           ptrF(:,:,lm_in-i+1)=ptrR(:,:,i)
        enddo
     else if (trim(item%fileVDir)=="up") then
        do i=1,lm_in
           ptrF(:,:,i)=ptrR(:,:,i)
        enddo
     end if
  end if

  _RETURN(ESMF_SUCCESS)

  end subroutine MAPL_ExtDataFillField

  subroutine MAPL_ExtDataFlipVertical(item,filec,rc)
      type(PrimaryExport), intent(inout)      :: item
      integer,                  intent(in)    :: filec
      integer, optional, intent(out)          :: rc

      integer :: status

      type(ESMF_Field) :: Field,field1,field2
      real, pointer    :: ptr(:,:,:)
      real, allocatable :: ptemp(:,:,:)
      integer :: ls, le

      if (item%isVector) then

         if (item%do_Fill .or. item%do_VertInterp) then
            call MAPL_ExtDataGetBracket(item,filec,field=Field1,vcomp=1,getRL=.true.,_RC)
            call MAPL_ExtDataGetBracket(item,filec,field=Field2,vcomp=2,getRL=.true.,_RC)
         else
            call MAPL_ExtDataGetBracket(item,filec,field=Field1,vcomp=1,_RC)
            call MAPL_ExtDataGetBracket(item,filec,field=Field2,vcomp=2,_RC)
         end if

         call ESMF_FieldGet(Field1,0,farrayPtr=ptr,rc=status)
         _VERIFY(STATUS)
         allocate(ptemp,source=ptr,stat=status)
         _VERIFY(status)
         ls = lbound(ptr,3)
         le = ubound(ptr,3)
         ptr(:,:,le:ls:-1) = ptemp(:,:,ls:le:+1)

         call ESMF_FieldGet(Field2,0,farrayPtr=ptr,rc=status)
         _VERIFY(STATUS)
         ptemp=ptr
         ptr(:,:,le:ls:-1) = ptemp(:,:,ls:le:+1)

         deallocate(ptemp)

      else

         if (item%do_Fill .or. item%do_VertInterp) then
            call MAPL_ExtDataGetBracket(item,filec,field=Field,getRL=.true.,_RC)
         else
            call MAPL_ExtDataGetBracket(item,filec,field=Field,_RC)
         end if

         call ESMF_FieldGet(Field,0,farrayPtr=ptr,rc=status)
         _VERIFY(STATUS)
         allocate(ptemp,source=ptr,stat=status)
         _VERIFY(status)
         ls = lbound(ptr,3)
         le = ubound(ptr,3)
         ptr(:,:,le:ls:-1) = ptemp(:,:,ls:le:+1)
         deallocate(ptemp)
      end if

      _RETURN(ESMF_SUCCESS)

  end subroutine MAPL_ExtDataFlipVertical
  subroutine MAPL_ExtDataPopulateBundle(item,filec,pbundle,rc)
      type(PrimaryExport), intent(inout)      :: item
      integer,                  intent(in)    :: filec
      type(ESMF_FieldBundle), intent(inout)   :: pbundle
      integer, optional, intent(out)          :: rc

      integer :: status

      type(ESMF_Field) :: Field,field1,field2
      type(ESMF_Grid)  :: grid

      if (item%isVector) then

         if (item%do_Fill .or. item%do_VertInterp) then
            call MAPL_ExtDataGetBracket(item,filec,field=Field1,vcomp=1,getRL=.true.,_RC)
            call MAPL_ExtDataGetBracket(item,filec,field=Field2,vcomp=2,getRL=.true.,_RC)
         else
            call MAPL_ExtDataGetBracket(item,filec,field=Field1,vcomp=1,_RC)
            call MAPL_ExtDataGetBracket(item,filec,field=Field2,vcomp=2,_RC)
         end if

         call ESMF_FieldGet(Field1,grid=grid,rc=status)
         _VERIFY(STATUS)
         call ESMF_FieldBundleSet(pbundle,grid=grid,rc=status)
         _VERIFY(STATUS)
         call MAPL_FieldBundleAdd(pbundle,Field1,rc=status)
         _VERIFY(STATUS)
         call MAPL_FieldBundleAdd(pbundle,Field2,rc=status)
         _VERIFY(STATUS)

      else

         if (item%do_Fill .or. item%do_VertInterp) then
            call MAPL_ExtDataGetBracket(item,filec,field=Field,getRL=.true.,_RC)
         else
            call MAPL_ExtDataGetBracket(item,filec,field=Field,_RC)
         end if

         call ESMF_FieldGet(Field,grid=grid,rc=status)
         _VERIFY(STATUS)
         call ESMF_FieldBundleSet(pbundle,grid=grid,rc=status)
         _VERIFY(STATUS)
         call MAPL_FieldBundleAdd(pbundle,Field,rc=status)
         _VERIFY(STATUS)

      end if

      _RETURN(ESMF_SUCCESS)

  end subroutine MAPL_ExtDataPopulateBundle

  subroutine MAPL_ExtDataCreateCFIO(IOBundles, rc)
    type(IOBundleVector), target, intent(inout) :: IOBundles
    integer, optional,      intent(out  ) :: rc

     type (IoBundleVectorIterator) :: bundle_iter
     type (ExtData_IoBundle), pointer :: io_bundle
     integer :: status

     bundle_iter = IOBundles%begin()
     do while (bundle_iter /= IOBundles%end())
        io_bundle => bundle_iter%get()
        call io_bundle%make_cfio(_RC)
        call bundle_iter%next()
     enddo

     _RETURN(ESMF_SUCCESS)

  end subroutine MAPL_ExtDataCreateCFIO

  subroutine MAPL_ExtDataDestroyCFIO(IOBundles,rc)
     type(IOBundleVector), target, intent(inout) :: IOBundles
     integer, optional,      intent(out  ) :: rc

     type(IoBundleVectorIterator) :: bundle_iter
     type (ExtData_IoBundle), pointer :: io_bundle
     integer :: status

     bundle_iter = IOBundles%begin()
     do while (bundle_iter /= IOBundles%end())
        io_bundle => bundle_iter%get()
        call io_bundle%clean(_RC)
        call bundle_iter%next
     enddo
     call IOBundles%clear()

     _RETURN(ESMF_SUCCESS)

  end subroutine MAPL_ExtDataDestroyCFIO

  subroutine MAPL_ExtDataPrefetch(IOBundles,rc)
     type(IoBundleVector), target, intent(inout) :: IOBundles
     integer, optional,      intent(out  ) :: rc

     integer :: n,nfiles
     type(ExtData_IoBundle), pointer :: io_bundle => null()
     integer :: status

     nfiles = IOBundles%size()

     do n = 1, nfiles
        io_bundle => IOBundles%at(n)
        call io_bundle%cfio%request_data_from_file(io_bundle%file_name,io_bundle%time_index,rc=status)
        _VERIFY(status)
     enddo

     _RETURN(ESMF_SUCCESS)

  end subroutine MAPL_ExtDataPrefetch

  subroutine MAPL_ExtDataReadPrefetch(IOBundles,rc)
     type(IOBundleVector), target, intent(inout) :: IOBundles
     integer, optional,      intent(out  ) :: rc

     integer :: nfiles, n
     type (ExtData_IoBundle), pointer :: io_bundle
     integer :: status


     nfiles = IOBundles%size()
     do n=1, nfiles
        io_bundle => IOBundles%at(n)
        call io_bundle%cfio%process_data_from_file(rc=status)
        _VERIFY(status)
     enddo

     _RETURN(ESMF_SUCCESS)

  end subroutine MAPL_ExtDataReadPrefetch

  subroutine createFileLevBracket(item,cf,rc)
     type(PrimaryExport), intent(inout) :: item
     type(ESMF_Config), intent(inout) :: cf
     integer, optional, intent(out) :: rc

     integer :: status
     type (ESMF_Grid) :: grid, newgrid

     if (item%vartype==MAPL_FieldItem) then
        call ESMF_FieldGet(item%modelGridFields%v1_finterp1,grid=grid,_RC)
        newGrid = MAPL_ExtDataGridChangeLev(grid,cf,item%lm,_RC)
        call ESMF_FieldGet(item%modelGridFields%v1_finterp1,grid=grid,_RC)
        item%modelGridFields%v1_faux1 = MAPL_FieldCreate(item%modelGridFields%v1_finterp1,newGrid,lm=item%lm,newName=trim(item%var),_RC)
        item%modelGridFields%v1_faux2 = MAPL_FieldCreate(item%modelGridFields%v1_finterp2,newGrid,lm=item%lm,newName=trim(item%var),_RC)
     else if (item%vartype==MAPL_ExtDataVectorItem) then
        call ESMF_FieldGet(item%modelGridFields%v1_finterp1,grid=grid,_RC)
        newGrid = MAPL_ExtDataGridChangeLev(grid,cf,item%lm,_RC)
        call ESMF_FieldGet(item%modelGridFields%v1_finterp1,grid=grid,_RC)
        item%modelGridFields%v1_faux1 = MAPL_FieldCreate(item%modelGridFields%v1_finterp1,newGrid,lm=item%lm,newName=trim(item%fcomp1),_RC)
        item%modelGridFields%v1_faux2 = MAPL_FieldCreate(item%modelGridFields%v1_finterp2,newGrid,lm=item%lm,newName=trim(item%fcomp1),_RC)
        call ESMF_FieldGet(item%modelGridFields%v1_finterp1,grid=grid,_RC)
        item%modelGridFields%v2_faux1 = MAPL_FieldCreate(item%modelGridFields%v2_finterp1,newGrid,lm=item%lm,newName=trim(item%fcomp2),_RC)
        item%modelGridFields%v2_faux2 = MAPL_FieldCreate(item%modelGridFields%v2_finterp2,newGrid,lm=item%lm,newName=trim(item%fcomp2),_RC)
     end if
     _RETURN(_SUCCESS)

  end subroutine createFileLevBracket


  subroutine IOBundle_Add_Entry(IOBundles,item,entry_num,file,bside,time_index,rc)
     type(Iobundlevector), intent(inout) :: IOBundles
     type(primaryExport), intent(in)        :: item
     integer, intent(in)                    :: entry_num
     character(len=*), intent(in)           :: file
     integer, intent(in)                    :: bside
     integer, intent(in)                    :: time_index
     integer, intent(out), optional         :: rc

     integer :: status

     type (ExtData_IOBundle) :: io_bundle
     type (GriddedIOItemVector) :: items

     call items%push_back(item%fileVars)
     io_bundle = ExtData_IOBundle(bside, entry_num, file, time_index, item%trans, item%fracval, item%file, &
         item%pfioCollection_id,item%iclient_collection_id,items,rc=status)
     _VERIFY(status)

     call IOBundles%push_back(io_bundle)

     _RETURN(ESMF_SUCCESS)

  end subroutine IOBundle_Add_Entry

 END MODULE MAPL_ExtDataGridCompMod