! $Id: MAPL_Base.F90,v 1.8.2.3 2008/04/28 15:11:56 trayanov Exp $
#include "MAPL_ErrLog.h"


module MAPL_BaseMod 12,17

  use ESMF_Mod

  implicit none
  private

!=============================================================================
!BOP

! !MODULE: -- A container module for global constants


! !PUBLIC PARAMETERS

integer, public, parameter :: MAPL_CplUNKNOWN        = 0
integer, public, parameter :: MAPL_CplSATISFIED      = 1
integer, public, parameter :: MAPL_CplNEEDED         = 2
integer, public, parameter :: MAPL_CplNOTNEEDED      = 4
integer, public, parameter :: MAPL_FriendlyVariable  = 8
integer, public, parameter :: MAPL_FieldItem         = 8
integer, public, parameter :: MAPL_BundleItem        = 16
integer, public, parameter :: MAPL_NoRestart         = 32

integer, public, parameter :: MAPL_Write2Disk        = 0
integer, public, parameter :: MAPL_Write2RAM         = 1

integer, public, parameter :: MAPL_VLocationNone   = 0
integer, public, parameter :: MAPL_VLocationEdge   = 1
integer, public, parameter :: MAPL_VLocationCenter = 2

integer, public, parameter :: MAPL_DimsUnknown     = 0
integer, public, parameter :: MAPL_DimsVertOnly    = 1
integer, public, parameter :: MAPL_DimsHorzOnly    = 2
integer, public, parameter :: MAPL_DimsHorzVert    = 3
integer, public, parameter :: MAPL_DimsTileOnly    = 4
integer, public, parameter :: MAPL_DimsTileTile    = 5

integer, public, parameter :: MAPL_DuplicateEntry  = -99
integer, public, parameter :: MAPL_Self = 0 
integer, public, parameter :: MAPL_Import = 1
integer, public, parameter :: MAPL_Export = 2
integer, public, parameter :: MAPL_ConnUnknown = -1
integer, public, parameter :: MAPL_RecordPhase  = 99
integer, public, parameter :: MAPL_ColdstartPhase  = 99
integer, public, parameter :: MAPL_FirstPhase   = 81
integer, public, parameter :: MAPL_SecondPhase  = MAPL_FirstPhase+1
integer, public, parameter :: MAPL_ThirdPhase   = MAPL_FirstPhase+2
integer, public, parameter :: MAPL_FourthPhase  = MAPL_FirstPhase+3
integer, public, parameter :: MAPL_FifthPhase   = MAPL_FirstPhase+4

real,    public, parameter :: MAPL_UNDEF              = 1.0e15  

integer, public, parameter :: MAPL_Ocean              = 0
integer, public, parameter :: MAPL_Lake               = 19
integer, public, parameter :: MAPL_LandIce            = 20

integer, public, parameter :: MAPL_BroadleafEvergreen = 1
integer, public, parameter :: MAPL_BroadleafDeciduous = 2
integer, public, parameter :: MAPL_Needleleaf         = 3
integer, public, parameter :: MAPL_GroundCover        = 4
integer, public, parameter :: MAPL_BroadleafShrubs    = 5
integer, public, parameter :: MAPL_Tundra             = 6
integer, public, parameter :: MAPL_BareSoil           = 7
integer, public, parameter :: MAPL_Desert             = 8
integer, public, parameter :: MAPL_NumVegTypes        = 8

integer, public, parameter :: MAPL_Land               = 100
integer, public, parameter :: MAPL_Vegetated          = 101


! !PUBLIC VARIABLES:

!EOP

public MAPL_ArrayF90Deallocate

type WRAP1R4
   real(kind=4), dimension(:)    , pointer :: ptr
end type WRAP1R4

type WRAP2R4
   real(kind=4), dimension(:,:)    , pointer :: ptr
end type WRAP2R4

type WRAP3R4
   real(kind=4), dimension(:,:,:)    , pointer :: ptr
end type WRAP3R4

type WRAP4R4
   real(kind=4), dimension(:,:,:,:)    , pointer :: ptr
end type WRAP4R4

type WRAP1R8
   real(kind=8), dimension(:)    , pointer :: ptr
end type WRAP1R8

type WRAP2R8
   real(kind=8), dimension(:,:)    , pointer :: ptr
end type WRAP2R8

type WRAP3R8
   real(kind=8), dimension(:,:,:)    , pointer :: ptr
end type WRAP3R8

type WRAP4R8
   real(kind=8), dimension(:,:,:,:)    , pointer :: ptr
end type WRAP4R8


public MAPL_RTRN
public MAPL_VRFY
public MAPL_ASRT

public MAPL_AllocateCoupling
public MAPL_ConnectCoupling
public MAPL_DecomposeDim
public MAPL_Interp_Fac
public MAPL_ClimInterpFac
public MAPL_PackTime
public MAPL_UnpackTime
public MAPL_TimeStringGet
public MAPL_FieldSetTime
public MAPL_FieldGetTime
public MAPL_tick
public MAPL_incymd
public MAPL_nhmsf
public MAPL_nsecf2
public MAPL_FieldCreate
public MAPL_RemapBounds


interface MAPL_FieldCreate
   module procedure
   module procedure
end interface


interface MAPL_FieldGetTime 1
   module procedure MAPL_GetFieldTimeFromField
   module procedure MAPL_GetFieldTimeFromState
end interface


interface MAPL_FieldSetTime 1
   module procedure MAPL_SetFieldTimeFromField
   module procedure MAPL_SetFieldTimeFromState
end interface


interface MAPL_AllocateCoupling 10
   module procedure MAPL_AllocateCouplingFromArray
   module procedure MAPL_AllocateCouplingFromField
end interface


interface MAPL_ConnectCoupling 1
   module procedure MAPL_ConnectCouplingFromArray
   module procedure MAPL_ConnectCouplingFromField
end interface


interface MAPL_RemapBounds
   module procedure
end interface


interface MAPL_VRFY 1
   module procedure MAPL_VRFY
   module procedure
end interface


interface MAPL_ASRT 1
   module procedure MAPL_ASRT
   module procedure
end interface


interface MAPL_RTRN 1
   module procedure MAPL_RTRN
   module procedure
end interface

contains

  subroutine MAPL_AllocateCouplingFromField(field, rc) 1,1
    type(ESMF_Field),  intent(INOUT) :: field
    integer, optional, intent(  OUT) :: rc             
    
    integer                                 :: status
    character(len=ESMF_MAXSTR), parameter   :: IAm='MAPL_AllocateCouplingFromField'
    type(ESMF_Array)                        :: array
    
#ifdef ESMF_1_0_4
    call ESMF_FieldGetData (FIELD, ARRAY, RC=STATUS)
#else
    call ESMF_FieldGetArray (FIELD, ARRAY, RC=STATUS)
