!   $Id: GEOS_TurbulenceGridComp.F90,v 1.88.2.3.2.1.2.2.2.6 2007/10/03 19:44:02 f4mjs Exp $

#include "MAPL_Generic.h"

!=============================================================================


module GEOS_TurbulenceGridCompMod 1,1

!BOP

!  !MODULE: GEOS_Turbulence --- An GEOS generic atmospheric turbulence component

! !USES:

  use ESMF_Mod
  use GEOS_Mod
  use LockEntrain
  
  implicit none
  private

! !PUBLIC MEMBER FUNCTIONS:

  public SetServices

! !DESCRIPTION:
! 
!   {\tt GEOS\_TurbulenceGridComp} computes atmospheric tendencies due to turbulence.
!   Its physics is a combination of the first-order scheme of Louis---for stable PBLs
!   and free atmospheric turbulence---with a modified version of the non-local-K
!   scheme proposed by Lock for unstable and cloud-topped boundary layers.
!   In addition to diffusive tendencies, it adds the effects orographic form drag
!   for features with horizontal scales of 2 to 20 km following Beljaars et al. (2003,
!   ECMWF Tech. Memo. 427).  
!
!\vspace{12 pt}
!\noindent
!{\bf Grid Considerations}
!
!   Like all GEOS\_Generic-based components, it works on an inherited 
!   3-dimensional ESMF grid. It assumes that the first two (inner) dimensions span the
!   horizontal and the third (outer) dimension is the vertical. In the horizontal,
!   one or both dimensions can be degenerate, effectively supporting 
!   single-columns (1-D), and slices (2-D). No horizontal dimension needs to be
!   aligned with a particular coordinate. In the vertical, the only assumption
!   is that columns are indexed from top to bottom.
!
!\vspace{12 pt}
!\noindent
!{\bf Methods}
!
!   {\tt GEOS\_TurbulenceGridComp} uses the default Initialize and Finalize methods
!   of GEOS\_Generic. It has a 2-stage Run method that can be used in conjunction with
!   two-stage surface calculations to implement semi-implicit time differencing.
!
!\vspace{12 pt}
!\noindent
!{\bf Time Behavior}
!
!   {\tt GEOS\_TurbulenceGridComp} assumes both run stages will be invoked every 
!   RUN\_DT seconds, where RUN\_DT is required in the configuration. On this interval
!   both run stages will perform diffusion updates using diffusivities found in the
!   internal state.  The diffusivities in the internal state may be refreshed intermitently
!   by specifying MY\_STEP and ACCUMINT in the configuration. Accumulated imports used
!   in the intermittent refreshing are valid only on MY\_STEP intervals. Currently the
!   origin of these intervals is the beginning of the run. Accumulation of these imports
!   is done for a period ACCUMINT prior to the valid time. Both ACCUMINT and MY\_STEP are
!   in seconds.
!
!\vspace{12 pt}
!\noindent
!{\bf Working with Bundles and Friendlies}
!
!   {\tt GEOS\_TurbulenceGridComp} works on bundles of quantities to be diffused
!   and with corresponding bundles of their tendencies, surface values, etc.
!   These bundles may contain an arbitrary number of conservative quantities and
!   no requirements or restrictions are placed on what quantities they contain.
!   Quantities required for the calculation, such as pressures, stability, etc
!   are passed separately from the diffused quantities. Little distinction is made
!   of what is in the bundle, except that needed to decide what diffusivity applies
!   to the quantity and in what form its effects are implemented.
!
!   Quantities to be diffused can be marked as "Friendly-for-diffusion". In that case,
!   {\tt GEOS\_TurbulenceGridComp} directly updates the quantity; otherwise it 
!   merely computes its tendency, placing it in the appropriate bundle and treating
!   the quantity itself as read-only.
!
!   In working with bundled quantities, corresponding fields must appear in the 
!   same order in all bundles. Some of these fields, however, 
!   may be ``empty'' in the sense that the data pointer has not been allocated.
!   
!   {\tt GEOS\_TurbulenceGridComp} works with six bundles; three in the import
!   state and three in the export state. The import bundles are:
! \begin{itemize}
!   \item[]
!   \makebox[1in][l]{\bf TR} 
!   \parbox[t]{4in}{The quantity being diffused.}
!   \item[]
!   \makebox[1in][l]{\bf TRG} 
!   \parbox[t]{4in}{The surface (ground) value of the quantity being diffused.
!                   (Used only by Run2)}
!   \item[]
!   \makebox[1in][l]{\bf DTG} 
!   \parbox[t]{4in}{The change of TRG during the time step. (Used only by Run2)}
! \end{itemize}
!
!   The export bundles are:
! \begin{itemize}
!   \item[]
!   \makebox[1in][l]{\bf TRI} 
!   \parbox[t]{4in}{The tendency of the quantity being diffused.
!                   (Produced by Run1, updated by Run2.)  }
!   \item[]
!   \makebox[1in][l]{\bf FSTAR} 
!   \parbox[t]{4in}{After Run1, the ``preliminary'' (i.e., at the original surface
!    value) surface flux of the diffused quantity; after Run2, its final value.
!    (Produced by Run1, updated by Run2)}
!   \item[]
!   \makebox[1in][l]{\bf DFSTAR} 
!   \parbox[t]{4in}{The change of preliminary FSTAR per unit change in the 
!                   surface value. (Produced by Run1)}
! \end{itemize}
!
!   All fields in the export bundles are checked for associated pointers before being
!   updated.
!
!   Fields in the TR bundle can have four attributes:
! \begin{itemize}
! \item FriendlyTo[{\it Component Name}]: default=false --- If true, TR field is updated.
! \item WeightedTendency: default=true --- If true, tendencies (TRI) are pressure-weighted
! \item DiffuseLike: ('S','Q','M') default='S' --- Use mixing coefficients for either
!          heat, moisture or momentum.
! \end{itemize}
!  
!   Only fields in the TR bundle are checked for friendly status. Non-friendly
!   fields in TR and all other bundles are treated with the usual Import/Export
!   rules.
!
!\vspace{12 pt}
!\noindent
!{\bf Other imports and exports}
!
!   In addition to the updates of these bundles, {\tt GEOS\_TurbulenceGridComp} produces
!   a number of diagnostic exports, as well as frictional heating contributions. The latter 
!   are NOT added by {\tt GEOS\_TurbulenceGridComp}, but merely exported to be added
!   elsewhere in the GCM.
!
!\vspace{12 pt}
!\noindent
!{\bf Two-Stage Interactions with the Surface}
!
!   The two-stage scheme for interacting with the surface module is as follows:
! \begin{itemize}
!   \item  The first run stage takes the surface values of the diffused quantities
!      and the surface exchange coefficients as input. These are, of course, on the 
!      grid turbulence is working on.
!   \item  It then does the full diffusion calculation assuming the surface values are
!      fixed, i.e., the explicit surface case. In addition, it also computes derivatives of the
!      tendencies wrt surface values. These are to be used in the second stage.
!   \item The second run stage takes the increments of the surface values as inputs
!      and produces the final results, adding the implicit surface contributions. 
!   \item It also computes the frictional heating due to both implicit and explicit
!       surface contributions.
! \end{itemize}
!
!\vspace{12 pt}
!\noindent
!{\bf GEOS-5 Specific Aspects}
!
!   In GEOS-5, {\tt GEOS\_TurbulenceGridComp} works on the atmosphere's lat-lon grid,
!   while surface quantities are computed during the first run stage of the each of
!   the tiled surface components.  The tiled quantities are properly aggregated to
!   the GEOS-5 lat-lon grid by the first stage of {\tt GEOS\_SurfaceGridComp}, which
!   is called immediately before the first run stage of {\tt GEOS\_TurbulenceGridComp}.
!
!EOP

contains

!=============================================================================
!=============================================================================
!=============================================================================
!=============================================================================

!BOP

! !IROUTINE: SetServices -- Sets ESMF services for this component

! !DESCRIPTION: This version uses the {\tt GEOS\_GenericSetServices}, which sets
!               the Initialize and Finalize services to generic versions. It also
!   allocates our instance of a generic state and puts it in the 
!   gridded component (GC). Here we only set the two-stage run method and
!   declare the data services.
! \newline
! !REVISION HISTORY: 
!   ??Jul2006 E.Novak./Todling - Added output defining TLM/ADM trajectory

! !INTERFACE:


  subroutine SetServices ( GC, RC ),1759

! !ARGUMENTS:

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

!=============================================================================
!
! ErrLog Variables

    character(len=ESMF_MAXSTR)              :: IAm
    integer                                 :: STATUS
    character(len=ESMF_MAXSTR)              :: COMP_NAME

! Local derived type aliases

    type (ESMF_Config          )            :: CF

! Locals

    integer      :: MY_STEP
    integer      :: ACCUMINT
    real         :: DT

!=============================================================================

! Begin...

! Get my name and set-up traceback handle
! ---------------------------------------

    Iam = 'SetServices'
    call ESMF_GridCompGet( GC, NAME=COMP_NAME, RC=STATUS )
    VERIFY_(STATUS)
    Iam = trim(COMP_NAME) // Iam

! Set the Run entry points
! ------------------------

    call MAPL_GridCompSetEntryPoint ( GC, ESMF_SETRUN,  Run1, RC=STATUS )
    VERIFY_(STATUS)
    call MAPL_GridCompSetEntryPoint ( GC, ESMF_SETRUN,  Run2, RC=STATUS )
    VERIFY_(STATUS)