#endif
    VERIFY_(STATUS)
    
    call MAPL_AllocateCouplingFromArray(array, rc=STATUS)
    VERIFY_(STATUS)
    
    RETURN_(ESMF_SUCCESS)
  end subroutine MAPL_AllocateCouplingFromField


  subroutine MAPL_AllocateCouplingFromArray(array, rc) 2
    type(ESMF_Array),  intent(INOUT) :: array
    integer, optional, intent(  OUT) :: rc             
    
    integer                                 :: rank
    type(ESMF_DataType)                     :: type
    type(ESMF_DataKind)                     :: dk
    integer, dimension(ESMF_MAXDIM)         :: counts, lbounds, ubounds
    type(ESMF_Pointer)                      :: base
    integer                                 :: status
    character(len=ESMF_MAXSTR), parameter   :: IAm='MAPL_AllocateCouplingFromArray'

    real(kind=4), dimension(:)        , pointer :: r4d1
    real(kind=4), dimension(:,:)      , pointer :: r4d2
    real(kind=4), dimension(:,:,:)    , pointer :: r4d3
    real(kind=4), dimension(:,:,:,:)  , pointer :: r4d4

    real(kind=8), dimension(:)        , pointer :: r8d1
    real(kind=8), dimension(:,:)      , pointer :: r8d2
    real(kind=8), dimension(:,:,:)    , pointer :: r8d3
    real(kind=8), dimension(:,:,:,:)  , pointer :: r8d4

    type (WRAP1R4) :: wrap1dr4
    type (WRAP2R4) :: wrap2dr4
    type (WRAP3R4) :: wrap3dr4
    type (WRAP4R4) :: wrap4dr4

    type (WRAP1R8) :: wrap1dr8
    type (WRAP2R8) :: wrap2dr8
    type (WRAP3R8) :: wrap3dr8
    type (WRAP4R8) :: wrap4dr8

    call ESMF_ArrayGet(array, rank, kind=dk, &
                       counts = counts, lbounds=lbounds, ubounds=ubounds, &
                       base=base, rc=status)
    VERIFY_(STATUS)
!ALT in case the counts=0 emsf keeps ubounds=lbounds
    where (counts==0) ubounds = lbounds + counts - 1
    if (dk .eq. ESMF_R4) then
       if (rank .eq. 1) then
          call ESMF_ArrayGetData(array, r4d1, rc=status)
          VERIFY_(STATUS)
          if (.not. associated(r4d1)) then
             allocate(r4d1(lbounds(1):ubounds(1)),  stat=status)
             VERIFY_(STATUS)

             r4d1 = 0.0
             call c_ESMC_ArraySetBaseAddr(array, r4d1, status) 
             VERIFY_(STATUS)

             wrap1dr4%ptr => r4d1
             call c_ESMC_ArraySetF90Ptr(array, wrap1dr4, status) 
             VERIFY_(STATUS)
          endif

       else if (rank .eq. 2) then
          call ESMF_ArrayGetData(array, r4d2, rc=status)
          VERIFY_(STATUS)
          if (.not. associated(r4d2)) then
             allocate(r4d2(lbounds(1):ubounds(1), &
                           lbounds(2):ubounds(2)),  stat=status)
             VERIFY_(STATUS)

             r4d2 = 0.0
             call c_ESMC_ArraySetBaseAddr(array, r4d2, status) 
             VERIFY_(STATUS)

             wrap2dr4%ptr => r4d2
             call c_ESMC_ArraySetF90Ptr(array, wrap2dr4, status) 
             VERIFY_(STATUS)
          endif

       else if (rank .eq. 3) then
          call ESMF_ArrayGetData(array, r4d3, rc=status)
          VERIFY_(STATUS)
          if (.not. associated(r4d3)) then
             allocate(r4d3(lbounds(1):ubounds(1), &
                           lbounds(2):ubounds(2), &
                           lbounds(3):ubounds(3)), stat=status)
             VERIFY_(STATUS)

             r4d3 = 0.0
             call c_ESMC_ArraySetBaseAddr(array, r4d3, status) 
             VERIFY_(STATUS)

             wrap3dr4%ptr => r4d3
             call c_ESMC_ArraySetF90Ptr(array, wrap3dr4, status) 
             VERIFY_(STATUS)
          endif

       else if (rank .eq. 4) then
          call ESMF_ArrayGetData(array, r4d4, rc=status)
          VERIFY_(STATUS)
          if (.not. associated(r4d4)) then
             allocate(r4d4(lbounds(1):ubounds(1), &
                           lbounds(2):ubounds(2), &
                           lbounds(3):ubounds(3), &
                           lbounds(4):ubounds(4)), stat=status)
             VERIFY_(STATUS)

             r4d4 = 0.0
             call c_ESMC_ArraySetBaseAddr(array, r4d4, status) 
             VERIFY_(STATUS)

             wrap4dr4%ptr => r4d4
             call c_ESMC_ArraySetF90Ptr(array, wrap4dr4, status) 
             VERIFY_(STATUS)
          end if

       else
          RETURN_(ESMF_FAILURE)
       endif
    else if (dk .eq. ESMF_R8) then
       if (rank .eq. 1) then
          call ESMF_ArrayGetData(array, r8d1, rc=status)
          VERIFY_(STATUS)
          if (.not. associated(r8d1)) then
             allocate(r8d1(lbounds(1):ubounds(1)),  stat=status)
             VERIFY_(STATUS)

             r8d1 = 0.0
             call c_ESMC_ArraySetBaseAddr(array, r8d1, status) 
             VERIFY_(STATUS)

             wrap1dr8%ptr => r8d1
             call c_ESMC_ArraySetF90Ptr(array, wrap1dr8, status) 
             VERIFY_(STATUS)
          endif

       else if (rank .eq. 2) then
          call ESMF_ArrayGetData(array, r8d2, rc=status)
          VERIFY_(STATUS)
          if (.not. associated(r8d2)) then
             allocate(r8d2(lbounds(1):ubounds(1), &
                           lbounds(2):ubounds(2)),  stat=status)
             VERIFY_(STATUS)

             r8d2 = 0.0
             call c_ESMC_ArraySetBaseAddr(array, r8d2, status) 
             VERIFY_(STATUS)

             wrap2dr8%ptr => r8d2
             call c_ESMC_ArraySetF90Ptr(array, wrap2dr8, status) 
             VERIFY_(STATUS)
          endif

       else if (rank .eq. 3) then
          call ESMF_ArrayGetData(array, r8d3, rc=status)
          VERIFY_(STATUS)
          if (.not. associated(r8d3)) then
             allocate(r8d3(lbounds(1):ubounds(1), &
                           lbounds(2):ubounds(2), &
                           lbounds(3):ubounds(3)), stat=status)
             VERIFY_(STATUS)

             r8d3 = 0.0
             call c_ESMC_ArraySetBaseAddr(array, r8d3, status) 
             VERIFY_(STATUS)

             wrap3dr8%ptr => r8d3
             call c_ESMC_ArraySetF90Ptr(array, wrap3dr8, status) 
             VERIFY_(STATUS)
          endif

       else if (rank .eq. 4) then
          call ESMF_ArrayGetData(array, r8d4, rc=status)
          VERIFY_(STATUS)
          if (.not. associated(r8d4)) then
             allocate(r8d4(lbounds(1):ubounds(1), &
                           lbounds(2):ubounds(2), &
                           lbounds(3):ubounds(3), &
                           lbounds(4):ubounds(4)), stat=status)
             VERIFY_(STATUS)

             r8d4 = 0.0
             call c_ESMC_ArraySetBaseAddr(array, r8d4, status) 
             VERIFY_(STATUS)

             wrap4dr8%ptr => r8d4
             call c_ESMC_ArraySetF90Ptr(array, wrap4dr8, status) 
             VERIFY_(STATUS)
          end if

       else
          RETURN_(ESMF_FAILURE)
       endif
    else
       RETURN_(ESMF_FAILURE)
    endif

    RETURN_(ESMF_SUCCESS)


  end subroutine MAPL_AllocateCouplingFromArray






  subroutine MAPL_ConnectCouplingFromField(field, from_field, rc) 1,1
    type(ESMF_Field),  intent(INOUT) :: field
    type(ESMF_Field),  intent(IN   ) :: from_field
    integer, optional, intent(  OUT) :: rc             
    
    integer                                 :: status
    character(len=ESMF_MAXSTR), parameter   :: IAm='MAPL_ConnectCouplingFromField'
    type(ESMF_Array)                        :: array
    type(ESMF_Array)                        :: from_array
    
#ifdef ESMF_1_0_4
    call ESMF_FieldGetData (FIELD, ARRAY, RC=STATUS)
#else
    call ESMF_FieldGetArray (FIELD, ARRAY, RC=STATUS)
#endif
    VERIFY_(STATUS)

#ifdef ESMF_1_0_4
    call ESMF_FieldGetData (FROM_FIELD, FROM_ARRAY, RC=STATUS)
#else
    call ESMF_FieldGetArray (FROM_FIELD, FROM_ARRAY, RC=STATUS)
#endif
    VERIFY_(STATUS)
    
    call MAPL_ConnectCouplingFromArray(array, from_array, rc=STATUS)
    VERIFY_(STATUS)
    
    RETURN_(ESMF_SUCCESS)
  end subroutine MAPL_ConnectCouplingFromField



  subroutine MAPL_ConnectCouplingFromArray(array, from_array, rc) 2
    type(ESMF_Array),  intent(INOUT) :: array
    type(ESMF_Array),  intent(IN   ) :: from_array
    integer, optional, intent(  OUT) :: rc             
    
    integer                                 :: rank
    type(ESMF_DataType)                     :: type
    type(ESMF_DataKind)                     :: dk
    integer, dimension(ESMF_MAXDIM)         :: counts, lbounds, ubounds
    type(ESMF_Pointer)                      :: base
    integer                                 :: status
    character(len=ESMF_MAXSTR), parameter   :: IAm='MAPL_ConnectCouplingFromArray'

    real(kind=4), dimension(:)        , pointer :: p4d1
    real(kind=4), dimension(:,:)      , pointer :: p4d2
    real(kind=4), dimension(:,:,:)    , pointer :: p4d3
    real(kind=4), dimension(:,:,:,:)  , pointer :: p4d4

    real(kind=4), dimension(:)        , pointer :: r4d1
    real(kind=4), dimension(:,:)      , pointer :: r4d2
    real(kind=4), dimension(:,:,:)    , pointer :: r4d3
    real(kind=4), dimension(:,:,:,:)  , pointer :: r4d4

    real(kind=8), dimension(:)        , pointer :: r8d1
    real(kind=8), dimension(:,:)      , pointer :: r8d2
    real(kind=8), dimension(:,:,:)    , pointer :: r8d3
    real(kind=8), dimension(:,:,:,:)  , pointer :: r8d4

    type (WRAP1R4) :: wrap1dr4
    type (WRAP2R4) :: wrap2dr4
    type (WRAP3R4) :: wrap3dr4
    type (WRAP4R4) :: wrap4dr4

    type (WRAP1R8) :: wrap1dr8
    type (WRAP2R8) :: wrap2dr8
    type (WRAP3R8) :: wrap3dr8
    type (WRAP4R8) :: wrap4dr8

    call ESMF_ArrayGet(array, rank, kind=dk, &
                       counts = counts, lbounds=lbounds, ubounds=ubounds, &
                       base=base, rc=status)
    VERIFY_(STATUS)
    where (counts==0) ubounds = lbounds + counts - 1
    if (dk .eq. ESMF_R4) then
       if (rank .eq. 1) then
          call ESMF_ArrayGetData(from_array, p4d1, rc=status)
          VERIFY_(STATUS)
          call ESMF_ArrayGetData(array, r4d1, rc=status)
          VERIFY_(STATUS)
          if (associated(r4d1)) then
             deallocate(r4d1,  stat=status)
             VERIFY_(STATUS)
          endif

          r4d1 => p4d1
          call c_ESMC_ArraySetBaseAddr(array, r4d1, status) 
          VERIFY_(STATUS)

          wrap1dr4%ptr => r4d1
          call c_ESMC_ArraySetF90Ptr(array, wrap1dr4, status) 
          VERIFY_(STATUS)

       else if (rank .eq. 2) then
          call ESMF_ArrayGetData(from_array, p4d2, rc=status)
          VERIFY_(STATUS)
          call ESMF_ArrayGetData(array, r4d2, rc=status)
          VERIFY_(STATUS)
          if (associated(r4d2)) then
             deallocate(r4d2,  stat=status)
             VERIFY_(STATUS)
          endif

          r4d2 => p4d2
          call c_ESMC_ArraySetBaseAddr(array, r4d2, status) 
          VERIFY_(STATUS)

          wrap2dr4%ptr => r4d2
          call c_ESMC_ArraySetF90Ptr(array, wrap2dr4, status) 
          VERIFY_(STATUS)

       else if (rank .eq. 3) then
          call ESMF_ArrayGetData(from_array, p4d3, rc=status)
          VERIFY_(STATUS)
          call ESMF_ArrayGetData(array, r4d3, rc=status)
          VERIFY_(STATUS)
          if (associated(r4d3)) then
             deallocate(r4d3, stat=status)
             VERIFY_(STATUS)
          end if
          r4d3 => p4d3
          call c_ESMC_ArraySetBaseAddr(array, r4d3, status) 
          VERIFY_(STATUS)

          wrap3dr4%ptr => r4d3
          call c_ESMC_ArraySetF90Ptr(array, wrap3dr4, status) 
          VERIFY_(STATUS)

       else if (rank .eq. 4) then
          call ESMF_ArrayGetData(from_array, p4d4, rc=status)
          VERIFY_(STATUS)
          call ESMF_ArrayGetData(array, r4d4, rc=status)
          VERIFY_(STATUS)
          if (associated(r4d4)) then
             deallocate(r4d4, stat=status)
             VERIFY_(STATUS)
          end if
          r4d4 => p4d4
          call c_ESMC_ArraySetBaseAddr(array, r4d4, status) 
          VERIFY_(STATUS)

          wrap4dr4%ptr => r4d4
          call c_ESMC_ArraySetF90Ptr(array, wrap4dr4, status) 
          VERIFY_(STATUS)

       else
          RETURN_(ESMF_FAILURE)
       endif
    else if (dk .eq. ESMF_R8) then