! Get the intervals
! -----------------

    call ESMF_GridCompGet( GC, CONFIG = CF, RC=STATUS )
    VERIFY_(STATUS)

    call ESMF_ConfigGetAttribute( CF, DT, Label="RUN_DT:"                           , RC=STATUS)
    VERIFY_(STATUS)
    call ESMF_ConfigGetAttribute( CF, DT, Label=trim(COMP_NAME)//"_DT:" , default=DT, RC=STATUS)
    MY_STEP  = nint(DT)
    call ESMF_ConfigGetAttribute( CF, DT, Label=trim(COMP_NAME)//"Avrg:", default=DT, RC=STATUS)
    ACCUMINT = nint(DT)

! Set the state variable specs.
! -----------------------------

!BOP
! !IMPORT STATE:

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME = 'PLE',                                       &
        LONG_NAME  = 'air_pressure',                              &
        UNITS      = 'Pa',                                        &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationEdge,                          &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

      call MAPL_AddImportSpec(GC,                             &
         SHORT_NAME = 'T',                                         &
         LONG_NAME  = 'air_temperature',                           &
         UNITS      = 'K',                                         &
         DIMS       = MAPL_DimsHorzVert,                           &
         VLOCATION  = MAPL_VLocationCenter,                        &
         AVERAGING_INTERVAL = ACCUMINT,                            &
         REFRESH_INTERVAL   = MY_STEP,                             &
                                                        RC=STATUS  )
      VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME = 'TH',                                        &
        LONG_NAME  = 'potential_temperature',                     &
        UNITS      = 'K',                                         &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationCenter,                        &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME = 'QV',                                        &
        LONG_NAME  = 'specific_humidity',                         &
        UNITS      = '1',                                         &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationCenter,                        &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME = 'QLLS',                                      &
        LONG_NAME  = 'liquid_condensate_mixing_ratio',            &
        UNITS      = '1',                                         &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationCenter,                        &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME = 'QILS',                                      &
        LONG_NAME  = 'frozen_condensate_mixing_ratio',            &
        UNITS      = '1',                                         &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationCenter,                        &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME = 'CLLS',                                      &
        LONG_NAME  = 'cloud_fraction',                            &
        UNITS      = '1',                                         &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationCenter,                        &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME = 'QLCN',                                      &
        LONG_NAME  = 'liquid_condensate_mixing_ratio',            &
        UNITS      = '1',                                         &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationCenter,                        &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME = 'QICN',                                      &
        LONG_NAME  = 'frozen_condensate_mixing_ratio',            &
        UNITS      = '1',                                         &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationCenter,                        &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME = 'CLCN',                                      &
        LONG_NAME  = 'cloud_fraction',                            &
        UNITS      = '1',                                         &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationCenter,                        &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME = 'U',                                         &
        LONG_NAME  = 'eastward_wind',                             &
        UNITS      = 'm s-1',                                     &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationCenter,                        &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME = 'V',                                         &
        LONG_NAME  = 'northward_wind',                            &
        UNITS      = 'm s-1',                                     &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationCenter,                        &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'CT',                                &
        LONG_NAME          = 'surface_heat_exchange_coefficient', &
        UNITS              = 'kg m-2 s-1',                        &
        DIMS               = MAPL_DimsHorzOnly,                   &
        VLOCATION          = MAPL_VLocationNone,                  &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'CQ',                                &
        LONG_NAME          = 'surface_moisture_exchange_coefficient', &
        UNITS              = 'kg m-2 s-1',                        &
        DIMS               = MAPL_DimsHorzOnly,                   &
        VLOCATION          = MAPL_VLocationNone,                  &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'CM',                                &
        LONG_NAME          = 'surface_momentum_exchange_coefficient', &
        UNITS              = 'kg m-2 s-1',                        &
        DIMS               = MAPL_DimsHorzOnly,                   &
        VLOCATION          = MAPL_VLocationNone,                  &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'BSTAR',                             &
        LONG_NAME          = 'surface_bouyancy_scale',            &
        UNITS              = 'm s-2',                             &
        DIMS               = MAPL_DimsHorzOnly,                   &
        VLOCATION          = MAPL_VLocationNone,                  &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'USTAR',                             &
        LONG_NAME          = 'surface_velocity_scale',            &
        UNITS              = 'm s-1',                             &
        DIMS               = MAPL_DimsHorzOnly,                   &
        VLOCATION          = MAPL_VLocationNone,                  &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'FRLAND',                            &
        LONG_NAME          = 'land_fraction',                     &
        UNITS              = '1',                                 &
        DIMS               = MAPL_DimsHorzOnly,                   &
        VLOCATION          = MAPL_VLocationNone,                  &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'RADLW',                             &
        LONG_NAME          = 'air_temperature_tendency_due_to_longwave',&
        UNITS              = 'K s-1',                             &
        DIMS               = MAPL_DimsHorzVert,                   &
        VLOCATION          = MAPL_VLocationCenter,                &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'RADLWC',                            &
        LONG_NAME          = 'clearsky_air_temperature_tendency_lw',&
        UNITS              = 'K s-1',                             &
        DIMS               = MAPL_DimsHorzVert,                   &
        VLOCATION          = MAPL_VLocationCenter,                &
        AVERAGING_INTERVAL = ACCUMINT,                            &
        REFRESH_INTERVAL   = MY_STEP,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'PREF',                              &
        LONG_NAME          = 'reference_air_pressure',            &
        UNITS              = 'Pa',                                &
        DIMS               = MAPL_DimsVertOnly,                   &
        VLOCATION          = MAPL_VLocationEdge,                  &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'VARFLT',                            &
        LONG_NAME          = 'variance_of_filtered_topography',   &
        UNITS              = 'm+2',                               &
        DIMS               = MAPL_DimsHorzOnly,                   &
        VLOCATION          = MAPL_VLocationNone,                  &
                                                       RC=STATUS  )
     VERIFY_(STATUS)


     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'TR',                                &
        LONG_NAME          = 'diffused_quantities',               &
        UNITS              = 'X',                                 &
        DIMS               = MAPL_DimsHorzVert,                   &
        VLOCATION          = MAPL_VLocationCenter,                &
        DATATYPE           = MAPL_BundleItem,                     &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'TRG',                               &
        LONG_NAME          = 'surface_values_of_diffused_quantity',&
        UNITS              = 'X',                                 &
        DIMS               = MAPL_DimsHorzOnly,                   &
        VLOCATION          = MAPL_VLocationNone,                  &
        DATATYPE           = MAPL_BundleItem,                     &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddImportSpec(GC,                             &
        SHORT_NAME         = 'DTG',                               &
        LONG_NAME          = 'change_of_surface_values_of_diffused_quantity',&
        UNITS              = 'X',                                 &
        DIMS               = MAPL_DimsHorzOnly,                   &
        VLOCATION          = MAPL_VLocationNone,                  &
        DATATYPE           = MAPL_BundleItem,                     &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

! !EXPORT STATE:

     call MAPL_AddExportSpec(GC,                             &
        SHORT_NAME = 'TRI',                                       &
        LONG_NAME  = 'diffusion_tendencies',                      &
        UNITS      = 'X kg m-2 s-1',                              &
        DIMS       = MAPL_DimsHorzVert,                           &
        VLOCATION  = MAPL_VLocationCenter,                        &
        DATATYPE   = MAPL_BundleItem,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddExportSpec(GC,                             &
        SHORT_NAME = 'FSTAR',                                     &
        LONG_NAME  = 'surface_fluxes',                            &
        UNITS      = 'X kg m-2 s-1',                              &
        DIMS       = MAPL_DimsHorzOnly,                           &
        VLOCATION  = MAPL_VLocationNone,                          &
        DATATYPE   = MAPL_BundleItem,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

     call MAPL_AddExportSpec(GC,                             &
        SHORT_NAME = 'DFSTAR',                                    &
        LONG_NAME  = 'change_of_surface_fluxes_for_unit_change_of_surface_value',&
        UNITS      = 'kg m-2 s-1',                                &
        DIMS       = MAPL_DimsHorzOnly,                           &
        VLOCATION  = MAPL_VLocationNone,                          &
        DATATYPE   = MAPL_BundleItem,                             &
                                                       RC=STATUS  )
     VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'air_temperature',                                       &
       UNITS      = 'K',                                                     &
       SHORT_NAME = 'T',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'eastward_wind',                                         &
       UNITS      = 'm/s',                                                   &
       SHORT_NAME = 'U',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'northward_wind',                                        &
       UNITS      = 'm/s',                                                   &
       SHORT_NAME = 'V',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'specific_humidity',                                     &
       UNITS      = '1',                                                     &
       SHORT_NAME = 'QV',                                                    &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'total_momentum_diffusivity',                            &
       UNITS      = 'm+2 s-1',                                               &
       SHORT_NAME = 'KM',                                                    &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationEdge,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'total_scalar_diffusivity',                              &
       UNITS      = 'm+2 s-1',                                               &
       SHORT_NAME = 'KH',                                                    &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationEdge,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'Richardson_number_from_Louis',                          &
       UNITS      = '1',                                                     &
       SHORT_NAME = 'RI',                                                    &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationEdge,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'bulk_shear_from_Louis',                                 &
       UNITS      = 's-1',                                                   &
       SHORT_NAME = 'DU',                                                    &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationEdge,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'scalar_diffusivity_from_Louis',                         &
       UNITS      = 'm+2 s-1',                                               &
       SHORT_NAME = 'KHLS',                                                  &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationEdge,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'momentum_diffusivity_from_Louis',                       &
       UNITS      = 'm+2 s-1',                                               &
       SHORT_NAME = 'KMLS',                                                  &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationEdge,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'surface_driven_scalar_diffusivity_from_Lock_scheme',    &
       UNITS      = 'm+2 s-1',                                               &
       SHORT_NAME = 'KHSFC',                                                 &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationEdge,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'radiation_driven_scalar_diffusivity_from_Lock_scheme',  &
       UNITS      = 'm+2 s-1',                                               &
       SHORT_NAME = 'KHRAD',                                                 &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationEdge,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'cloudy_LW_radiation_tendency_used_by_Lock_scheme',      &
       UNITS      = 'K s-1',                                                 &
       SHORT_NAME = 'LWCRT',                                                 &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'entrainment_heat_diffusivity_from_Lock',                &
       UNITS      = 'm+2 s-1',                                               &
       SHORT_NAME = 'EKH',                                                   &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationEdge,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'entrainment_momentum_diffusivity_from_Lock',            &
       UNITS      = 'm+2 s-1',                                               &
       SHORT_NAME = 'EKM',                                                   &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationEdge,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'Blackadar_length_scale_for_scalars',                    &
       UNITS      = 'm',                                                     &
       SHORT_NAME = 'ALH',                                                   &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationEdge,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'p-weighted_frictional_heating_rate_from_diffusion',     &
       UNITS      = 'K s-1 Pa',                                              &
       SHORT_NAME = 'INTDIS',                                                &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'p-weighted_frictional_heating_rate_from_orographic_drag',&
       UNITS      = 'K s-1 Pa',                                              &
       SHORT_NAME = 'TOPDIS',                                                &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'p-weighted_frictional_heating_rate_from_surface_drag',  &
       UNITS      = 'K s-1 Pa',                                              &
       SHORT_NAME = 'SRFDIS',                                                &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec ( gc,                            &
         SHORT_NAME = 'KETRB',                                    &
         LONG_NAME  = 'vertically_integrated_kinetic_energy_tendency_across_turbulence',&
         UNITS      = 'W m-2',                                    &
         DIMS       = MAPL_DimsHorzOnly,                          &
         VLOCATION  = MAPL_VLocationNone,              RC=STATUS  )
     VERIFY_(STATUS)

    call MAPL_AddExportSpec ( gc,                            &
         SHORT_NAME = 'KESRF',                                    &
         LONG_NAME  = 'vertically_integrated_kinetic_energy_dissipation_due_to_surface_friction',&
         UNITS      = 'W m-2',                                    &
         DIMS       = MAPL_DimsHorzOnly,                          &
         VLOCATION  = MAPL_VLocationNone,              RC=STATUS  )
     VERIFY_(STATUS)

    call MAPL_AddExportSpec ( gc,                            &
         SHORT_NAME = 'KEINT',                                    &
         LONG_NAME  = 'vertically_integrated_kinetic_energy_dissipation_due_to_diffusion',&
         UNITS      = 'W m-2',                                    &
         DIMS       = MAPL_DimsHorzOnly,                          &
         VLOCATION  = MAPL_VLocationNone,              RC=STATUS  )
     VERIFY_(STATUS)

    call MAPL_AddExportSpec ( gc,                            &
         SHORT_NAME = 'KETOP',                                    &
         LONG_NAME  = 'vertically_integrated_kinetic_energy_dissipation_due_to_topographic_friction',&
         UNITS      = 'W m-2',                                    &
         DIMS       = MAPL_DimsHorzOnly,                          &
         VLOCATION  = MAPL_VLocationNone,              RC=STATUS  )
     VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'entrainment_velocity_from_surface_plume',               &
       UNITS      = 'm s-1',                                                 &
       SHORT_NAME = 'WESFC',                                                 &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'entrainment_velocity_from_radiation',                   &
       UNITS      = 'm s-1',                                                 &
       SHORT_NAME = 'WERAD',                                                 &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'entrainment_velocity_from_buoy_rev',                    &
       UNITS      = 'm s-1',                                                 &
       SHORT_NAME = 'WEBRV',                                                 &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'Buoyancy_jump_across_inversion',                        &
       UNITS      = 'm s-2',                                                 &
       SHORT_NAME = 'DBUOY',                                                 &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'turbulent_velocity_scale_for_sfc',                      &
       UNITS      = 'm s-1',                                                 &
       SHORT_NAME = 'VSCSFC',                                                &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'turbulent_velocity_scale_for_cooling',                  &
       UNITS      = 'm s-1',                                                 &
       SHORT_NAME = 'VSCRAD',                                                &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'turbulent_velocity_scale_for_buoy_rev',                 &
       UNITS      = 'm s-1',                                                 &
       SHORT_NAME = 'VSCBRV',                                                &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'turbulent_entrainment_diff_from_cooling',               &
       UNITS      = 'm+2 s-1',                                               &
       SHORT_NAME = 'KERAD',                                                 &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'cloud_top_radiative_forcing',                           &
       UNITS      = 'W m-2',                                                 &
       SHORT_NAME = 'CLDRF',                                                 &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)


    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'pbltop_height_as_diagnosed_from_KH',                    &
       UNITS      = 'm',                                                     &
       SHORT_NAME = 'ZPBL',                                                  &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'pbltop_pressure',                                       &
       UNITS      = 'Pa',                                                    &
       SHORT_NAME = 'PPBL',                                                  &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'pbltop_height_for_sfc_plume_LOCK',                      &
       UNITS      = 'm',                                                     &
       SHORT_NAME = 'ZSML',                                                  &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'depth_for_rad/brv_plume_LOCK',                          &
       UNITS      = 'm',                                                     &
       SHORT_NAME = 'ZRADML',                                                &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'hght_of_base_for_rad/brv_plume_LOCK',                   &
       UNITS      = 'm',                                                     &
       SHORT_NAME = 'ZRADBS',                                                &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'pbltop_cloud_depth_LOCK',                               &
       UNITS      = 'm',                                                     &
       SHORT_NAME = 'ZCLD',                                                  &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'pbltop_cloud_top_height_LOCK',                          &
       UNITS      = 'm',                                                     &
       SHORT_NAME = 'ZCLDTOP',                                               &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'optimal_mixture_fraction_for_BRV',                      &
       UNITS      = '1',                                                     &
       SHORT_NAME = 'CHIS',                                                  &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 's_of_optimal_mixture_for_BRV',                          &
       UNITS      = 'J kg-1',                                                &
       SHORT_NAME = 'SMIXT',                                                 &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'Scaled_Del_s_at_Cloud_top',                             &
       UNITS      = 'K',                                                     &
       SHORT_NAME = 'DELSINV',                                               &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'Siems_buoy_rev_parameter',                              &
       UNITS      = '1',                                                     &
       SHORT_NAME = 'DSIEMS',                                                &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'Return_codes_for_Lock_top_driven_plume',                &
       UNITS      = '1',                                                     &
       SHORT_NAME = 'RADRCODE',                                              &
       DIMS       = MAPL_DimsHorzOnly,                                       &
       VLOCATION  = MAPL_VLocationNone,                                      &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_ak_for_scalars_over_dt',                &
       SHORT_NAME = 'AKSODT',                                                &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_ck_for_scalars_over_dt',                &
       SHORT_NAME = 'CKSODT',                                                &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_ak_for_moisture_over_dt',               &
       SHORT_NAME = 'AKQODT',                                                &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_ck_for_moisture_over_dt',               &
       SHORT_NAME = 'CKQODT',                                                &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_ak_for_winds_over_dt',                  &
       SHORT_NAME = 'AKVODT',                                                &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddExportSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_ck_for_winds_over_dt',                  &
       SHORT_NAME = 'CKVODT',                                                &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)


! !INTERNAL STATE:

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_ahat_for_scalars',                      &
       SHORT_NAME = 'AKS',                                                   &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_bhat_for_scalars',                      &
       SHORT_NAME = 'BKS',                                                   &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_c_for_scalars',                         &
       SHORT_NAME = 'CKS',                                                   &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'sensitivity_of_tendency_to_surface_value_for_scalars',  &
       SHORT_NAME = 'DKS',                                                   &
       UNITS      = 's-1',                                                   &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_ahat_for_moisture',                     &
       SHORT_NAME = 'AKQ',                                                   &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_bhat_for_moisture',                     &
       SHORT_NAME = 'BKQ',                                                   &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_c_for_moisture',                        &
       SHORT_NAME = 'CKQ',                                                   &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'sensitivity_of_tendency_to_surface_value_for_moisture', &
       SHORT_NAME = 'DKQ',                                                   &
       UNITS      = 's-1',                                                   &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_ahat_for_winds',                        &
       SHORT_NAME = 'AKV',                                                   &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_bhat_for_winds',                        &
       SHORT_NAME = 'BKV',                                                   &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'matrix_diagonal_c_for_winds',                           &
       SHORT_NAME = 'CKV',                                                   &
       UNITS      = '1',                                                     &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'sensitivity_of_tendency_to_surface_value_for_winds',    &
       SHORT_NAME = 'DKV',                                                   &
       UNITS      = 's-1',                                                   &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'momentum_mixing_factor',                                &
       SHORT_NAME = 'EKV',                                                   &
       UNITS      = 'Pa s-1',                                                &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)

    call MAPL_AddInternalSpec(GC,                                               &
       LONG_NAME  = 'topographic_roughness_factor',                          &
       SHORT_NAME = 'FKV',                                                   &
       UNITS      = 'Pa s-1',                                                &
       DIMS       = MAPL_DimsHorzVert,                                       &
       VLOCATION  = MAPL_VLocationCenter,                                    &
       DATATYPE   = MAPL_NoRestart,                                          &
                                                                  RC=STATUS  )
    VERIFY_(STATUS)


!EOP

! Set the Profiling timers
! ------------------------

    call MAPL_TimerAdd(GC,   name="-RUN1"       ,RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_TimerAdd(GC,   name="--DIFFUSE"   ,RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_TimerAdd(GC,   name="--REFRESHKS" ,RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_TimerAdd(GC,   name="---PRELIMS"  ,RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_TimerAdd(GC,   name="---LOUIS"    ,RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_TimerAdd(GC,   name="---LOCK"     ,RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_TimerAdd(GC,   name="---BELJAARS" ,RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_TimerAdd(GC,   name="---DECOMP"   ,RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_TimerAdd(GC,   name="-RUN2"       ,RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_TimerAdd(GC,   name="--UPDATE"    ,RC=STATUS)
    VERIFY_(STATUS)
    
! Set generic init and final methods
! ----------------------------------

    call MAPL_GenericSetServices    ( GC, RC=STATUS)
    VERIFY_(STATUS)

    RETURN_(ESMF_SUCCESS)
  
  end subroutine SetServices


!=============================================================================
!=============================================================================
!=============================================================================
!=============================================================================
!=============================================================================


!BOP

! !IROUTINE: RUN1 -- First run stage for the {\tt MAPL_TurbulenceGridComp} component

! !INTERFACE:


  subroutine RUN1 ( GC, IMPORT, EXPORT, CLOCK, RC ),83

! !ARGUMENTS:

    type(ESMF_GridComp), intent(inout) :: GC
    type(ESMF_State),    intent(inout) :: IMPORT
    type(ESMF_State),    intent(inout) :: EXPORT
    type(ESMF_Clock),    intent(inout) :: CLOCK
    integer, optional,   intent(  out) :: RC

! !DESCRIPTION: The first run stage of {\tt GEOS\_TurbulenceGridComp} computes the diffusivities,
!   sets-up the matrix for a backward-implicit computation of the surface fluxes,
!   and solves this system for a fixed surface value of the diffused quantity. Run1
!   takes as inputs the surface exchange coefficients (i.e., $\rho |U| C_{m,h,q}$) for
!   momentun, heat, and moisture, as well as the pressure, temperature, moisture, 
!   and winds for the sounding. These are used only for computing the diffusivities
!   and, as explained above,  are not the temperatures, moistures, etc. being diffused.
!
!   The computation of turbulence fluxes for fixed surface values is done at every
!   time step in the contained subroutine {\tt DIFFUSE}; but the computation of 
!   diffusivities and orographic drag coefficients, as well as the set-up of the
!   vertical difference matrix and its LU decomposition
!   can be done intermittently for economy in the contained subroutine  {\tt REFRESH}.
!   The results of this calculation are stored in an internal state. 
!   Run1 also computes the sensitivity of the 
!   atmospheric tendencies and the surface flux to changes in the surface value.
!
!   The diffusivities are computed by calls to {\tt LOUIS\_KS} and {\tt ENTRAIN}, which
!   compute the Louis et al. (1983) and Lock (2000) diffusivities. The Louis 
!   diffusivities are computed for all conditions, and {\tt ENTRAIN} overrides them 
!   where appropriate. Lock can be turned off from the resource file.


!

!EOP

! ErrLog Variables

    character(len=ESMF_MAXSTR)          :: IAm
    integer                             :: STATUS
    character(len=ESMF_MAXSTR)          :: COMP_NAME

! Local derived type aliases

    type (MAPL_MetaComp), pointer   :: MAPL
    type (ESMF_Config      )            :: CF
    type (ESMF_State       )            :: INTERNAL 
    type (ESMF_Alarm       )            :: ALARM   

! Local variables

    real, dimension(:,:,:), pointer     :: AKS, BKS, CKS, DKS
    real, dimension(:,:,:), pointer     :: AKQ, BKQ, CKQ, DKQ
    real, dimension(:,:,:), pointer     :: AKV, BKV, CKV, DKV, EKV, FKV
    real, dimension(:,:,:), pointer     :: PLE
    real, dimension(:,:  ), pointer     :: CU, CT, CQ
    integer                             :: IM, JM, LM
    real                                :: DT

! Begin... 
!---------

! Get my name and set-up traceback handle
! ---------------------------------------

    call ESMF_GridCompGet( GC, NAME=COMP_NAME, RC=STATUS )
    VERIFY_(STATUS)
    Iam = trim(COMP_NAME) // 'Run1'

! Get my internal MAPL_Generic state
!-----------------------------------

    call MAPL_GetObjectFromGC ( GC, MAPL, RC=STATUS)
    VERIFY_(STATUS)

    call MAPL_TimerOn(MAPL,"TOTAL")
    call MAPL_TimerOn(MAPL,"-RUN1")

! Get parameters from generic state.
!-----------------------------------

    call MAPL_Get(MAPL,        &
         IM=IM, JM=JM, LM=LM,               &
         RUNALARM=ALARM,                    &
         INTERNAL_ESMF_STATE=INTERNAL,      &
                                  RC=STATUS )
    VERIFY_(STATUS)

! Get configuration from component
!---------------------------------

    call ESMF_GridCompGet( GC, CONFIG = CF, RC=STATUS )
    VERIFY_(STATUS)

! Get all pointers that are needed by both REFRESH and DIFFUSE
!-------------------------------------------------------------

! Get pressure structure; this is instantaneous.
!-----------------------------------------------

     call MAPL_GetPointer(IMPORT,  PLE,   'PLE',     RC=STATUS)
     VERIFY_(STATUS)

! Get surface exchange coefficients
!----------------------------------

     call MAPL_GetPointer(IMPORT,  CU,     'CM',     RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,  CT,     'CT',     RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,  CQ,     'CQ',     RC=STATUS)
     VERIFY_(STATUS)

! Get pointers from internal state
!---------------------------------

    call MAPL_GetPointer(INTERNAL, AKS,   'AKS',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, BKS,   'BKS',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, CKS,   'CKS',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, DKS,   'DKS',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, AKQ,   'AKQ',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, BKQ,   'BKQ',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, CKQ,   'CKQ',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, DKQ,   'DKQ',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, AKV,   'AKV',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, BKV,   'BKV',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, CKV,   'CKV',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, DKV,   'DKV',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, EKV,   'EKV',     RC=STATUS)
    VERIFY_(STATUS)
    call MAPL_GetPointer(INTERNAL, FKV,   'FKV',     RC=STATUS)
    VERIFY_(STATUS)

! Get application's timestep from configuration
!----------------------------------------------

    call ESMF_ConfigGetAttribute(CF, DT, Label="RUN_DT:" , RC=STATUS)
    VERIFY_(STATUS)

! If its time, do the refresh
! ---------------------------

    if ( ESMF_AlarmIsRinging(ALARM, rc=status) ) then
       VERIFY_(STATUS)
       call ESMF_AlarmRingerOff(ALARM, RC=STATUS)
       VERIFY_(STATUS)

       call MAPL_TimerOn (MAPL,"--REFRESHKS")
        call REFRESH(IM,JM,LM,RC=STATUS)
        VERIFY_(STATUS)
       call MAPL_TimerOff(MAPL,"--REFRESHKS")
    endif

! Solve the free atmosphere problem
! ---------------------------------

    call MAPL_TimerOn (MAPL,"--DIFFUSE")
     call DIFFUSE(IM,JM,LM,RC=STATUS)
     VERIFY_(STATUS)
    call MAPL_TimerOff(MAPL,"--DIFFUSE")

!  All done with RUN1
!--------------------

    call MAPL_TimerOff(MAPL,"-RUN1")
    call MAPL_TimerOff(MAPL,"TOTAL")
    RETURN_(ESMF_SUCCESS)

  contains

!=============================================================================
!=============================================================================

!BOP

! !CROUTINE: REFRESH -- Refreshes diffusivities.

! !INTERFACE:


   subroutine REFRESH(IM,JM,LM,RC) 1,18

! !ARGUMENTS:

     integer,           intent(IN)       :: IM,JM,LM
     integer, optional, intent(OUT)      :: RC

! !DESCRIPTION: 
!   {\tt REFRESH} can be called intermittently to compute new values of the 
!   diffusivities. In addition it does all possible calculations that depend
!   only on these. In particular, it sets up the semi-implicit tridiagonal
!   solver in the vertical and does the LU decomposition. It also includes the
!   local effects of orographic drag, so that it to is done implicitly.
!
!   Diffusivities are first computed with the Louis scheme ({\tt LOUIS\_KS}),
!   and then, where appropriate,
!   they are overridden by the Lock values ({\tt ENTRAIN}).
!   Once diffusivities are computed, {\tt REFRESH} sets-up the tridiagonal
!   matrices for the semi-implicit vertical diffusion calculation and performs
!   their $LU$ decomposition. 
!
!   {\tt REFRESH} requires surface exchange coefficients for heat, moisture, and
!   momentum,  The calculations in the interior are also
!   done for momentum, heat, and water diffusion. Heat and water mixing
!   coefficients differ only at the surface, but these affect the entire $LU$
!   decomposition, and so all three decompositions are saved in the internal state. 
!
!   For a conservatively diffused quantity $q$, we have
!   $$
!   \frac{\partial q}{\partial t} = -g \frac{\partial }{\partial p} 
!       \left(\rho K_q \frac{\partial q}{\partial z} \right)
!   $$
!   In finite difference form, using backward time differencing, this becomes
!   $$
!   \begin{array}{rcl}
!   {q^{n+1}_l - q^{n}_l} & = & - \frac{g}{\delta_l p}^*
!     \delta_l \left[
!      \left( \frac{\Delta t \rho K_q}{\delta_l z} \right)^* (\delta_l q)^{n+1} \right]   \\
!   &&\\
!                         & = & - \alpha_l ( \beta_{l+\frac{1}{2}}(q_{l+1}-q_l)^{n+1} - 
!                                            \beta_{l-\frac{1}{2}}(q_l-q_{l-1})^{n+1} ) \\
!   &&\\
!   \alpha_l & = & \frac{g \Delta t}{(p_{l+\frac{1}{2}}-p_{l-\frac{1}{2}})^*} \\
!   &&\\
!   \beta_{l+\frac{1}{2}} & = & \left( \frac{ (\rho K_q)^*_{l+\frac{1}{2}}}{(z_{l+1}-z_{l})^*} \right) \\
!   \end{array}
!   $$
!   where the subscripts denote levels, superscripts denote times, and the $*$ superscript
!   denotes evaluation at the refresh time.
!   The following tridiagonal set is then solved for $q^{n+1}_l$:
!   $$
!   a_l q_{l-1} + b_l q_l + c_l q_{l+1} = q_l
!   $$
!   where
!   $$
!   \begin{array}{rcl}
!   a_l & = & \alpha_l \beta_{l-\frac{1}{2}} \\
!   c_l & = & \alpha_l \beta_{l+\frac{1}{2}} \\
!   b_l & = & 1 - a_l - c_l.
!   \end{array}
!   $$
!   At the top boundary, we assume $K_q=0$, so  $ \beta_{\frac{1}{2}}=0$ and $a_1=0$.
!   At the surface, $ \beta_{L+\frac{1}{2}}= \rho_s |U|_s C_{m,h,q}$, the surface exchange coefficient.
!   

!EOP
 
     character(len=ESMF_MAXSTR)          :: IAm='Refresh'
     integer                             :: STATUS

     real, dimension(:,:,:), pointer     :: TH, U, V, Q, T, RI, DU, RADLW, RADLWC, LWCRT
     real, dimension(:,:  ), pointer     :: VARFLT
     real, dimension(:,:,:), pointer     :: KH, KM, QLLS, QILS, CLLS, QLCN, QICN, CLCN
     real, dimension(:,:,:), pointer     :: ALH
     real, dimension(:    ), pointer     :: PREF

     real, dimension(IM,JM,1:LM-1)       :: TVE, RDZ
     real, dimension(IM,JM,LM)           :: THV, TV, Z, DMI, PLO, QS, DQS, QL, QI, QA
     real, dimension(IM,JM,0:LM)         :: PKE, ZLE

     real, dimension(:,:,:), pointer     :: EKH, EKM, KHLS, KMLS, KHRAD, KHSFC
     real, dimension(:,:  ), pointer     :: BSTAR, USTAR, ZPBL, PPBL, WERAD, WESFC,VSCRAD,KERAD,DBUOY,ZSML,ZCLD,ZRADML,FRLAND
     real, dimension(:,:  ), pointer     :: WEBRV,VSCBRV,DSIEMS,CHIS,ZCLDTOP,DELSINV,SMIXT,ZRADBS,CLDRF,VSCSFC,RADRCODE

     real, dimension(:,:,:), pointer     :: AKSODT, CKSODT
     real, dimension(:,:,:), pointer     :: AKQODT, CKQODT
     real, dimension(:,:,:), pointer     :: AKVODT, CKVODT


     logical, dimension(IM,JM     )      :: CONVECT

     real                                :: LOUIS
     real                                :: LAMBDAM, LAMBDAM2
     real                                :: LAMBDAH, LAMBDAH2
     real                                :: ZKMENV, ZKHENV 
     real                                :: MINTHICK
     real                                :: MINSHEAR
     real                                :: AKHMMAX
     real                                :: C_B, LAMBDA_B, ZMAX_B,LOUIS_MEMORY
     real                                :: PRANDTLSFC,PRANDTLRAD,BETA_RAD,BETA_SURF,KHRADFAC,TPFAC_SURF,ENTRATE_SURF
     real                                :: PCEFF_SURF, KHSFCFAC,ZCHOKE


     integer                             :: L,LOCK_ON


     logical ::     KH_alloc
     logical ::     KM_alloc
     logical ::     RI_alloc
     logical ::     DU_alloc
     logical ::    EKH_alloc
     logical ::    EKM_alloc
     logical ::  KHSFC_alloc
     logical ::  KHRAD_alloc
     logical ::  LWCRT_alloc
     logical :: ZRADML_alloc
     logical :: ZRADBS_alloc
     logical ::   ZSML_alloc
     logical ::   ZCLD_alloc

     call MAPL_TimerOn(MAPL,"---PRELIMS")
     
! Get Sounding from the import state
!-----------------------------------

     call MAPL_GetPointer(IMPORT,     T,       'T', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,     Q,      'QV', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,    TH,      'TH', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,     U,       'U', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,     V,       'V', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,VARFLT,  'VARFLT', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,  PREF,    'PREF', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT, RADLW,   'RADLW', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,RADLWC,  'RADLWC', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,  QLLS,    'QLLS', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,  QILS,    'QILS', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,  QLCN,    'QLCN', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,  QICN,    'QICN', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,  CLLS,    'CLLS', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,  CLCN,    'CLCN', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT, BSTAR,   'BSTAR', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT, USTAR,   'USTAR', RC=STATUS); VERIFY_(STATUS)
     call MAPL_GetPointer(IMPORT,FRLAND,  'FRLAND', RC=STATUS); VERIFY_(STATUS)

! Compute the edge heights using Arakawa-Suarez hydrostatic equation
!---------------------------------------------------------------------------

     PKE = (PLE/MAPL_P00)**MAPL_KAPPA
     ZLE(:,:,LM) = 0.0
     do L=LM,1,-1
        ZLE(:,:,L-1) = ZLE(:,:,L) + &
               (MAPL_CP/MAPL_GRAV)*TH(:,:,L)*(PKE(:,:,L)-PKE(:,:,L-1))
     end do

! Layer height, pressure, and virtual temperatures
!-------------------------------------------------
     ! First add up clouds to get total fraction, ice, and liquid
     QL  = QLCN + QLLS
     QI  = QICN + QILS
     QA  = CLCN + CLLS
     Z   = 0.5*(ZLE(:,:,0:LM-1)+ZLE(:,:,1:LM))
     PLO = 0.5*(PLE(:,:,0:LM-1)+PLE(:,:,1:LM))

     TV  = T *( 1.0 + MAPL_VIREPS *Q - QL - QI )
     THV = TV*(TH/T)
     TVE = (TV (:,:,1:LM-1) + TV (:,:,2:LM))*0.5

! Miscellaneous factors
!----------------------

     RDZ = PLE(:,:,1:LM-1) / ( MAPL_RGAS * TVE )
     RDZ = RDZ / (Z(:,:, 1:LM-1)-Z(:,:, 2:LM))
     DMI = (MAPL_GRAV*DT)/(PLE(:,:,1:LM)-PLE(:,:,0:LM-1))

! Get turbulence parameters from configuration
!---------------------------------------------

     call ESMF_ConfigGetAttribute(CF,LOUIS    ,Label=trim(COMP_NAME)//"_LOUIS:"   ,default=5.0     ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,LAMBDAM  ,Label=trim(COMP_NAME)//"_LAMBDAM:" ,default=160.0   ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,LAMBDAM2 ,Label=trim(COMP_NAME)//"_LAMBDAM2:",default=160.0   ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,LAMBDAH  ,Label=trim(COMP_NAME)//"_LAMBDAH:" ,default=160.0   ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,LAMBDAH2 ,Label=trim(COMP_NAME)//"_LAMBDAH2:",default=160.0   ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,ZKMENV   ,Label=trim(COMP_NAME)//"_ZKMENV:"  ,default=3000.   ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,ZKHENV   ,Label=trim(COMP_NAME)//"_ZKHENV:"  ,default=3000.   ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,MINTHICK ,Label=trim(COMP_NAME)//"_MINTHICK:",default=0.1     ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,MINSHEAR ,Label=trim(COMP_NAME)//"_MINSHEAR:",default=0.0030  ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,C_B      ,Label=trim(COMP_NAME)//"_C_B:"     ,default=2.50E-6 ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,LAMBDA_B ,Label=trim(COMP_NAME)//"_LAMBDA_B:",default=1500.   ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,AKHMMAX  ,Label=trim(COMP_NAME)//"_AKHMMAX:" ,default=100.    ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,LOCK_ON  ,Label=trim(COMP_NAME)//"_LOCK_ON:" ,default=1       ,RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,PRANDTLSFC , Label=trim(COMP_NAME)//"_PRANDTLSFC:",   default=1.0 ,  RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,PRANDTLRAD , Label=trim(COMP_NAME)//"_PRANDTLRAD:",   default=0.75,  RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,BETA_RAD  ,  Label=trim(COMP_NAME)//"_BETA_RAD:",     default=0.23,  RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,BETA_SURF ,  Label=trim(COMP_NAME)//"_BETA_SURF:",    default=0.23,  RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,KHRADFAC  ,  Label=trim(COMP_NAME)//"_KHRADFAC:",     default=0.85,  RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,KHSFCFAC  ,  Label=trim(COMP_NAME)//"_KHSFCFAC:",     default=0.85,  RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,TPFAC_SURF,  Label=trim(COMP_NAME)//"_TPFAC_SURF:",   default=10.0,  RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,ENTRATE_SURF,Label=trim(COMP_NAME)//"_ENTRATE_SURF:", default=1.e-3, RC=STATUS)
     call ESMF_ConfigGetAttribute(CF,PCEFF_SURF,  Label=trim(COMP_NAME)//"_PCEFF_SURF:",   default=0.05,  RC=STATUS)
 
     call ESMF_ConfigGetAttribute(CF,LOUIS_MEMORY,Label=trim(COMP_NAME)//"_LOUIS_MEMORY:", default=-999., RC=STATUS)



! Get pointers from export state...
!-----------------------------------

     call MAPL_GetPointer(EXPORT,    KH,    'KH', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT,    KM,    'KM', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT,    RI,    'RI', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT,    DU,    'DU', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT,   EKH,   'EKH', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT,   EKM,   'EKM', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT,  KHLS,  'KHLS', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT,  KMLS,  'KMLS', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, KHSFC, 'KHSFC', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, KHRAD, 'KHRAD', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT,  ZPBL,  'ZPBL', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT,  PPBL,  'PPBL', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, LWCRT, 'LWCRT', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, WERAD, 'WERAD', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, WESFC, 'WESFC', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, DBUOY, 'DBUOY', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, VSCRAD,'VSCRAD',RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, VSCsfc,'VSCSFC',RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, KERAD, 'KERAD', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, VSCBRV,'VSCBRV',RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, WEBRV, 'WEBRV', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, CHIS,  'CHIS',  RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, DSIEMS,'DSIEMS',  RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT,  ZCLD,  'ZCLD', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT,  ZSML,  'ZSML', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, ZRADML, 'ZRADML', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, ZRADBS, 'ZRADBS', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, ZCLDTOP,'ZCLDTOP', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, DELSINV,'DELSINV', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, RADRCODE,'RADRCODE', RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, SMIXT  ,'SMIXT',   RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, CLDRF  ,'CLDRF',   RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, ALH    ,'ALH',   RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, AKSODT,   'AKSODT',     RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, CKSODT,   'CKSODT',     RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, AKQODT,   'AKQODT',     RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, CKQODT,   'CKQODT',     RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, AKVODT,   'AKVODT',     RC=STATUS)
     VERIFY_(STATUS)
     call MAPL_GetPointer(EXPORT, CKVODT,   'CKVODT',     RC=STATUS)
     VERIFY_(STATUS)

! Check which ones have to be allocated
!--------------------------------------

     KH_alloc     = .not.associated(KH   )
     KM_alloc     = .not.associated(KM   )
     RI_alloc     = .not.associated(RI   )
     DU_alloc     = .not.associated(DU   )
     EKH_alloc    = .not.associated(EKH  )
     EKM_alloc    = .not.associated(EKM  )
     KHSFC_alloc  = .not.associated(KHSFC)
     KHRAD_alloc  = .not.associated(KHRAD)
     LWCRT_alloc  = .not.associated(LWCRT)

     ZRADML_alloc = .not.associated(ZRADML)
     ZRADBS_alloc = .not.associated(ZRADBS)
     ZCLD_alloc   = .not.associated(ZCLD)
     ZSML_alloc   = .not.associated(ZSML)

! Allocate those
!---------------

     if(   KH_alloc)  allocate(KH   (IM,JM,0:LM))
     if(   KM_alloc)  allocate(KM   (IM,JM,0:LM))
     if(   RI_alloc)  allocate(RI   (IM,JM,0:LM))
     if(   DU_alloc)  allocate(DU   (IM,JM,0:LM))
     if(  EKH_alloc)  allocate(EKH  (IM,JM,0:LM))
     if(  EKM_alloc)  allocate(EKM  (IM,JM,0:LM))
     if(KHSFC_alloc)  allocate(KHSFC(IM,JM,0:LM))
     if(KHRAD_alloc)  allocate(KHRAD(IM,JM,0:LM))
     if(LWCRT_alloc)  allocate(LWCRT(IM,JM,1:LM))

     if(ZRADML_alloc) allocate(ZRADML(IM,JM))
     if(ZRADBS_alloc) allocate(ZRADBS(IM,JM))
     if(ZCLD_alloc)   allocate(ZCLD(IM,JM))
     if(ZSML_alloc)   allocate(ZSML(IM,JM))


! Need DQSAT for Lock scheme
     DQS      = GEOS_DQSAT(T, PLO, qsat=QS, PASCALS=.true. )


!===> Running 1-2-1 smooth of bottom 5 levels of Virtual Pot. Temp.
    THV(:,:,LM) = THV(:,:,LM-1)*0.25 + THV(:,:,LM)*0.75
    do L = LM-1,LM-5,-1
       THV(:,:,L) = THV(:,:,L-1)*0.25 + THV(:,:,L)*0.50 + THV(:,:,L+1)*0.25 
    end do


     call MAPL_TimerOff(MAPL,"---PRELIMS")

!   Refresh diffusivities: First compute Louis...
!   ---------------------------------------------

      call MAPL_TimerOn(MAPL,"---LOUIS")

      call LOUIS_KS(KH(:,:,1:LM-1), KM(:,:,1:LM-1),       &
                    RI(:,:,1:LM-1), DU(:,:,1:LM-1),       &
                    Z, ZLE(:,:,1:LM-1), THV, U, V,        &
                    LOUIS, MINSHEAR, MINTHICK,            &
                    LAMBDAM, LAMBDAM2, LAMBDAH, LAMBDAH2, & 
                    ZKMENV, ZKHENV,                       &
                    AKHMMAX,                              &
                    ALH,                                  &
                                              RC=STATUS )
      VERIFY_(STATUS)


      if(associated(KHLS)) KHLS    = KH
      if(associated(KMLS)) KMLS    = KM

      call MAPL_TimerOff(MAPL,"---LOUIS")

!   ...then add Lock.
!--------------------

      LWCRT = RADLW - RADLWC

  if (LOCK_ON==1) then
      call MAPL_TimerOn(MAPL,"---LOCK")

      CALL ENTRAIN(1,IM,1,JM, RADLW,USTAR,BSTAR,FRLAND,     &
                   T,Q,QL,QI,QA,U,V,Z,PLO,ZLE,PLE,          &
                   QS,DQS,                                  &
                   KM   (:,:,0:LM-1),                       &
                   KH   (:,:,0:LM-1),                       &
                   EKM  (:,:,0:LM-1),                       &
                   EKH  (:,:,0:LM-1),                       &
                   KHSFC(:,:,0:LM-1),                       &
                   KHRAD(:,:,0:LM-1),                       &
                   ZCLD,                                    &
                   ZRADML,                                  &
                   ZRADBS,                                  &
                   ZSML,                                    &
  ! these are optionally allocated
                   ZCLDTOP,                                 &
                   WESFC,                                   &
                   WERAD,                                   &
                   DBUOY,                                   &
                   VSCSFC,                                  &
                   VSCRAD,                                  &
                   KERAD,                                   &
                   VSCBRV,                                  &
                   WEBRV,                                   &
                   DSIEMS,                                  &
                   CHIS,                                    &
                   DELSINV,                                 &
                   SMIXT,                                   &
                   CLDRF,                                   &
                   RADRCODE,                                &
  ! these are input params
                   PRANDTLSFC,PRANDTLRAD,                   &
                   BETA_SURF,BETA_RAD,                      &
                   TPFAC_SURF,ENTRATE_SURF,PCEFF_SURF,      &
                   KHRADFAC, KHSFCFAC                          )

      call MAPL_TimerOff(MAPL,"---LOCK")
   else
      EKM  (:,:,0:LM-1) = 0.0
      EKH  (:,:,0:LM-1) = 0.0
      KHSFC(:,:,0:LM-1) = 0.0
      KHRAD(:,:,0:LM-1) = 0.0
   endif


! PBL-top diagnostic
! -----------------------------------------

     if (associated(ZPBL)) then
       ZPBL = MAPL_UNDEF
       where( (KH(:,:,LM-1) < 2.) ) ZPBL = Z(:,:,LM)
       do L=LM-2,1,-1
         where( (KH(:,:,L) < 2.) .and. (KH(:,:,L+1) >= 2.) .and. (ZPBL == MAPL_UNDEF ) )
           ZPBL = Z(:,:,L+1)
         endwhere
       enddo
     endif

     if (associated(PPBL)) then
       PPBL = MAPL_UNDEF
       where( (KH(:,:,LM-1) < 2.) ) PPBL = PLO(:,:,LM)
       do L=LM-2,1,-1
         where( (KH(:,:,L) < 2.) .and. (KH(:,:,L+1) >= 2.) .and. (PPBL == MAPL_UNDEF ) )
           PPBL = PLO(:,:,L+1)
         endwhere
       enddo
     endif

! Second difference coefficients for scalars; RDZ is RHO/DZ, DMI is (G DT)/DP
! ---------------------------------------------------------------------------

      CKS(:,:,1:LM-1) = -KH(:,:,1:LM-1) * RDZ(:,:,1:LM-1)
      AKS(:,:,1     ) = 0.0
      AKS(:,:,2:LM  ) = CKS(:,:,1:LM-1) * DMI(:,:,2:LM  )
      CKS(:,:,1:LM-1) = CKS(:,:,1:LM-1) * DMI(:,:,1:LM-1)
      CKS(:,:,  LM  ) = -         CT    * DMI(:,:,  LM  )

! Water vapor can differ at the surface
!--------------------------------------

      CKQ             = CKS
      AKQ             = AKS
      CKQ(:,:,  LM  ) = -         CQ    * DMI(:,:,  LM  )

! Second difference coefficients for winds
! EKV is saved to use in the frictional heating calc.
! ---------------------------------------------------

      EKV(:,:,1:LM-1) = -KM(:,:,1:LM-1) * RDZ(:,:,1:LM-1)
      AKV(:,:,1     ) = 0.0
      AKV(:,:,2:LM  ) = EKV(:,:,1:LM-1) * DMI(:,:,2:LM  )
      CKV(:,:,1:LM-1) = EKV(:,:,1:LM-1) * DMI(:,:,1:LM-1)
      EKV(:,:,1:LM-1) = -MAPL_GRAV      * EKV(:,:,1:LM-1)


      CKV(:,:,  LM  ) = -         CU    * DMI(:,:,  LM  )
      EKV(:,:,  LM  ) =  MAPL_GRAV      * CU

! Setup the tridiagonal matrix
! ----------------------------

      BKS = 1.00 - (AKS+CKS)
      BKQ = 1.00 - (AKQ+CKQ)
      BKV = 1.00 - (AKV+CKV)

! Add the topographic roughness term
!-----------------------------------

      if( associated(AKSODT) ) then
          AKSODT = -AKS/DT
          AKSODT(:,:, 1) = 0.0
      endif
      if( associated(CKSODT) ) then
          CKSODT = -CKS/DT
          CKSODT(:,:,LM) = 0.0
      endif
      if( associated(AKQODT) ) then
          AKQODT = -AKQ/DT
          AKQODT(:,:, 1) = 0.0
      endif
      if( associated(CKQODT) ) then
          CKQODT = -CKQ/DT
          CKQODT(:,:,LM) = 0.0
      endif
      if( associated(AKVODT) ) AKVODT = -AKV/DT
      if( associated(CKVODT) ) CKVODT = -CKV/DT

!BOP
!
!   Orograpghic drag follows  Beljaars (2003):
!   $$
!   \frac{\partial}{\partial z}\frac{\tau}{\rho} = \frac{C_B}{\lambda_B} |U(z)| U(z) 
!          e^{-\tilde{z}^\frac{3}{2}}\tilde{z}^{-1.2},
!   $$
!   where $z$ is the height above the surface in meters, 
!   $\tilde{z}=\frac{z}{\lambda_B}$, $\tau$ is the orographic stress at $z$,
!   $\rho$ is the air density, $U(z)$ is the wind velocity, and $\lambda_B$ is a vertical length scale.
!   Beljaars uses $\lambda_B = 1500$m, for which the non-dimensional parameter $C_B = 2.50 \times 10^{-6}$.
!   These are the default values, but both can be modified from the configuration. To avoid underflow.
!   the tendency is set to zero once $\tilde{z}$ exceeds 4 (i.e., 6 km from the surface for default values). 
!
!EOP

      call MAPL_TimerOn(MAPL,"---BELJAARS")

      do L=LM,1,-1
         where(Z(:,:,L) < 4.0*LAMBDA_B)
            FKV(:,:,L) = Z(:,:,L)*(1.0/LAMBDA_B)
            FKV(:,:,L) = VARFLT * exp(-FKV(:,:,L)*sqrt(FKV(:,:,L)))*(FKV(:,:,L)**(-1.2))
            FKV(:,:,L) = (C_B/LAMBDA_B)*sqrt(U(:,:,L)**2+V(:,:,L)**2)*FKV(:,:,L)
         elsewhere
            FKV(:,:,L) = 0.0
         end where
         BKV(:,:,L) = BKV(:,:,L) + DT*FKV(:,:,L)
         FKV(:,:,L) = FKV(:,:,L) * (PLE(:,:,L)-PLE(:,:,L-1))
      end do

      call MAPL_TimerOff(MAPL,"---BELJAARS")

      call MAPL_TimerOn(MAPL,"---DECOMP")

! Do LU decomposition; C is not modified.
! On exit, B is the main diagonals of the LU
! decomposition, and A is the r.h.s multiplier.
!----------------------------------------------

      call VTRILU(AKS,BKS,CKS)
      call VTRILU(AKQ,BKQ,CKQ)
      call VTRILU(AKV,BKV,CKV)

! Get the sensitivity of solution to a unit
! change in the surface value. B and C are
! not modified.
!------------------------------------------

      call VTRISOLVESURF(BKS,CKS,DKS)
      call VTRISOLVESURF(BKQ,CKQ,DKQ)
      call VTRISOLVESURF(BKV,CKV,DKV)

      call MAPL_TimerOff(MAPL,"---DECOMP")

! Deallocate the temporaries
!---------------------------

      if(KH_alloc   )  deallocate(KH)
      if(KM_alloc   )  deallocate(KM)
      if(RI_alloc   )  deallocate(RI)
      if(DU_alloc   )  deallocate(DU)
      if(EKH_alloc  )  deallocate(EKH)
      if(EKM_alloc  )  deallocate(EKM)
      if(KHSFC_alloc)  deallocate(KHSFC)
      if(KHRAD_alloc)  deallocate(KHRAD)
      if(LWCRT_alloc)  deallocate(LWCRT)

     if(ZRADML_alloc) deallocate(ZRADML)
     if(ZRADBS_alloc) deallocate(ZRADBS)
     if(ZCLD_alloc)   deallocate(ZCLD)
     if(ZSML_alloc)   deallocate(ZSML)

      RETURN_(ESMF_SUCCESS)
     end subroutine REFRESH

!=============================================================================
!=============================================================================

!BOP

! !CROUTINE: DIFFUSE -- Solves for semi-implicit diffusive tendencies assuming fixed surface conditions.  

! !INTERFACE:


  subroutine DIFFUSE(IM,JM,LM,RC) 1,6

! !ARGUMENTS:

    integer,           intent(IN)       :: IM,JM,LM
    integer, optional, intent(OUT)      :: RC

! !DESCRIPTION: {\tt DIFFUSE} computes semi-implicit tendencies of all fields in
!  the TR bundle. Each field is examined for three attributes: {\tt DiffuseLike},
!  {\tt FriendlyToTURBULENCE}, and {\tt WeightedTendency}. These determine the behavior of
!  {\tt DIFFUSE} for that field. {\tt DiffuseLike} can be either 'U', 'Q', or 'S'; the default is 'Q'.
!  {\tt FriendlyToTURBULENCE}, and {\tt WeightedTendency} are ESMF logicals.
!  If {\tt FriendlyToTURBULENCE} is true, the field in TR is updated directly; otherwise
!  it is left untouched. In either case, If the corresponding pointer TRI bundle is associated, the
!  tendencies are returned there. If {\tt WeightedTendency} is true, the tendency in TRI, if any,
!  is pressure weighted.

!EOP

    character(len=ESMF_MAXSTR)          :: IAm='Diffuse'
    integer                             :: STATUS

    character(len=ESMF_MAXSTR)          :: TYPE
    type (ESMF_Field)                   :: FIELD
    type (ESMF_Array)                   :: ARRAY
    type (ESMF_Bundle)                  :: TR
    type (ESMF_Bundle)                  :: TRI
    type (ESMF_Bundle)                  :: TRG
    type (ESMF_Bundle)                  :: FSTAR
    type (ESMF_Bundle)                  :: DFSTAR
    real, dimension(:,:,:), pointer     :: S, SOI, SOD
    real, dimension(:,:),   pointer     :: SG, SF, SDF, CX, SRG
    real, dimension(:,:,:), pointer     :: DX
    real, dimension(:,:,:), pointer     :: AK, BK, CK
    integer                             :: KM, K,L
    type(ESMF_logical)                  :: FRIENDLY
    type(ESMF_logical)                  :: WEIGHTED
    real, dimension(IM,JM,LM)           :: DP, SX


! Get the bundles containing the quantities to be diffused, 
!     their tendencies, their surface values, their surface
!     fluxes, and the derivatives of their surface fluxes
!     wrt the surface values. 
!----------------------------------------------------------

    call ESMF_StateGetBundle(IMPORT, 'TR' ,    TR,     RC=STATUS); VERIFY_(STATUS)
    call ESMF_StateGetBundle(IMPORT, 'TRG',    TRG,    RC=STATUS); VERIFY_(STATUS)

    call ESMF_StateGetBundle(EXPORT, 'TRI',    TRI,    RC=STATUS); VERIFY_(STATUS)
    call ESMF_StateGetBundle(EXPORT, 'FSTAR',  FSTAR,  RC=STATUS); VERIFY_(STATUS)
    call ESMF_StateGetBundle(EXPORT, 'DFSTAR', DFSTAR, RC=STATUS); VERIFY_(STATUS)

! Count the firlds in TR...
!--------------------------

    call ESMF_BundleGet(TR, fieldCOUNT=KM, RC=STATUS)
    VERIFY_(STATUS)

! ...and make sure the other bundles are the same.
!-------------------------------------------------

    call ESMF_BundleGet(TRI,    FieldCount=K , RC=STATUS)
    VERIFY_(STATUS)
    ASSERT_(KM==K)
    call ESMF_BundleGet(TRG,    FieldCount=K , RC=STATUS)
    VERIFY_(STATUS)
    ASSERT_(KM==K)
    call ESMF_BundleGet(FSTAR,  FieldCount=K , RC=STATUS)
    VERIFY_(STATUS)
    ASSERT_(KM==K)
    call ESMF_BundleGet(DFSTAR, FieldCount=K , RC=STATUS)
    VERIFY_(STATUS)
    ASSERT_(KM==K)

! Pressure thickness of layers
!-----------------------------

    DP = PLE(:,:,1:LM)-PLE(:,:,0:LM-1)

! Loop over all quantities to be diffused.
!----------------------------------------

    do K=1,KM

! Get the Kth Field from tracer bundle
!-------------------------------------

       call ESMF_BundleGetField     (TR, K, FIELD,                         RC=STATUS)
       VERIFY_(STATUS)

! Get item's diffusion type (U, S or Q; default is Q)
!----------------------------------------------------

       call ESMF_FieldGetAttribute  (FIELD, NAME="DiffuseLike",         VALUE=TYPE,     RC=STATUS)
       if(STATUS /= ESMF_SUCCESS) TYPE = 'Q'

! Get item's friendly status (default is not friendly)
!-----------------------------------------------------

       call ESMF_FieldGetAttribute  (FIELD, NAME="FriendlyToTURBULENCE",VALUE=FRIENDLY, RC=STATUS)
       if(STATUS /= ESMF_SUCCESS) FRIENDLY = ESMF_false

! Get item's weighting (default is unweighted tendencies)
!--------------------------------------------------------

       call ESMF_FieldGetAttribute  (FIELD, NAME="WeightedTendency",    VALUE=WEIGHTED, RC=STATUS)
       if(STATUS /= ESMF_SUCCESS) WEIGHTED = ESMF_false

! Get pointer to the quantity, its tendency, its surface value,
!   the surface flux, and the sensitivity of the surface flux.
! -------------------------------------------------------------

       call ESMFL_BundleGetPointerToData(TR    , K, S  , RC=STATUS); VERIFY_(STATUS)
       call ESMFL_BundleGetPointerToData(TRI   , K, SOI, RC=STATUS); VERIFY_(STATUS)
       call ESMFL_BundleGetPointerToData(TRG   , K, SRG, RC=STATUS); VERIFY_(STATUS)
       call ESMFL_BundleGetPointerToData(FSTAR , K, SF , RC=STATUS); VERIFY_(STATUS)
       call ESMFL_BundleGetPointerToData(DFSTAR, K, SDF, RC=STATUS); VERIFY_(STATUS)

! The quantity must exist; others are optional.
!----------------------------------------------

       ASSERT_(associated(S ))

! If the surface values does not exists, we assume zero flux.
!------------------------------------------------------------
       
       if(associated(SRG)) then
          SG => SRG
       else
          allocate (SG(0,0), stat=STATUS)
          VERIFY_(STATUS)
       end if

! Pick the right exchange coefficients
!-------------------------------------

       if     ( TYPE=='U' ) then ! Momentum
          CX => CU
          DX => DKV
          AK => AKV; BK => BKV; CK => CKV
       else if( TYPE=='Q' ) then ! Water Vapor
          CX => CQ
          DX => DKQ
          AK => AKQ; BK => BKQ; CK => CKQ
       else if( TYPE=='S' ) then ! Heat or other scalars
          CX => CT
          DX => DKS
          AK => AKS; BK => BKS; CK => CKS
       else
          RETURN_(ESMF_FAILURE)
       endif

! Copy diffused quantity to temp buffer
! ------------------------------------------
       
       SX = S

! Solve for semi-implicit changes. This modifies SX
! -------------------------------------------------

       call VTRISOLVE(AK,BK,CK,SX,SG)

! Compute the surface fluxes
!---------------------------

       if(associated(SF)) then
          if(size(SG)>0) then
             SF = CX*(SG - SX(:,:,LM))
          else
             SF = 0.0
          end if
       end if

! Create tendencies
!------------------

       if(associated(SOI)) then
          if( WEIGHTED==ESMF_TRUE ) then
             SOI = ( (SX - S)/DT )*DP
          else
             SOI = ( (SX - S)/DT )
          endif
       end if

! Update friendlies
!------------------

       if(FRIENDLY==ESMF_TRUE) then
          S = SX
       end if

! Compute the derivative of the surface flux wrt the surface value
!-----------------------------------------------------------------

       if(associated(SDF)) then
          SDF = CX * (1.0-DX(:,:,LM))
       endif

       if(.not.associated(SRG)) then
          deallocate (SG)
       end if

    enddo ! End loop over all quantities to be diffused
! -----------------------------------------------------

    RETURN_(ESMF_SUCCESS)
  end subroutine DIFFUSE

end subroutine RUN1


!*********************************************************************
!*********************************************************************
!*********************************************************************


!BOP

! !IROUTINE: RUN2 -- The second run stage for the TURBULENCE component

! !INTERFACE:


  subroutine RUN2 ( GC, IMPORT, EXPORT, CLOCK, RC ),179

! !ARGUMENTS:

    type(ESMF_GridComp), intent(inout) :: GC     ! Gridded component 
    type(ESMF_State),    intent(inout) :: IMPORT ! Import state
    type(ESMF_State),    intent(inout) :: EXPORT ! Export state
    type(ESMF_Clock),    intent(inout) :: CLOCK  ! The clock
    integer, optional,   intent(  out) :: RC     ! Error code:

! !DESCRIPTION: Second run stage of {\tt GEOS\_TurbulenceGridComp} performs
!    the updates due to changes in surface quantities. Its input are the changes in 
!    surface quantities during the time step. It can also compute the frictional
!    dissipation terms as exports, but these are not added to the temperatures.


!EOP

! ErrLog Variables

    character(len=ESMF_MAXSTR)          :: IAm
    integer                             :: STATUS
    character(len=ESMF_MAXSTR)          :: COMP_NAME

! Local derived type aliases

    type (MAPL_MetaComp), pointer   :: MAPL
    type (ESMF_Config      )            :: CF
    type (ESMF_State       )            :: INTERNAL 

! Local variables

    integer                             :: IM, JM, LM
    real                                :: DT

! Begin... 
!---------

! Get my name and set-up traceback handle
! ---------------------------------------

    call ESMF_GridCompGet( GC, NAME=COMP_NAME, RC=STATUS )
    VERIFY_(STATUS)
    Iam = trim(COMP_NAME) // 'Run2'

! Get my internal MAPL_Generic state
!-----------------------------------

    call MAPL_GetObjectFromGC ( GC, MAPL, RC=STATUS)
    VERIFY_(STATUS)

    call MAPL_TimerOn(MAPL,"TOTAL")
    call MAPL_TimerOn(MAPL,"-RUN2")

! Get parameters from generic state.
!-----------------------------------

    call MAPL_Get(MAPL,        &
         IM=IM, JM=JM, LM=LM,               &
         INTERNAL_ESMF_STATE=INTERNAL,      &
                                  RC=STATUS )
    VERIFY_(STATUS)

! Get configuration from component
!---------------------------------

    call ESMF_GridCompGet( GC, CONFIG = CF, RC=STATUS )
    VERIFY_(STATUS)

! Get application's timestep from configuration
!----------------------------------------------

    call ESMF_ConfigGetAttribute( CF, DT, Label="RUN_DT:" , RC=STATUS)
    VERIFY_(STATUS)

! Solve the free atmosphere problem
! ---------------------------------

    call MAPL_TimerOn (MAPL,"--UPDATE")
      call UPDATE(IM,JM,LM,RC=STATUS)
      VERIFY_(STATUS)
    call MAPL_TimerOff(MAPL,"--UPDATE")

!  All done with RUN
!-------------------

    call MAPL_TimerOff(MAPL,"-RUN2")
    call MAPL_TimerOff(MAPL,"TOTAL")
    RETURN_(ESMF_SUCCESS)

  contains

!BOP

! !CROUTINE: UPDATE -- Updates diffusive effects for changes at surface.

! !INTERFACE:


    subroutine UPDATE(IM,JM,LM,RC) 8,13

! !ARGUMENTS:

      integer,           intent(IN)       :: IM,JM,LM
      integer, optional, intent(OUT)      :: RC

! !DESCRIPTION: 
!    Some description

!EOP
 
 
      character(len=ESMF_MAXSTR)          :: IAm='Update'
      integer                             :: STATUS

      character(len=ESMF_MAXSTR)          :: TYPE
      type (ESMF_Field)                   :: FIELD
      type (ESMF_Bundle)                  :: TR
      type (ESMF_Bundle)                  :: TRI
      type (ESMF_Bundle)                  :: DTG
      type (ESMF_Bundle)                  :: FSTAR
      type (ESMF_Bundle)                  :: DFSTAR
      real, dimension(:,:,:), pointer     :: PLE
      real, dimension(:,:,:), pointer     :: S, SOI, INTDIS, TOPDIS
      real, dimension(:,:  ), pointer     :: DSG, SF, SDF, SRFDIS
      real, dimension(:,:  ), pointer     :: KETRB, KESRF, KETOP, KEINT
      real, dimension(:,:,:), pointer     :: DKS, DKV, DKQ, DKX, EKV, FKV
      integer                             :: KM, K, L
      type(ESMF_logical)                  :: FRIENDLY
      type(ESMF_logical)                  :: WEIGHTED
      real, dimension(IM,JM,LM)           :: DP, SX
      real, dimension(IM,JM,LM-1)         :: DF

! Pressure-weighted dissipation heating rates
!--------------------------------------------

      call MAPL_GetPointer(EXPORT, KETRB ,  'KETRB' , RC=STATUS); VERIFY_(STATUS)
      call MAPL_GetPointer(EXPORT, KESRF ,  'KESRF' , RC=STATUS); VERIFY_(STATUS)
      call MAPL_GetPointer(EXPORT, KETOP ,  'KETOP' , RC=STATUS); VERIFY_(STATUS)
      call MAPL_GetPointer(EXPORT, KEINT ,  'KEINT' , RC=STATUS); VERIFY_(STATUS)

      call MAPL_GetPointer(EXPORT, SRFDIS,  'SRFDIS',                      &
                       alloc=associated(KETRB) .or. associated(KESRF), &
                                                              RC=STATUS)
      VERIFY_(STATUS)
      call MAPL_GetPointer(EXPORT, INTDIS,  'INTDIS',                      &
                       alloc=associated(KETRB) .or. associated(KEINT), &
                                                              RC=STATUS)
      VERIFY_(STATUS)
      call MAPL_GetPointer(EXPORT, TOPDIS,  'TOPDIS',                      &
                       alloc=associated(KETRB) .or. associated(KETOP), &
                                                              RC=STATUS)
      VERIFY_(STATUS)

! Get imports
!------------

      call MAPL_GetPointer(IMPORT,    PLE,     'PLE', RC=STATUS); VERIFY_(STATUS)

! Get the tendecy sensitivities computed in RUN1
!-----------------------------------------------

      call MAPL_GetPointer(INTERNAL, DKS,   'DKS',   RC=STATUS)
      VERIFY_(STATUS)
      call MAPL_GetPointer(INTERNAL, DKV,   'DKV',   RC=STATUS)
      VERIFY_(STATUS)
      call MAPL_GetPointer(INTERNAL, DKQ,   'DKQ',   RC=STATUS)
      VERIFY_(STATUS)
      call MAPL_GetPointer(INTERNAL, EKV,   'EKV',   RC=STATUS)
      VERIFY_(STATUS)
      call MAPL_GetPointer(INTERNAL, FKV,   'FKV',   RC=STATUS)
      VERIFY_(STATUS)

! Get the bundles containing the quantities to be diffused, 
!     their tendencies, their surface values, their surface
!     fluxes, and the derivatives of their surface fluxes
!     wrt the surface values. 
!----------------------------------------------------------

      call ESMF_StateGetBundle(IMPORT, 'TR' ,    TR,     RC=STATUS); VERIFY_(STATUS)
      call ESMF_StateGetBundle(IMPORT, 'DTG',    DTG,    RC=STATUS); VERIFY_(STATUS)

      call ESMF_StateGetBundle(EXPORT, 'TRI',    TRI,    RC=STATUS); VERIFY_(STATUS)
      call ESMF_StateGetBundle(EXPORT, 'FSTAR' , FSTAR,  RC=STATUS); VERIFY_(STATUS)
      call ESMF_StateGetBundle(EXPORT, 'DFSTAR', DFSTAR, RC=STATUS); VERIFY_(STATUS)

! Count them...
!--------------

      call ESMF_BundleGet(TR , FieldCount=KM, RC=STATUS)
      VERIFY_(STATUS)

! and make sure the other bundles are the same.
!----------------------------------------------

      call ESMF_BundleGet(DTG, FieldCount=K , RC=STATUS)
      VERIFY_(STATUS)
      ASSERT_(KM==K)

! Clear the accumulators for the dissipation.
!--------------------------------------------

      if(associated(SRFDIS)) SRFDIS = 0.0
      if(associated(INTDIS)) INTDIS = 0.0
      if(associated(TOPDIS)) TOPDIS = 0.0
      if(associated(KETRB )) KETRB  = 0.0
      if(associated(KESRF )) KESRF  = 0.0
      if(associated(KETOP )) KETOP  = 0.0
      if(associated(KEINT )) KEINT  = 0.0

! Pressure thickness of layers
!-----------------------------

      DP = PLE(:,:,1:LM)-PLE(:,:,0:LM-1)

! Loop over all quantities to be diffused.
!-----------------------------------------

      do K=1,KM

! Get Kth field from bundle
!--------------------------

         call ESMF_BundleGetField     (TR, K, FIELD, RC=STATUS)
         VERIFY_(STATUS)

! Get item's diffusion type (U, S or Q; default is Q)
!----------------------------------------------------

         call ESMF_FieldGetAttribute  (FIELD, NAME="DiffuseLike",         VALUE=TYPE,      RC=STATUS)
         if(STATUS /= ESMF_SUCCESS) TYPE = 'Q'

! Get item's friendly status (default is FALSE)
!----------------------------------------------

         call ESMF_FieldGetAttribute  (FIELD, NAME="FriendlyToTURBULENCE",VALUE=FRIENDLY,  RC=STATUS)
         if(STATUS /= ESMF_SUCCESS) FRIENDLY  = ESMF_false

! Get item's weighting attribute (default is TRUE)
!-------------------------------------------------

         call ESMF_FieldGetAttribute  (FIELD, NAME="WeightedTendency",    VALUE=WEIGHTED,  RC=STATUS)
         if(STATUS /= ESMF_SUCCESS) WEIGHTED  = ESMF_false

! Get pointers to the quantity, its tendency, its surface increment,
!   the preliminary surface flux, and the sensitivity of the surface
!   flux to the surface value.
! ------------------------------------------------------------------

         call ESMFL_BundleGetPointerToData(TR    , K, S  , RC=STATUS)
         VERIFY_(STATUS)
         call ESMFL_BundleGetPointerToData(TRI   , K, SOI, RC=STATUS)
         VERIFY_(STATUS)
         call ESMFL_BundleGetPointerToData(DTG   , K, DSG, RC=STATUS)
         VERIFY_(STATUS)
         call ESMFL_BundleGetPointerToData(FSTAR , K, SF , RC=STATUS)
         VERIFY_(STATUS)
         call ESMFL_BundleGetPointerToData(DFSTAR, K, SDF, RC=STATUS)
         VERIFY_(STATUS)


!  Point to the appropriate sensitivity
!--------------------------------------

         if      ( TYPE=='U' ) then
            DKX => DKV
         else if ( TYPE=='Q' ) then
            DKX => DKQ
         else if ( TYPE=='S' ) then
            DKX => DKS
         else
            RETURN_(ESMF_FAILURE)
         end if

! Update diffused quantity
!-------------------------

         SX = S

         if(associated(DSG)) then
            do L=1,LM 
               SX(:,:,L) = SX(:,:,L) + DKX(:,:,L)*DSG 
            end do
         end if

! Replace friendly
!-----------------

         if(FRIENDLY==ESMF_TRUE) then
            S = SX
         end if

! Increment the dissipation
!-------------------------- 

         if( TYPE=='U' ) then
            if(associated(KETRB )) KETRB  = 0.0
            if(associated(KESRF )) KESRF  = 0.0
            if(associated(KETOP )) KETOP  = 0.0
            if(associated(KEINT )) KEINT  = 0.0
            if(associated(INTDIS)) then
               DF             = (0.5/(MAPL_CP))*EKV(:,:,1:LM-1)*(SX(:,:,1:LM-1)-SX(:,:,2:LM))**2
               INTDIS(:,:,1:LM-1) = INTDIS(:,:,1:LM-1) + DF
               INTDIS(:,:,2:LM  ) = INTDIS(:,:,2:LM  ) + DF
               if(associated(KETRB)) then
                  do L=1,LM
                     KETRB = KETRB - INTDIS(:,:,L)* (MAPL_CP/MAPL_GRAV)
                  end do
               end if
               if(associated(KEINT)) then
                  do L=1,LM
                     KEINT = KEINT - INTDIS(:,:,L)* (MAPL_CP/MAPL_GRAV)
                  end do
               end if
            endif
            if(associated(TOPDIS)) then
               TOPDIS = TOPDIS + (1.0/(MAPL_CP))*FKV*SX**2
               if(associated(KETRB)) then
                  do L=1,LM
                     KETRB = KETRB - TOPDIS(:,:,L)* (MAPL_CP/MAPL_GRAV)
                  end do
               end if
               if(associated(KETOP)) then
                  do L=1,LM
                     KETOP = KETOP - TOPDIS(:,:,L)* (MAPL_CP/MAPL_GRAV)
                  end do
               end if
             endif
            if(associated(SRFDIS)) then
               SRFDIS = SRFDIS + (1.0/(MAPL_CP))*EKV(:,:,LM)*SX(:,:,LM)**2
               if(associated(KETRB)) KETRB = KETRB - SRFDIS* (MAPL_CP/MAPL_GRAV)
               if(associated(KESRF)) KESRF = KESRF - SRFDIS* (MAPL_CP/MAPL_GRAV)
            endif
         end if

! Update tendencies
! -----------------

         if(associated(SOI).and.associated(DSG)) then
            if( WEIGHTED==ESMF_TRUE ) then
               do L=1,LM
                  SOI(:,:,L) = SOI(:,:,L) +  (DKX(:,:,L)*DSG/DT)*DP(:,:,L)
               end do
            else
               do L=1,LM
                  SOI(:,:,L) = SOI(:,:,L) +  (DKX(:,:,L)*DSG/DT)
               end do
            endif
         end if

! Update surface fluxes
! ---------------------

         if(associated(SF).and.associated(DSG)) then
            SF = SF + DSG*SDF
         end if

      enddo ! End loop over all quantities to be diffused
!--------------------------------------------------------

      RETURN_(ESMF_SUCCESS)
    end subroutine UPDATE

  end subroutine RUN2


!*********************************************************************
!*********************************************************************
!*********************************************************************


!BOP

! !IROUTINE:  VTRILU --  Does LU decomposition of tridiagonal matrix.

! !INTERFACE:


  subroutine VTRILU  ( A,B,C ) 3

! !ARGUMENTS:

    real, dimension(:,:,:), intent(IN   ) ::  C
    real, dimension(:,:,:), intent(INOUT) ::  A, B

! !DESCRIPTION: {\tt VTRILU} performs an $LU$ decomposition on
! a tridiagonal matrix $M=LU$.
!
! $$
! M = \left( \begin{array}{ccccccc}
!      b_1 & c_1 & & & & & \\
!      a_2 & b_2 & c_2 & & & &  \\
!      &  \cdot& \cdot & \cdot & & &  \\
!      & & \cdot& \cdot & \cdot & &  \\
!      &&  & \cdot& \cdot & \cdot &  \\
!      &&&& a_{K-1} & b_{K-1} & c_{K-1}   \\
!      &&&&& a_{K} & b_{K}
!    \end{array} \right)
! $$
!
! $$
! \begin{array}{lr}
! L = \left( \begin{array}{ccccccc}
!      1 &&&&&& \\
!      \hat{a}_2 & 1 & &&&&  \\
!      &  \cdot& \cdot &  & & &  \\
!      & & \cdot& \cdot &  &&  \\
!      &&  & \cdot& \cdot &  &  \\
!      &&&& \hat{a}_{K-1} & 1 &   \\
!      &&&&& \hat{a}_{K} & 1
!    \end{array} \right)
! &
! U = \left( \begin{array}{ccccccc}
!      \hat{b}_1 & c_1 &&&&& \\
!       & \hat{b}_2 & c_2 &&&&  \\
!      &  & \cdot & \cdot & & &  \\
!      & & & \cdot & \cdot &&  \\
!      &&  & & \cdot & \cdot &  \\
!      &&&&  & \hat{b}_{K-1} & c_{K-1}   \\
!      &&&&&  & \hat{b}_{K}
!    \end{array} \right)
! \end{array}
! $$
!
! On input, A, B, and C contain, $a_k$, $b_k$, and $c_k$
! the lower, main, and upper diagonals of the matrix, respectively.
! On output, B contains $1/\hat{b}_k$, the inverse of the main diagonal of $U$,
! and A contains $\hat{a}_k$,
! the lower diagonal of $L$. C contains the upper diagonal of the original matrix and of $U$.
!
! The new diagonals $\hat{a}_k$ and $\hat{b}_k$ are:
! $$
! \begin{array}{rcl}
! \hat{b}_1 & = & b_1, \\
! \hat{a}_k & = & \makebox[2 in][l]{$a_k / \hat{b}_{k-1}$,}  k=2, K, \\
! \hat{b}_k & = & \makebox[2 in][l]{$b_k - c_{k-1} \hat{a}_k$,} k=2, K. 
! \end{array}
! $$
!EOP

    integer :: L

    B(:,:,1) = 1. /  B(:,:,1)

    do L = 2,size(A,3)
       A(:,:,L) = A(:,:,L) * B(:,:,L-1)
       B(:,:,L) = 1. / ( B(:,:,L) - C(:,:,L-1) * A(:,:,L) )
    enddo

    return
  end subroutine VTRILU


!*********************************************************************


!BOP

! !IROUTINE:  VTRISOLVE -- Solves for tridiagonal system that has been decomposed by VTRILU


! !INTERFACE:


  subroutine VTRISOLVE ( A,B,C,Y,YG ) 1

! !ARGUMENTS:

    real, dimension(:,:,:),  intent(IN   ) ::  A, B, C
    real, dimension(:,:,:),  intent(INOUT) ::  Y
    real, dimension(:,:),    intent(IN)    ::  YG

! !DESCRIPTION: Solves tridiagonal system that has been LU decomposed
!   $LU x = f$. This is done by first solving $L g = f$ for $g$, and 
!   then solving $U x = g$ for $x$. The solutions are:
! $$
! \begin{array}{rcl}
! g_1 & = & f_1, \\
! g_k & = & \makebox[2 in][l]{$f_k - g_{k-1} \hat{a}_{k}$,}  k=2, K, \\
! \end{array}
! $$
! and  
! $$
! \begin{array}{rcl}
! x_K & = & g_K /\hat{b}_K, \\
! x_k & = & \makebox[2 in][l]{($g_k - c_k g_{k+1}) / \hat{b}_{k}$,}  k=K-1, 1 \\
! \end{array}
! $$
!  
!  On input A contains the $\hat{a}_k$, the lower diagonal of $L$,
!   B contains the $1/\hat{b}_k$, inverse of the  main diagonal of $U$,
!   C contains the $c_k$, the upper diagonal of $U$. The forcing, $f_k$ is
!   
!   It returns the
!   solution in the r.h.s input vector, Y. A has the multiplier from the
!   decomposition, B the 
!   matrix (U), and C the upper diagonal of the original matrix and of U.
!   YG is the LM+1 (Ground) value of Y.

!EOP

    integer :: LM, L

    LM = size(Y,3)

! Sweep down, modifying rhs with multiplier A

    do L = 2,LM
       Y(:,:,L) = Y(:,:,L) - Y(:,:,L-1) * A(:,:,L)
    enddo

! Sweep up, solving for updated value. Note B has the inverse of the main diagonal

    if(size(YG)>0) then
       Y(:,:,LM)   = (Y(:,:,LM) - C(:,:,LM) * YG        )*B(:,:,LM)
    else
       Y(:,:,LM)   =  Y(:,:,LM)*B(:,:,LM-1)/(B(:,:,LM-1) - A(:,:,LM)*(1.0+C(:,:,LM-1)*B(:,:,LM-1) ))
    endif

    do L = LM-1,1,-1
       Y(:,:,L) = (Y(:,:,L ) - C(:,:,L ) * Y(:,:,L+1))*B(:,:,L )
    enddo

    return
  end subroutine VTRISOLVE

!*********************************************************************

!BOP

! !IROUTINE:  VTRISOLVESURF -- Solves for sensitivity to surface value


! !INTERFACE:


  subroutine VTRISOLVESURF( B,C,Y ) 3

! !ARGUMENTS:

    real, dimension(:,:,:), intent(IN   ) ::  B, C
    real, dimension(:,:,:), intent(  OUT) ::  Y

! !DESCRIPTION: Solves tridiagonal system that has been LU decomposed
!   for the special case
!   where the surface Y (YG) is 1 and the rest of the input Ys are 0.
!   Everything else is as in {\tt VTRISOLVE}. This gives the sensitivity of the
!   solution to a unit change in the surface values.

!EOP

    integer :: LM, L

    LM = size(B,3)

    Y(:,:,LM) = -C(:,:,LM) * B(:,:,LM)

    do L = LM-1,1,-1
       Y(:,:,L) = -C(:,:,L) * Y(:,:,L+1) * B(:,:,L)
    enddo

    return
  end subroutine VTRISOLVESURF

!*********************************************************************

!BOP

! !IROUTINE:  GETKS -- Computes atmospheric diffusivities at interior levels

! !INTERFACE:


   subroutine LOUIS_KS(                         &  1
     KH,KM,RI,DU,                               &
     ZZ,ZE,PV,UU,VV,                            &
     LOUIS, MINSHEAR, MINTHICK,                 &
     LAMBDAM, LAMBDAM2,LAMBDAH, LAMBDAH2,       & 
     ZKMENV, ZKHENV,                            &
     KHMMAX,                                    &
     ALH_DIAG,                                  &
                                         RC     )
! !ARGUMENTS:

   real, intent(IN ) :: ZZ(:,:,:) ! Height of layer center above the surface (m).
   real, intent(IN ) :: PV(:,:,:) ! Virtual potential temperature at layer center (K).
   real, intent(IN ) :: UU(:,:,:) ! Eastward velocity at layer center (m s-1).
   real, intent(IN ) :: VV(:,:,:) ! Northward velocity at layer center (m s-1).
   real, intent(IN ) :: ZE(:,:,:) ! Height of layer base above the surface (m).
   real, intent(IN ) :: LOUIS     ! Louis scheme parameters (usually 5).
   real, intent(IN ) :: MINSHEAR  ! Min shear allowed in Ri calculation (s-1).
   real, intent(IN ) :: MINTHICK  ! Min layer thickness (m).
   real, intent(IN ) :: KHMMAX    ! Maximum allowe diffusivity (m+2 s-1).
   real, intent(IN ) :: LAMBDAM   ! Blackadar(1962) length scale parameter for momentum (m).
   real, intent(IN ) :: LAMBDAM2  ! Second Blackadar parameter for momentum (m).
   real, intent(IN ) :: LAMBDAH   ! Blackadar(1962) length scale parameter for heat (m).
   real, intent(IN ) :: LAMBDAH2  ! Second Blackadar parameter for heat (m).
   real, intent(IN ) :: ZKMENV    ! Transition height for Blackadar param for momentum (m)
   real, intent(IN ) :: ZKHENV    ! Transition height for Blackadar param for heat     (m)
   real, intent(OUT) :: KM(:,:,:) ! Momentum diffusivity at base of each layer (m+2 s-1).
   real, intent(OUT) :: KH(:,:,:) ! Heat diffusivity at base of each layer  (m+2 s-1).
   real, intent(OUT) :: RI(:,:,:) ! Richardson number
   real, intent(OUT) :: DU(:,:,:) ! Magnitude of wind shear (s-1).

   integer, optional, intent(OUT) :: RC

   real, pointer     :: ALH_DIAG(:,:,:)  ! Blackadar Length Scale diagnostic (m) [Optional] 

! !DESCRIPTION: Computes Louis et al.(1979) Richardson-number-based diffusivites,
!                as well as an additional ``entrainment'' diffusivity.
!                The Louis diffusivities for momentum, $K_m$, and for heat
!   and moisture, $K_h$, are defined at the interior layer edges. For LM layers,
!   we define diffusivities at the base of the top LM-1 layers. All indexing
!   is from top to bottom of the atmosphere. 
!
!
!  The Richardson number, Ri, is defined at the same edges as the diffusivities. 
!  $$
!  {\rm Ri}_l = \frac{ \frac{g}{\left(\overline{\theta_v}\right)_l}\left(\frac{\delta \theta_v}{\delta z}\right)_l }
!                    { \left(\frac{\delta {\bf |V|}}{\delta z}\right)^2_l             }, \, \,  l=1,LM-1
!  $$
!  where $\theta_v=\theta(1+\epsilon q)$ is the virtual potential temperature,
!  $\epsilon=\frac{M_a}{M_w}-1$, $M_a$ and $M_w$ are the molecular weights of
!  dry air and water, and $q$ is the specific humidity.
!  $\delta \theta_v$ is the difference of $\theta_v$ in the layers above and below the edge 
!  at which Ri$_l$ is defined; $\overline{\theta_v}$ is their average.
!
!  The diffusivities at the layer edges have the form:
!  $$
!  K^m_l = (\ell^2_m)_l \left(\frac{\delta {\bf |V|}}{\delta z}\right)_l f_m({\rm Ri}_l)
!  $$
!  and
!  $$
!  K^h_l = (\ell^2_h)_l \left(\frac{\delta {\bf |V|}}{\delta z}\right)_l f_h({\rm Ri}_l),
!  $$
!  where $k$ is the Von Karman constant, and $\ell$ is the 
!  Blackdar(1962) length scale, also defined at the layer edges.
!
!  Different turbulent length scales can be used for heat and momentum. 
!  in both cases, we use the  traditional formulation:
!  $$
!  (\ell_{(m,h)})_l  = \frac{kz_l}{1 + \frac{kz_l}{\lambda_{(m,h)}}},
!  $$
!  where, near the surface, the scale is proportional to $z_l$, the height above 
!  the surface of edge level $l$, and far from the surface it approaches $\lambda$.
!  The length scale $\lambda$ is usually taken to be a constant (order 150 m), assuming
!  the same scale for the outre boundary layer and the free atmosphere. We make it
!  a function of height, reducing its value in the free atmosphere. The momentum
!  length scale written as:
!  $$
!  \lambda_m = \max(\lambda_1 e^{\left(\frac{z_l}{z_T}\right)^2}, \lambda_2)
!  $$
!  where $\lambda_2 \le \lambda_1$ and $z_T$ is the top of the boundary layer.
!  The length scale for heat and other scalers is taken as: $\lambda_h =  \sqrt\frac{3d}{2} \lambda_m$,
!  following the scheme used at ECMWF.
!
!  The two universal functions of the Richardson number,  $f_m$ and $f_h$,
!  are taken from Louis et al (1982). For unstable conditions (Ri$\le 0$),
!  they are:
!  $$
!  f_m = (1 - 2b \psi)
!  $$
!  and
!  $$
!  f_h = (1 - 3b \psi),
!  $$
!  where
!  $$
!  \psi = \frac{ {\rm Ri} }{ 1 + 3bC(z)\sqrt{-{\rm Ri}} },
!  $$
!  and
!  $$
!  C(z)=
!  $$

!  For stable condition (Ri$\ge 0$), they are
!  $$
!  f_m = \frac{1}{1.0 + \frac{2b{\rm Ri}}{\psi}}
!  $$
!  and
!  $$
!  f_h = \frac{1}{1.0 + 3b{\rm Ri}\psi},
!  $$
!  where
!  $$
!  \psi =  \sqrt{1+d{\rm Ri}}.
!  $$
!  As in Louis et al (1982), the parameters appearing in these are taken  
!  as $b = c = d = 5$. 


!EOP


! ErrLog Variables

    character(len=ESMF_MAXSTR)                         :: IAm = "TurbulenceGetks"
    integer                                            :: STATUS

! Locals

   real, dimension(size(KH,1),size(KH,2),size(KH,3))   :: ALH, ALM, DZ, DT, TM, PS, LAMBDAM_X, LAMBDAH_X
   integer                                             :: LM,L
   real                                                :: Zchoke 

! Begin...

!===>   Number of layers; edge levels will be one less (LM-1).

    LM = size(ZZ,3)

!===>   Quantities needed for Richardson number

    DZ = (ZZ (:,:,1:LM-1) - ZZ (:,:,2:LM))
    TM = (PV (:,:,1:LM-1) + PV (:,:,2:LM))*0.5
    DT = (PV (:,:,1:LM-1) - PV (:,:,2:LM))
    DU = (UU (:,:,1:LM-1) - UU (:,:,2:LM))**2 + &
         (VV (:,:,1:LM-1) - VV (:,:,2:LM))**2

!===>   Limits on distance between layer centers and vertical shear at edges.

    DZ = max(         DZ, MINTHICK)
    DU = sqrt(DU)/DZ

!===>   Richardson number  ( RI = G*(DTheta_v/DZ) / (Theta_v*|DV/DZ|^2) )

    RI = MAPL_GRAV*(DT/DZ)/(TM*( max(DU, MINSHEAR)**2))

!===>   Blackadar(1962) length scale: $1/l = 1/(kz) + 1/\lambda$

    LAMBDAM_X = MAX( LAMBDAM * EXP( -(ZE / ZKMENV )**2 ) , LAMBDAM2 )
    LAMBDAH_X = MAX( LAMBDAH * EXP( -(ZE / ZKHENV )**2 ) , LAMBDAH2 )

    ALM = ( MAPL_KARMAN*ZE/( 1.0 + MAPL_KARMAN*(ZE/LAMBDAM_X) ) )**2
    ALH = ( MAPL_KARMAN*ZE/( 1.0 + MAPL_KARMAN*(ZE/LAMBDAH_X) ) )**2

       if (associated( ALH_DIAG ) ) then 
         ALH_DIAG(:,:,0)      = 0.0
         ALH_DIAG(:,:,1:LM-1) = SQRT( ALH )
         ALH_DIAG(:,:,LM)     = 0.0
       endif

!===>   Unstable case: Uses (3.14, 3.18, 3.27) in Louis-scheme
!                      should approach (3.13) for small -RI.

    where( RI  < 0.0 )
       PS = ( (ZZ(:,:,1:LM-1)/ZZ(:,:,2:LM))**(1./3.) - 1.0 ) ** 3
       PS = ALH*sqrt( PS/(ZE*(DZ**3)) )
       PS = RI/(1.0 + (3.0*LOUIS*LOUIS)*PS*sqrt(-RI))

       KH = 1.0 - (LOUIS*3.0)*PS
       KM = 1.0 - (LOUIS*2.0)*PS
    endwhere

!===>   Choke off unstable KH below Zchoke (m). JTB 2/2/06    
    Zchoke = 500.
    where( (RI < 0.0) .and. (ZE < Zchoke ) )  
       KH = KH * (( ZE / Zchoke )**3)            
    endwhere


!===>   Stable case

    where( RI >= 0.0 )
       PS = sqrt  (1.0 +  LOUIS     *RI   )

       KH = 1.0 / (1.0 + (LOUIS*3.0)*RI*PS)
       KM = PS  / (PS  + (LOUIS*2.0)*RI   )
    endwhere

!===>   DIMENSIONALIZE Kz and  LIMIT DIFFUSIVITY

    ALM = DU*ALM
    ALH = DU*ALH

    KM = min(KM*ALM, KHMMAX)
    KH = min(KH*ALH, KHMMAX)


    RETURN_(ESMF_SUCCESS)

  end subroutine LOUIS_KS

end module GEOS_TurbulenceGridCompMod