!ALT: temporaty set to FAIL; if compiles OK, copy and paste from above; replace r4=>r8
       RETURN_(ESMF_FAILURE)
    else
       RETURN_(ESMF_FAILURE)
    endif

    RETURN_(ESMF_SUCCESS)


  end subroutine MAPL_ConnectCouplingFromArray


  subroutine MAPL_ArrayF90Deallocate(array, rc) 9
    type(ESMF_Array),  intent(INOUT) :: array
    integer, optional, intent(  OUT) :: rc             
    
    integer                                 :: rank
    type(ESMF_DataType)                     :: type
    type(ESMF_DataKind)                     :: dk
    integer, dimension(ESMF_MAXDIM)         :: counts, lbounds, ubounds
    type(ESMF_Pointer)                      :: base
    integer                                 :: status
    character(len=ESMF_MAXSTR), parameter   :: IAm='MAPL_ArrayF90Deallocate'

    real(kind=4), dimension(:)        , pointer :: r4d1
    real(kind=4), dimension(:,:)      , pointer :: r4d2
    real(kind=4), dimension(:,:,:)    , pointer :: r4d3
    real(kind=4), dimension(:,:,:,:)  , pointer :: r4d4

    real(kind=8), dimension(:)        , pointer :: r8d1
    real(kind=8), dimension(:,:)      , pointer :: r8d2
    real(kind=8), dimension(:,:,:)    , pointer :: r8d3
    real(kind=8), dimension(:,:,:,:)  , pointer :: r8d4

    type (WRAP1R4) :: wrap1dr4
    type (WRAP2R4) :: wrap2dr4
    type (WRAP3R4) :: wrap3dr4
    type (WRAP4R4) :: wrap4dr4

    type (WRAP1R8) :: wrap1dr8
    type (WRAP2R8) :: wrap2dr8
    type (WRAP3R8) :: wrap3dr8
    type (WRAP4R8) :: wrap4dr8

    call ESMF_ArrayGet(array, rank, kind=dk, &
                       counts = counts, lbounds=lbounds, ubounds=ubounds, &
                       base=base, rc=status)
    VERIFY_(STATUS)
    if (dk .eq. ESMF_R4) then
       if (rank .eq. 1) then
          call ESMF_ArrayGetData(array, r4d1, rc=status)
          VERIFY_(STATUS)
          if (associated(r4d1)) then
             deallocate(r4d1,  stat=status)
             VERIFY_(STATUS)

             wrap1dr4%ptr => r4d1
             call c_ESMC_ArraySetF90Ptr(array, wrap1dr4, status) 
             VERIFY_(STATUS)
          endif

       else if (rank .eq. 2) then
          call ESMF_ArrayGetData(array, r4d2, rc=status)
          VERIFY_(STATUS)
          if (associated(r4d2)) then
             deallocate(r4d2,  stat=status)
             VERIFY_(STATUS)

             wrap2dr4%ptr => r4d2
             call c_ESMC_ArraySetF90Ptr(array, wrap2dr4, status) 
             VERIFY_(STATUS)
          endif

       else if (rank .eq. 3) then
          call ESMF_ArrayGetData(array, r4d3, rc=status)
          VERIFY_(STATUS)
          if (associated(r4d3)) then
             deallocate(r4d3, stat=status)
             VERIFY_(STATUS)

             wrap3dr4%ptr => r4d3
             call c_ESMC_ArraySetF90Ptr(array, wrap3dr4, status) 
             VERIFY_(STATUS)
          endif

       else if (rank .eq. 4) then
          call ESMF_ArrayGetData(array, r4d4, rc=status)
          VERIFY_(STATUS)
          if (associated(r4d4)) then
             deallocate(r4d4, stat=status)
             VERIFY_(STATUS)

             wrap4dr4%ptr => r4d4
             call c_ESMC_ArraySetF90Ptr(array, wrap4dr4, status) 
             VERIFY_(STATUS)
          end if

       else
          RETURN_(ESMF_FAILURE)
       endif
    else if (dk .eq. ESMF_R8) then
!ALT: temporaty set to FAIL; if compiles OK, copy and paste from above; replace r4=>r8
       RETURN_(ESMF_FAILURE)
    else
       RETURN_(ESMF_FAILURE)
    endif

    RETURN_(ESMF_SUCCESS)


  end subroutine MAPL_ArrayF90Deallocate


  subroutine MAPL_DecomposeDim ( dim_world,dim,NDEs ) 10
      implicit   none
      integer    dim_world, NDEs
      integer    dim(0:NDEs-1)
      integer    n,im,rm,nbeg,nend
      im = dim_world/NDEs
      rm = dim_world-NDEs*im
      do n=0,NDEs-1
                      dim(n) = im
      if( n.le.rm-1 ) dim(n) = im+1
      enddo
  end subroutine MAPL_DecomposeDim


  subroutine MAPL_Interp_Fac (TIME0, TIME1, TIME2, FAC1, FAC2, RC) 3

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

!  PURPOSE:
!  ========
!
!    Compute interpolation factors, fac, to be used 
!    in the calculation of the instantaneous boundary 
!    conditions, ie:
!
!     q(i,j) = fac1*q1(i,j) + (1.-fac1)*q2(i,j)
!
!    where:
!     q(i,j)  => Boundary Data valid    at time0
!     q1(i,j) => Boundary Data centered at time1
!     q2(i,j) => Boundary Data centered at time2

!  INPUT:
!  ======
!    time0    : Time of current timestep
!    time1    : Time of boundary data 1 
!    time2    : Time of boundary data 2 

!  OUTPUT:
!  =======
!     fac1    : Interpolation factor for Boundary Data 1
!
! ------------------------------------------------------------        
!               GODDARD LABORATORY FOR ATMOSPHERES            
! ------------------------------------------------------------        

    type(ESMF_Time),   intent(in ) :: TIME0, TIME1, TIME2
    real,              intent(out) :: FAC1
    real,    optional, intent(out) :: FAC2
    integer, optional, intent(out) :: RC
 
    type(ESMF_TimeInterval)        :: TimeDif1
    type(ESMF_TimeInterval)        :: TimeDif
 
    TimeDif1 = TIME2-TIME0
    TimeDif  = TIME2-TIME1
       
    FAC1 = TimeDif1/TimeDif

    if(present(FAC2)) FAC2 = 1.-FAC1
    if(present(RC  )) RC   = ESMF_SUCCESS
 
  end subroutine MAPL_Interp_Fac


  subroutine MAPL_ClimInterpFac (CLOCK,I1,I2,FAC, RC) 1,1

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

    type(ESMF_CLOCK),  intent(in ) :: CLOCK
    integer,           intent(OUT) :: I1, I2
    real,              intent(out) :: FAC
    integer, optional, intent(out) :: RC
 
    integer                                 :: STATUS
    character(len=ESMF_MAXSTR), parameter   :: IAm='MAPL_ClimInterpFac'

    type (ESMF_Time)                  :: CurrTime
    type (ESMF_Time)                  :: midMonth
    type (ESMF_Time)                  :: BEFORE, AFTER
    type (ESMF_TimeInterval)          :: oneMonth
    type (ESMF_Calendar)              :: cal

    call ESMF_ClockGet       ( CLOCK,    CurrTime=CurrTime, calendar=cal, rc=STATUS )
    VERIFY_(STATUS)
    call ESMF_TimeGet        ( CurrTime, midMonth=midMonth,               rc=STATUS )
    VERIFY_(STATUS)
    call ESMF_TimeIntervalSet( oneMonth, MM = 1, calendar=cal,            rc=status )
    VERIFY_(STATUS)

    if( CURRTIME < midMonth ) then
       AFTER    = midMonth
       midMonth = midMonth - oneMonth
       call ESMF_TimeGet (midMonth, midMonth=BEFORE, rc=STATUS )
       VERIFY_(STATUS)
    else
       BEFORE   = midMonth
       midMonth = midMonth + oneMonth
       call ESMF_TimeGet (midMonth, midMonth=AFTER , rc=STATUS )
       VERIFY_(STATUS)
    endif

    call MAPL_Interp_Fac( CURRTIME, BEFORE, AFTER, FAC, RC=STATUS)
    VERIFY_(STATUS)

    call ESMF_TimeGet (BEFORE, MM=I1, rc=STATUS )
    VERIFY_(STATUS)
    call ESMF_TimeGet (AFTER , MM=I2, rc=STATUS )
    VERIFY_(STATUS)
 

    RETURN_(ESMF_SUCCESS)
  end subroutine MAPL_ClimInterpFac



subroutine MAPL_TimeStringGet(TIMESTRING,YY,MM,DD,H,M,S) 1
  character(len=*),  intent (IN ) :: TIMESTRING
  integer, optional, intent (OUT) :: YY
  integer, optional, intent (OUT) :: MM
  integer, optional, intent (OUT) :: DD
  integer, optional, intent (OUT) :: H
  integer, optional, intent (OUT) :: M
  integer, optional, intent (OUT) :: S

  integer :: IYY, IMM, IDD, IHH, IMN, ISS

  read(TIMESTRING,'(I4,1X,I2,1X,I2,1X,I2,1X,I2,1X,I2)') IYY,IMM,IDD,IHH,IMN,ISS
  
!ALT: SGI compiler does not like this format  read(TIMESTRING,'(I4,"-",I2,"-",I2,"T",I2,":",I2,":",I2)') IYY,IMM,IDD,IHH,IMN,ISS
  if(present(YY)) YY = IYY
  if(present(MM)) MM = IMM
  if(present(DD)) DD = IDD
  if(present(H )) H  = IHH
  if(present(M )) M  = IMN
  if(present(S )) S  = ISS

  return
end subroutine MAPL_TimeStringGet



subroutine MAPL_UnpackTime(TIME,IYY,IMM,IDD) 2
  integer, intent (IN ) :: TIME
  integer, intent (OUT) :: IYY
  integer, intent (OUT) :: IMM
  integer, intent (OUT) :: IDD
  IYY = TIME/10000
  IMM = mod(TIME/100,100)
  IDD = mod(TIME,100)
end subroutine MAPL_UnpackTime


subroutine MAPL_PackTime(TIME,IYY,IMM,IDD) 6
  integer, intent (OUT) :: TIME
  integer, intent (IN ) :: IYY
  integer, intent (IN ) :: IMM
  integer, intent (IN ) :: IDD
  TIME=IYY*10000+IMM*100+IDD
end subroutine MAPL_PackTime


subroutine MAPL_tick (nymd,nhms,ndt)
      integer nymd,nhms,ndt,nsec,nsecf
      nsecf(nhms) = nhms/10000*3600 + mod(nhms,10000)/100*60 + mod(nhms,100)
      IF(NDT.NE.0) THEN
      NSEC = NSECF(NHMS) + NDT
      IF (NSEC.GT.86400)  THEN
      DO WHILE (NSEC.GT.86400)
      NSEC = NSEC - 86400
      NYMD = MAPL_INCYMD (NYMD,1)
      ENDDO
      ENDIF   
      IF (NSEC.EQ.86400)  THEN
      NSEC = 0
      NYMD = MAPL_INCYMD (NYMD,1)
      ENDIF   
      IF (NSEC.LT.00000)  THEN
      DO WHILE (NSEC.LT.0)
      NSEC = 86400 + NSEC
      NYMD = MAPL_INCYMD (NYMD,-1)
      ENDDO
      ENDIF   
      NHMS = MAPL_NHMSF (NSEC)
      ENDIF   
      RETURN  
end subroutine MAPL_tick    


logical function MAPL_RTRN(A,iam,line,rc) 1
   integer,           intent(IN ) :: A
   character*(*),     intent(IN ) :: iam
   integer,           intent(IN ) :: line
   integer, optional, intent(OUT) :: RC

     MAPL_RTRN = .true.
     if(A/=ESMF_SUCCESS)print'(A40,I10)',Iam,line
     if(present(RC)) RC=A
end function MAPL_RTRN


logical function MAPL_VRFY(A,iam,line,rc) 1
   integer,           intent(IN ) :: A
   character*(*),     intent(IN ) :: iam
   integer,           intent(IN ) :: line
   integer, optional, intent(OUT) :: RC
     MAPL_VRFY = A/=ESMF_SUCCESS 
     if(MAPL_VRFY)then
       if(present(RC)) then
         print'(A40,I10)',Iam,line
         RC=A
       endif
     endif
end function MAPL_VRFY


logical function MAPL_ASRT(A,iam,line,rc) 1
   logical,           intent(IN ) :: A
   character*(*),     intent(IN ) :: iam
   integer,           intent(IN ) :: line
   integer, optional, intent(OUT) :: RC
     MAPL_ASRT = .not.A 
     if(MAPL_ASRT)then
       if(present(RC))then
         print'(A40,I10)',Iam,LINE
         RC=ESMF_FAILURE
       endif
     endif
end function MAPL_ASRT


logical function MAPL_RTRNt(A,text,iam,line,rc)
   integer,           intent(IN ) :: A
   character*(*),     intent(IN ) :: text,iam
   integer,           intent(IN ) :: line
   integer, optional, intent(OUT) :: RC

     MAPL_RTRNt = .true.
     if(A/=ESMF_SUCCESS)then
        print'(A40,I10)',Iam,line
        print *, text
     end if
     if(present(RC)) RC=A

end function MAPL_RTRNT


logical function MAPL_VRFYt(A,text,iam,line,rc)
   integer,           intent(IN ) :: A
   character*(*),     intent(IN ) :: iam,text
   integer,           intent(IN ) :: line
   integer, optional, intent(OUT) :: RC
     MAPL_VRFYt =  MAPL_VRFY(A,iam,line,rc)
     if(MAPL_VRFYt) print *, text
end function MAPL_VRFYT


logical function MAPL_ASRTt(A,text,iam,line,rc)
   logical,           intent(IN ) :: A
   character*(*),     intent(IN ) :: iam,text
   integer,           intent(IN ) :: line
   integer, optional, intent(OUT) :: RC
     MAPL_ASRTt =   MAPL_ASRT(A,iam,line,rc)
     if(MAPL_ASRTt) print *, text
end function MAPL_ASRTT


integer function MAPL_nsecf2 (nhhmmss,nmmdd,nymd)
      integer nhhmmss,nmmdd,nymd,nhms,nday,month
      integer nsday, ncycle,iday,iday2
      integer nsecf,i,nsegm,nsegd
      PARAMETER ( NSDAY  = 86400 )
      PARAMETER ( NCYCLE = 1461*24*3600 )
      INTEGER YEAR, DAY, SEC, YEAR0, DAY0, SEC0
      integer    MNDY(12,4), mnd48(48)
      DATA MND48/0,31,60,91,121,152,182,213,244,274,305,335,366,397,34*0 /
!     DATA MNDY /0,31,60,91,121,152,182,213,244,274,305,335,366,397,34*0 /
      equivalence ( mndy(1,1), mnd48(1) )
      nsecf(nhms) = nhms/10000*3600 + mod(nhms,10000)/100*60 + mod(nhms,100)
      MAPL_nsecf2 = nsecf( nhhmmss )
      if( nmmdd.eq.0 ) return
      DO 100 I=15,48
!     MNDY(I,1) = MNDY(I-12,1) + 365
      MND48(I) = MND48(I-12) + 365
100   CONTINUE
      nsegm =     nmmdd/100
      nsegd = mod(nmmdd,100)
      YEAR   = NYMD / 10000
      MONTH  = MOD(NYMD,10000) / 100
      DAY    = MOD(NYMD,100)
      SEC    = NSECF(nhhmmss)
      IDAY   = MNDY( MONTH ,MOD(YEAR ,4)+1 )
      month = month + nsegm
      If( month.gt.12 ) then
      month = month - 12
      year = year + 1
      endif
      IDAY2  = MNDY( MONTH ,MOD(YEAR ,4)+1 )
                    nday = iday2-iday
      if(nday.lt.0) nday = nday + 1461
                    nday = nday + nsegd
      MAPL_nsecf2 = MAPL_nsecf2 + nday*nsday
end function MAPL_nsecf2


integer function MAPL_nhmsf (nsec)
        implicit none
        integer  nsec
        MAPL_nhmsf =  nsec/3600*10000 + mod(nsec,3600)/60*100 + mod(nsec,60)
end function MAPL_nhmsf


integer function MAPL_incymd (NYMD,M)                                                  
      integer nymd,ny,nm,nd,m,ny00
      INTEGER NDPM(12)                                                          
      DATA    NDPM /31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/             
      LOGICAL LEAP                                                              
      DATA    NY00     / 1900 /                                                 
      LEAP(NY) = MOD(NY,4).EQ.0 .AND. (NY.NE.0 .OR. MOD(NY00,400).EQ.0)         
      NY = NYMD / 10000                                                         
      NM = MOD(NYMD,10000) / 100                                                
      ND = MOD(NYMD,100) + M                                                    
      IF (ND.EQ.0) THEN                                                         
      NM = NM - 1                                                               
      IF (NM.EQ.0) THEN                                                         
          NM = 12                                                               
          NY = NY - 1                                                           
      ENDIF                                                                     
      ND = NDPM(NM)                                                             
      IF (NM.EQ.2 .AND. LEAP(NY))  ND = 29                                      
      ENDIF                                                                     
      IF (ND.EQ.29 .AND. NM.EQ.2 .AND. LEAP(NY))  GO TO 20                      
      IF (ND.GT.NDPM(NM)) THEN                                                  
      ND = 1                                                                    
      NM = NM + 1                                                               
      IF (NM.GT.12) THEN                                                        
          NM = 1                                                                
          NY = NY + 1                                                           
      ENDIF                                                                     
      ENDIF                                                                     
   20 CONTINUE                                                                  
      MAPL_INCYMD = NY*10000 + NM*100 + ND                                           
      RETURN                                                                    
end function MAPL_incymd



subroutine MAPL_PICKEM(II,JJ,IM,JM,COUNT)
integer, intent(IN ) :: IM, JM, COUNT
integer, intent(OUT) :: II(COUNT), JJ(COUNT)

integer, parameter :: NT=3

logical :: MASK(IM,JM)
integer :: L, NN, IX, JX
real    :: IIR(NT*COUNT), JJR(NT*COUNT)

   MASK=.true.

   NN=1

   call RANDOM_NUMBER(IIR)
   call RANDOM_NUMBER(JJR)


   do L=1, COUNT

      do
         IX=IIR(NN)*(IM-1)+2
         JX=JJR(NN)*(JM-2)+2

         NN = NN + 1

         if(MASK(IX,JX)) then
            II(L) = IX
            JJ(L) = JX
            MASK(IX-1:IX+1,JX-1:JX+1) = .false.
            exit
         endif

         if(NN>NT*COUNT) stop 222

      enddo
   enddo

!!$   DO L=1,JM
!!$      PRINT '(144L1)',MASK(:,L) 
!!$   ENDDO
!!$
!!$   PRINT *, COUNT, NN

   return
 end subroutine MAPL_PICKEM





    subroutine MAPL_GetFieldTimeFromField ( FIELD, TIME, RC ) 1,3
      type(ESMF_Field),        intent(IN   ) :: FIELD
      type(ESMF_Time),         intent(  OUT) :: TIME
      integer, optional,       intent(  OUT) :: RC

      character(len=ESMF_MAXSTR),parameter   :: IAm=" MAPL_GetFieldTimeFromField"
      integer                                :: STATUS

      integer                                :: YEAR, MONTH, DAY
      integer                                :: HOUR, MINUTE, SCND
      character(len=ESMF_MAXSTR)             :: TIMESTAMP

      call ESMF_FieldGetAttribute(FIELD,     NAME="TimeStamp", VALUE=TIMESTAMP, RC=STATUS)
      if(STATUS/=0) then
         call ESMF_TimeSet          (TIME,      YY=0,                RC=STATUS)
      else
         call MAPL_TimeStringGet    (TIMESTAMP, YY=YEAR, MM=MONTH,  DD=DAY,   & 
                                                H =HOUR, M =MINUTE, S =SCND   )
         VERIFY_(STATUS)
         call ESMF_TimeSet          (TIME,      YY=YEAR, MM=MONTH,  DD=DAY,   &
                                                H =HOUR, M =MINUTE, S =SCND,  &
                                                                     RC=STATUS)
         VERIFY_(STATUS)
      end if

      RETURN_(ESMF_SUCCESS)
    end subroutine MAPL_GetFieldTimeFromField

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


    subroutine  MAPL_SetFieldTimeFromField (FIELD, TIME, RC ) 1
      type(ESMF_FIELD),        intent(INOUT) :: FIELD
      type(ESMF_TIME),         intent(IN   ) :: TIME
      integer, optional,       intent(  OUT) :: RC

      character(len=ESMF_MAXSTR),parameter   :: IAm=" MAPL_SetFieldTimeFromField"
      integer                                :: STATUS

      integer                                :: YEAR, MONTH, DAY
      character(len=ESMF_MAXSTR)             :: TIMESTAMP

      call ESMF_TimeGet          (TIME,  timeString=TIMESTAMP,             RC=STATUS)
      VERIFY_(STATUS)
      call ESMF_FieldSetAttribute(FIELD, NAME="TimeStamp", VALUE=TIMESTAMP, RC=STATUS)
      VERIFY_(STATUS)

      RETURN_(ESMF_SUCCESS)
    end subroutine  MAPL_SetFieldTimeFromField



    subroutine  MAPL_GetFieldTimeFromState ( STATE, Fieldname, TIME, RC ) 1
      type(ESMF_STATE),        intent(IN   ) :: STATE
      character(len=*),        intent(IN   ) :: Fieldname
      type(ESMF_Time),         intent(  OUT) :: TIME
      integer, optional,       intent(  OUT) :: RC

      character(len=ESMF_MAXSTR),parameter   :: IAm=" MAPL_GetFieldTimeFromState"
      integer                                :: STATUS

      type(ESMF_FIELD)                       :: FIELD
      integer                                :: YEAR, MONTH, DAY
      character(len=ESMF_MAXSTR)             :: TIMESTAMP

      call ESMF_StateGetField (STATE, FIELDNAME, FIELD, RC=STATUS )
      VERIFY_(STATUS)
      call MAPL_FieldGetTime  (FIELD, TIME,             RC=STATUS)
      VERIFY_(STATUS)

      RETURN_(ESMF_SUCCESS)
    end subroutine  MAPL_GetFieldTimeFromState

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


    subroutine  MAPL_SetFieldTimeFromState ( STATE, Fieldname, TIME, RC ) 1
      type(ESMF_STATE),        intent(INOUT) :: STATE
      character(len=*),        intent(IN   ) :: Fieldname
      type(ESMF_Time),         intent(IN   ) :: TIME
      integer, optional,       intent(  OUT) :: RC

      character(len=ESMF_MAXSTR),parameter   :: IAm=" MAPL_SetFieldTimeFromState"
      integer                                :: STATUS

      type(ESMF_FIELD)                       :: FIELD
      integer                                :: YEAR, MONTH, DAY
      character(len=ESMF_MAXSTR)             :: TIMESTAMP

      call ESMF_StateGetField (STATE, FIELDNAME, FIELD, RC=STATUS)
      VERIFY_(STATUS)
      call MAPL_FieldSetTime  (FIELD, TIME,             RC=STATUS)
      VERIFY_(STATUS)

      RETURN_(ESMF_SUCCESS)
    end subroutine  MAPL_SetFieldTimeFromState



    function MAPL_FieldCreateRename(FIELD, NAME, RC) RESULT(F),1
      type (ESMF_Field), intent(IN   ) :: FIELD
      character(len=*),  intent(IN   ) :: NAME
      integer, optional, intent(  OUT) :: RC
      type (ESMF_Field)                :: F
      type (ESMF_DataType)             :: dt
      type (ESMF_DataKind)             :: dk

!   we are creating new field so that we can change the name of the field;
!   the important thing is that the data (ESMF_Array) and the grid (ESMF_Grid) 
!   are the SAME as the one in the original Field

      type(ESMF_FieldDataMap) :: datamap           
      type(ESMF_RelLoc)       :: relloc
      type(ESMF_Grid)         :: grid
      type(ESMF_Array)        :: array
      character(len=ESMF_MAXSTR)       :: attname
      integer                 :: status
      character(len=ESMF_MAXSTR), parameter :: Iam='MAPL_FieldCreateRename'

!ALT added kludge (next 6 lines)
      call ESMF_FieldGet(FIELD, name=attname, RC=STATUS)
      VERIFY_(STATUS)
      if (NAME == attname) then
         F = FIELD
         RETURN_(ESMF_SUCCESS)
      endif
      call ESMF_FieldGet(FIELD, grid=GRID, RC=STATUS)
      VERIFY_(STATUS)
      call ESMF_FieldGet(FIELD, datamap=DATAMAP, RC=STATUS)
      VERIFY_(STATUS)
      call ESMF_FieldGet(FIELD,  horzRelLoc=RELLOC, RC=STATUS)
      VERIFY_(STATUS)
      call ESMF_FieldGetArray(FIELD, Array, RC=STATUS)
      VERIFY_(STATUS)
      
      F = ESMF_FieldCreate(GRID, ARRAY,          &
           datamap = datamap,                        &
           horzRelloc = relloc,                      &
           name  = NAME,            RC=STATUS )
      VERIFY_(STATUS)

      call MAPL_FieldCopyAttributes(FIELD_IN=field, FIELD_OUT=f, RC=status)
      VERIFY_(STATUS)

      RETURN_(ESMF_SUCCESS)
    end function MAPL_FieldCreateRename


    function MAPL_FieldCreateRegrid(FIELD, GRID, RC) RESULT(F),1
      type (ESMF_Field), intent(IN   ) :: FIELD
      type (ESMF_Grid),  intent(IN   ) :: GRID
      integer, optional, intent(  OUT) :: RC
      type (ESMF_Field)                :: F
      type (ESMF_DataType)             :: dt
      type (ESMF_DataKind)             :: dk

!   we are creating new field so that we can change the grid of the field 
!   (and allocate array accordingly);

      type(ESMF_FieldDataMap) :: datamap           
      type(ESMF_RelLoc)       :: hrelloc
      type(ESMF_RelLoc)       :: vrelloc
      type(ESMF_Array)        :: array
      integer                 :: rank
      integer                 :: COUNTS(3)
      real, pointer           :: VAR_1D(:), VAR_2D(:,:), VAR_3D(:,:,:)
      character(len=ESMF_MAXSTR) :: NAME
      integer                 :: status
      integer                 :: DIMS
      character(len=ESMF_MAXSTR), parameter :: Iam='MAPL_FieldCreateRegrid'

      call ESMF_FieldGet(FIELD, name=name, RC=STATUS)
      VERIFY_(STATUS)
      call ESMF_FieldGet(FIELD, datamap=DATAMAP, RC=STATUS)
      VERIFY_(STATUS)
      call ESMF_FieldGet(FIELD,  horzRelLoc=HRELLOC, vertRelLoc=VRELLOC, RC=STATUS)
      VERIFY_(STATUS)
      call ESMF_FieldGetArray(FIELD, Array, RC=STATUS)
      VERIFY_(STATUS)

      call ESMF_GridGetDELocalInfo(GRID, &
           horzRelLoc=ESMF_CELL_CENTER, &
           vertRelLoc=ESMF_CELL_CELL, &
           localCellCountPerDim=COUNTS,RC=STATUS)
      VERIFY_(STATUS)

      call ESMF_ArrayGet(array, rank=rank, rc=status)
      VERIFY_(STATUS)

      if (rank == 1) then
         rank = 2
         call ESMF_FieldDataMapSetDefault(datamap, rank, rc=status)
         VERIFY_(STATUS)
      end if

      if (rank == 2) then
!ALT halowidth assumed 0
         allocate(VAR_2D(COUNTS(1), COUNTS(2)), STAT=STATUS)
         VERIFY_(STATUS)
         ARRAY = ESMF_ArrayCreate(VAR_2D, ESMF_DATA_REF, RC=STATUS)
         VERIFY_(STATUS)
         DIMS = MAPL_DimsHorzOnly
      else
!ALT halowidth assumed 0
         allocate(VAR_3D(COUNTS(1), COUNTS(2), COUNTS(3)), STAT=STATUS)
         VERIFY_(STATUS)
         ARRAY = ESMF_ArrayCreate(VAR_3D, ESMF_DATA_REF, RC=STATUS)
         VERIFY_(STATUS)
         DIMS = MAPL_DimsHorzVert
      end if

      F = ESMF_FieldCreate(GRID, ARRAY,          &
           datamap = datamap,                        &
           horzRelloc = hrelloc,                     &
           vertRelloc = vrelloc,                     &
           name  = NAME,            RC=STATUS )
      VERIFY_(STATUS)

      call MAPL_FieldCopyAttributes(FIELD_IN=field, FIELD_OUT=f, RC=status)
      VERIFY_(STATUS)
! Overwrite DIMS attribute
      call ESMF_FieldSetAttribute(F, NAME='DIMS', VALUE=DIMS, RC=STATUS)
      VERIFY_(STATUS)

      RETURN_(ESMF_SUCCESS)
    end function MAPL_FieldCreateRegrid


    subroutine MAPL_FieldCopyAttributes(FIELD_IN, FIELD_OUT, RC) 2
      type (ESMF_Field), intent(IN   ) :: FIELD_IN
      type (ESMF_Field), intent(INOUT) :: FIELD_OUT
      integer, optional, intent(  OUT) :: RC

      type (ESMF_DataType)             :: dt
      type (ESMF_DataKind)             :: dk
      integer                          :: status
      character(len=ESMF_MAXSTR), parameter :: Iam='MAPL_FieldCopyAttributes'
      integer                          :: i, n, count
      character(len=ESMF_MAXSTR)       :: attname
      character(len=ESMF_MAXSTR)       :: att
      integer, pointer                 :: iptr(:)
      type(ESMF_Logical), pointer      :: lptr(:)
      real,    pointer                 :: rptr(:)

      call ESMF_FieldGetAttributeCount(field_in, count=n, rc=status)
      VERIFY_(STATUS)

      do i = 1, n
         call  ESMF_FieldGetAttributeInfo(field_in, attributeIndex=i, name=attname, &
                                          datatype=dt, datakind=dk, count=count, rc=status)
         VERIFY_(STATUS)

         if (dt == ESMF_Data_Integer) then
            allocate(iptr(count), stat=status)
            VERIFY_(STATUS)
            call ESMF_FieldGetAttribute(field_in,  NAME=attname, count=count, VALUELIST=iptr, RC=STATUS)
            VERIFY_(STATUS)
            call ESMF_FieldSetAttribute(field_out, NAME=attname, count=count, VALUELIST=iptr, RC=STATUS)
            VERIFY_(STATUS)
            deallocate(iptr)

         else if (dt == ESMF_Data_Logical) then
            allocate(lptr(count), stat=status)
            VERIFY_(STATUS)
            call ESMF_FieldGetAttribute(field_in,  NAME=attname, count=count, VALUELIST=lptr, RC=STATUS)
            VERIFY_(STATUS)
            call ESMF_FieldSetAttribute(field_out, NAME=attname, count=count, VALUELIST=lptr, RC=STATUS)
            VERIFY_(STATUS)
            deallocate(lptr)

         else if (dt == ESMF_Data_Real) then
            allocate(rptr(count), stat=status)
            VERIFY_(STATUS)
            call ESMF_FieldGetAttribute(field_in,  NAME=attname, count=count, VALUELIST=rptr, RC=STATUS)
            VERIFY_(STATUS)
            call ESMF_FieldSetAttribute(field_out, NAME=attname, count=count, VALUELIST=rptr, RC=STATUS)
            VERIFY_(STATUS)
            deallocate(rptr)

         else if (dt == ESMF_Data_Character) then
            call ESMF_FieldGetAttribute(field_in,  NAME=attname, VALUE=att, RC=STATUS)
            VERIFY_(STATUS)
            call ESMF_FieldSetAttribute(field_out, NAME=attname, VALUE=att, RC=STATUS)
            VERIFY_(STATUS)

         end if
      end do
      RETURN_(ESMF_SUCCESS)
    end subroutine MAPL_FieldCopyAttributes

!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

      function MAPL_RemapBounds_3dr4(A,I1,IM,J1,JM,L1,LM)
        integer,      intent(IN) :: I1,IM,J1,JM,L1,LM
        real, target, intent(IN) :: A(I1:IM,J1:JM,L1:LM)
        real, pointer            :: MAPL_RemapBounds_3dr4(:,:,:)

        MAPL_RemapBounds_3dr4 => A
      end function MAPL_RemapBounds_3dr4

end module MAPL_BaseMod