!BOI

!  !TITLE: GSI\_ChemGuess\_Mod: A GSI Bundle to handle Trace Gases and Aerosols

!  !AUTHORS: Ricardo Todling

!  !AFFILIATION: Global Modeling and Assimilation Office, NASA/GSFC, Greenbelt, MD 20771

!  !DATE: 12 Oct 2010

!  !INTRODUCTION: Overview
#ifdef __PROTEX__

This module defines to so-called GSI\_ChemGuess\_Bundle. Its main purpose is to
allow GSI to ingest guess fields related to trace gases, aerosols, and chemistry
in general. 

\begin{center}
\fbox{Chem Bundle is a way to ingest Chemistry-related backgrounds into GSI}
\end{center}

Before the introduction of this module, all guess fields entered GSI through the 
arrays ges\_x, with x standing for particular fields, defined in the guess\_grids module, 
e.g., ges\_u, ges\_tv, and so on. Extending this approach to handle chemistry-related fields
could become rather complex, particularly, because it is in principle not known which fields are
needed for given application. The GSI\_ChemGuess\_Bundle aims at allowing GSI to ingest 
a general set of fields without a given order or particular specification. 

\underline{Caution}: An important exception is ozone. Since guess\_grids already handles ozone, this
is the only chemistry field that should still be dealt through guess\_gridsi, as ges\_oz.

\begin{center}
\fbox{Chem Bundle is a GSI\_Bundle}
\end{center}

The GSI\_ChemGuess\_Bundle uses the GSI\_Bundle. But while the state and control vectors 
use the GSI\_Bundle to associate fields used by the observation operator and
those used in the cost function, respectively, the GSI\_ChemGuess\_Bundle
is simply aimed at allowing ingestion of Chemistry Guess fields into GSI. The translation
of these guess fields into state and control vectors is still done via the state and
control vectors defining mechanism. 

As guess\_grids does, this module still treats the Chemistry Guess fields via a
common-block-like structure. That is, the GSI\_Bundle defined here to hold the
Chemistry Guess fields is an internally defined type that cannot be passed
around. This will change in the future, but for the time being this is the
simplest thing to do given the current code design.

\begin{center}
\fbox{Chem Bundle Module provides an (almost) opaque access to the entries in
the object}
\end{center}

One of the ideas behind this module is that it defines an opaque-like object.
That is, functions related to contents of the Chem Bundle should can only be
extracted via inquires through a ``get-like'' procedures. This is why, only ``methods'' are 
made public to this module, that is, 

\begin{verbatim}
public :: gsi_chemguess_create_grids
public :: gsi_chemguess_destroy_grids
public :: gsi_chemguess_init
public :: gsi_chemguess_get
public :: gsi_chemguess_final
\end{verbatim}

and never the variables themselves; the only exception being the GSI\_ChemGuess\_Bundle itself 
(until it is no longer treated as a common-block).  Some of the above public methods are 
overloaded and all  have internal interfaces (name of which appears in the index of this protex 
document. It should be a rule here that any new routine to be make public should
have a declared interface procedure.

\begin{center}
\fbox{Chem Bundle is defined via the {\it chem\_guess} table in a resource file}
\end{center}

\underline{Defining the Chem Bundle} is done via the table {\it chem\_guess}, usually 
embedded in the {\it anavinfo} file. An example of such table follows:
\begin{verbatim}
chem_guess::
!#var     level  itracer crtm_use   type              orig_name
  co       72      1        -1       n/a                co
  co2      72      1         0       n/a                co2
!#      GOCART Aerosols
!#    ------ Dust ------  
  du001     72      1         10      dust               DU001
  du002     72      1         10      dust               DU002
  du003     72      1         10      dust               DU003
  du004     72      1         10      dust               DU004
  du005     72      1         10      dust               DU005
!#     ------ Sea-salt ------
  ss001     72      1         10      ssam               SS001
  ss002     72      1         10      sscm1              SS002
  ss003     72      1         10      sscm2              SS003
  ss004     72      1         10      sscm3              SS004
  ss005     72      1         10      sscm4              SS005
!#     ------ Sulfates ------
  so4       72      1         10      sulfate            SO4
!#     ------ Carbonaceous (main) ------
  bcphobic  72      1         10      dry_black_carbon   BCphobic
  bcphilic  72      1         10      wet_black_carbon   BCphilic
  ocphobic  72      1         10      dry_organic_carbon OCphobic
  ocphilic  72      1         10      wet_organic_carbon OCphilic
::
\end{verbatim}
This is what GMAO plans to use in the near future. 

As usual, this table follows INPAK/ESMF convention, begining with a name
(chem\_guess), followed by double colons (::), and ending with double colons.
Any line starting with an exclamation mark or a pound sign is taken as a comment.

The current {\it chem\_guess} table has six columns defined as follows:

\begin{verbatim}
Column 1: variable name - refers to internally known GSI variable name
Column 2: indicates number of levels (used to distinguish between 2d and 3d fields)
Column 3: likely to be redefined sometime soon
Column 4: indicates whether variable is to be passed to CRTM or not according to 
          the following scheme:
            <0    general chem variable; not used in CRTM 
            =0    general chem variable; use prescribed global mean data to affect CRTM
            =1    general chem variable; use variable in guess field to affect CRTM 
            >10   aerosol variable
Column 5: type of chemical/aerosol
Column 6: original name in file where species is read from
\end{verbatim}

\begin{center}
\fbox{Examples of extracting information related to the Chem Bundle}
\end{center}

\underline{Examples} of accessing information related to fields in the Chem Bundle.
\begin{enumerate}
\item Say a routine wants to know how $CO_2$ is to be used in CRTM. 
      This is done via the {\it i4crtm::} tag, as in:
      \begin{verbatim}
      call gsi_chemguess_get ( 'i4crtm::co2', igfsco2, ier )
      \end{verbatim}
       where the value returned {\it igfsco2} is an integer following the 
       scheme laid out for entries in column 4 of the resource file (anavinfo). 

\item Say a routine wants to get the number of all 3d aerosols available in the
      Chem Bundle, this can use the tag {\it aerosols::3d}, as in:
      \begin{verbatim}
      call gsi_chemguess_get ( 'aerosols::3d',n_aerosols,ier )
      \end{verbatim}
      notice this uses the same interface as in the example above, but returns
      information about something else.

\item Say a routine wants the name of all 3d aerosols
      \begin{verbatim}
      call gsi_chemguess_get ('aerosols::3d',aero_names,ier)     
      \end{verbatim}
      now the returned variable {\it aero\_names} is a character array with the 
      names of all 3d-aerosols. Notice it is important to inquire before hand
      about the number of  3d-aerosols available and to properly allocate space
      for the character arrays {\it aero\_names}, and only then make the call above.

\end{enumerate}

More on the other possible mnemonics known by this package can be found in the 
prologue description of the {it get} routines.

\begin{center}
\fbox{Conventions and Remarks}
\end{center}

\underline{Conventions} proposed for entries in this module:
\begin{itemize}
  \item GSI-known variable names should all be lower-case, these are the variables
        defined in column 1 of {\it anavinfo} file.
  \item Only methods should be made public from this module.
  \item New routines should be defined via interface procedure.
\end{itemize}
 
A general remark about the correct {\it chem\_guess} table: it is recognized that
the format for general specification related to specific entries in the table is 
not general enough. A better approach is the one used by the Registry used in
GEOS-5 GOCART where a table exists to control a particular functionality
applicable to a certain set of constituents. For example, use of a variable in
CRTM could be control instead by a specific table listing constituents to be
used in the CRTM and at what extent, for example, a table of the form:
\begin{verbatim}
use_in_crtm::
 !var     use  
  co2      1
  co       0
::
\end{verbatim}
Something of this form should eventually replace some of the columns in the 
{\it chem\_guess} table. 

#endif
!EOI


!-------------------------------------------------------------------------
!  NASA/GSFC, Global Modeling and Assimilation Office, Code 610.1, GMAO  !
!-------------------------------------------------------------------------
!BOP
!  
! !MODULE: ChemguessMod -- Implements Chem Guess capability for GSI
!
! !INTERFACE:

module gsi_chemguess_mod
!
! !DESCRIPTION: Module to handle chemistry fields, tracers, and aerosols.
!               This still uses wired-in type arrays to hold the guess. Soon
!               we'll generalize this.
!
! !REMARKS:
!   1. VERY IMPORTANT: No object from this file is to be make
!                      explicitly available to the outside world.
!                      Each object must be opaque with a get and
!                      a put method associated with it.
!   2. This is still functioning as a common-block when it comes
!      to the chem type itself - needs some work to make it into 
!      a self-contained type
! 
! !USES:

use kinds, only: i_kind,r_kind
use mpimod, only : mype
use mpeu_util,only: die
use file_utility, only : get_lun
use gsi_bundlemod, only : GSI_BundleCreate
use gsi_bundlemod, only : GSI_BundleGetPointer
use gsi_bundlemod, only : GSI_Bundle
use gsi_bundlemod, only : GSI_BundlePrint
use gsi_bundlemod, only : GSI_BundleDestroy

use gsi_bundlemod, only : GSI_Grid
use gsi_bundlemod, only : GSI_GridCreate

use mpeu_util, only: gettablesize
use mpeu_util, only: gettable
use mpeu_util, only: getindex

implicit none
private
save

! ! !PUBLIC MEMBER FUNCTIONS:

public :: gsi_chemguess_create_grids
public :: gsi_chemguess_destroy_grids
public :: gsi_chemguess_init
public :: gsi_chemguess_get
public :: gsi_chemguess_final

public :: GSI_ChemGuess_Bundle   ! still a common for now, ultimately should 
                                 ! be a dynamic "type", passed around in arg list

! !INTERFACE:

interface gsi_chemguess_init
          module procedure init_
end interface
interface gsi_chemguess_final
          module procedure final_ 
end interface
interface gsi_chemguess_create_grids
          module procedure create_
end interface
interface gsi_chemguess_destroy_grids
          module procedure destroy_
end interface
interface gsi_chemguess_get
          module procedure get_int0d_
          module procedure get_char0d_
          module procedure get_char1d_
end interface

type(GSI_Bundle),pointer :: GSI_ChemGuess_Bundle(:)   ! still a common for now


! !REVISION HISTORY:
!
!   20Apr2010 Todling  Initial code.
!   03May2010 Treadon - add iostat error check to ibm_sp read(lu,chemguess) in init_
!   19May2010 Todling - porter Hou's igfsco2 flag from setup namelist to this namelist
!   30May2010 Todling - remove namelist; revamp the way fields/info read in (i90-style)
!   25Jun2010 Treadon - consistently intialize ivar; check/use length of desc (gsi_chemguess_get)
!   07Oct2010 Todling - add entry usrname to differentiate gsi-names w/ in-file names
!   01May2011 Todling - rename module and its bundle for parallelism w/ MetGuess
!
!EOP
!-------------------------------------------------------------------------

! !PRIVATE ROUTINES:
!BOC

integer(i_kind),parameter::MAXSTR=256
logical:: tracer_grid_initialized=.false.
logical:: chem_initialized_=.false.
character(len=*), parameter :: myname = 'gsi_chemguess_mod'

integer(i_kind) :: nbundles=-1
integer(i_kind) :: ntgases=0
integer(i_kind) :: naero=0
integer(i_kind) :: n2daero=0
integer(i_kind) :: n3daero=0
integer(i_kind) :: ng3d=-1
integer(i_kind) :: ng2d=-1
character(len=MAXSTR),allocatable :: tgases(:)     ! same as list above, but each var as element of array
character(len=MAXSTR),allocatable :: tgases3d(:)   ! same as list above, but each var as element of array
character(len=MAXSTR),allocatable :: tgases2d(:)   ! same as list above, but each var as element of array
character(len=MAXSTR),allocatable :: chemtype(:)   ! indicate type of chem (used for aerosols for now)
character(len=MAXSTR),allocatable :: chemty3d(:)   ! indicate 3d type of chem
character(len=MAXSTR),allocatable :: chemty2d(:)   ! indicate 3d type of chem
character(len=MAXSTR),allocatable :: usrname(:)    ! chem user-defined (original) name (in file)
integer(i_kind),allocatable,dimension(:) :: i4crtm ! controls use of gas in CRTM:
                                                   ! < 0 don't use in CRTM
                                                   ! = 0 use predefined global mean co2 mixing ration
                                                   ! = 1 use gfs yearly global annual mean historical co2 value
                                                   ! = 2 use gfs monthly horizontal 2-d historical co2 value
                                                   ! in interval [0,10)  general trace gas
                                                   ! in interval [10,20) indicates aerosol
integer(i_kind),allocatable,dimension(:) :: i4crtm2d ! as above but for 2d fields
integer(i_kind),allocatable,dimension(:) :: i4crtm3d ! as above but for 3d fields

logical:: verbose_=.true.

contains

!-------------------------------------------------------------------------
!BOP
!
! !IROUTINE:  init_ --- Initialize Chem Bundle (read resource table); alloc internal
!
! !INTERFACE:
!
subroutine init_ (iamroot)
! USES:
implicit none
! !INPUT PARAMETER:
   logical,optional,intent(in) :: iamroot 
! !DESCRIPTION: Define contents of Chem Bundle through rc file (typilcally
!               embedded in anavinfo text file.
!
! !REVISION HISTORY:
!   2010-04-10  todling  initial code
!
! !REMARKS:
!   language: f90
!   machine:  discover
!
! !AUTHOR:
!   Ricardo Todling  org: gmao      date: 2010-04-10
!
!EOP
!-------------------------------------------------------------------------
!BOC
!character(len=*),parameter:: rcname='anavinfo.txt'
character(len=*),parameter:: rcname='anavinfo'  ! filename should have extension
character(len=*),parameter:: tbname='chem_guess::'
integer(i_kind) luin,i,ii,ntot,icrtmuse
character(len=256),allocatable,dimension(:):: utable
character(len=20) var,ctype,oname
character(len=*),parameter::myname_=myname//'*init_'
integer(i_kind) ilev, itracer
logical iamroot_

if(chem_initialized_) return

iamroot_=mype==0
if(present(iamroot)) iamroot_=iamroot 

! load file
luin=get_lun()
open(luin,file=rcname,form='formatted')

! Scan file for desired table first
! and get size of table
call gettablesize(tbname,luin,ntot,ntgases)
if(ntgases==0) then
   close(luin)
   return
endif

! Get contents of table
allocate(utable(ntgases))
call gettable(tbname,luin,ntot,ntgases,utable)

! release file unit
close(luin)

! Retrieve each token of interest from table and define
! variables participating in state vector

! Count variables first
ng3d=0; ng2d=0
do ii=1,ntgases
   read(utable(ii),*) var, ilev, itracer, icrtmuse
   if(ilev>1) then
       ng3d=ng3d+1
   else if(ilev==1) then
       ng2d=ng2d+1
   else
       write(6,*) myname_,': error, unknown number of levels'
       call stop2(999)
   endif
enddo

allocate(tgases3d(ng3d),tgases2d(ng2d),&
         chemty3d(ng3d),chemty2d(ng2d),&
         i4crtm3d(ng3d),i4crtm2d(ng2d),&
         i4crtm(ntgases),usrname(ntgases))

! Now load information from table
ng3d=0;ng2d=0
do ii=1,ntgases
   read(utable(ii),*) var, ilev, itracer, icrtmuse, ctype, oname
   if(ilev>1) then
      ng3d=ng3d+1
      tgases3d(ng3d)=trim(adjustl(var))
      chemty3d(ng3d)=trim(adjustl(ctype))
      i4crtm3d(ng3d)=icrtmuse
      if(abs(icrtmuse)>=10.and.abs(icrtmuse)<20) n3daero=n3daero+1 ! convention, for now
   else
      ng2d=ng2d+1
      tgases2d(ng2d)=trim(adjustl(var))
      chemty2d(ng2d)=trim(adjustl(ctype))
      i4crtm2d(ng2d)=icrtmuse
      if(abs(icrtmuse)>=10.and.abs(icrtmuse)<20) n2daero=n2daero+1 ! convention, for now
   endif
   i4crtm  (ii)=icrtmuse
   usrname(ii)=trim(adjustl(oname))
   if(abs(icrtmuse)>=10.and.abs(icrtmuse)<20) naero=naero+1 ! convention, for now
enddo

deallocate(utable)

allocate(tgases(ntgases),chemtype(ntgases))

! Fill in array w/ all var names (must be 3d first, then 2d)
ii=0
do i=1,ng3d
   ii=ii+1
   tgases(ii)=tgases3d(i)
   chemtype(ii)=trim(adjustl(chemty3d(i)))
enddo
do i=1,ng2d
   ii=ii+1
   tgases(ii)=tgases2d(i)
   chemtype(ii)=trim(adjustl(chemty2d(i)))
enddo

if (iamroot_) then
   write(6,*) myname_,':  2D-CHEM STATE VARIABLES: '
   do i=1,ng2d
      write(6,*) trim(tgases2d(i))
   enddo
   write(6,*) myname_,':  3D-CHEM STATE VARIABLES:'
   do i=1,ng3d
      write(6,*) trim(tgases3d(i))
   enddo
   write(6,*) myname_,': ALL CHEM STATE VARIABLES:'
   do i=1,ntgases
      write(6,*) trim(tgases(i))
   enddo
end if
chem_initialized_=.true.

end subroutine init_
!EOC

!-------------------------------------------------------------------------
!BOP
!
! !IROUTINE:  final_ --- Deallocate internal Chem Bundle info arrays
!
! !INTERFACE:
!
subroutine final_
implicit none

! !DESCRIPTION: Dealloc grids holding trace gases
!
! !REVISION HISTORY:
!   2010-04-10  todling  initial code
!
! !REMARKS:
!   language: f90
!   machine:  discover
!
! !AUTHOR:
!   Ricardo Todling  org: gmao      date: 2010-04-10
!
!EOP
!-------------------------------------------------------------------------
!BOC
if(.not.chem_initialized_) return
deallocate(tgases)
deallocate(tgases3d,tgases2d,i4crtm,i4crtm3d,i4crtm2d,chemty3d,chemty2d,chemtype,usrname)
chem_initialized_=.false.
end subroutine final_
!EOC

!-------------------------------------------------------------------------
!BOP
!
! !IROUTINE:  create_ --- Allocate grid and bundle holding chem guess
!
! !INTERFACE:
!
!!subroutine create_(GSI_ChemGuess_Bundle,im,jm,km,lm,istatus) ! ultimately
  subroutine create_(im,jm,km,lm,istatus)

! !USES:

    use constants,only: zero
    implicit none

! !INPUT PARAMETERS:
    integer(i_kind),intent(in)::im,jm,km,lm

! !OUTPUT PARAMETERS:
    integer(i_kind),intent(out)::istatus

! !INPUT/OUTPUT PARAMETERS:
!!  type(GSI_Bundle) :: GSI_ChemGuess_Bundle

! !DESCRIPTION: allocate grids to hold guess cloud fields
!
! !REVISION HISTORY:
!   2010-04-20  todling  initial code
!   2010-05-17  todling  update create interface to pass a grid
!   2011-07-03  todling  allow running single or double precision
!
! !AUTHOR:
!   Ricardo Todling  org: gmao      date: 2010-04-10
!
!EOP
!-------------------------------------------------------------------------
!BOC

    character(len=*), parameter :: myname_ = myname//'*create_'
    integer(i_kind) i,j,k,n,nt,ic
    character(len=MAXSTR) :: var
    type(GSI_Grid):: grid

    istatus=0
    if(ntgases<=0) return

    if(tracer_grid_initialized) return

!   Create simple regular grid
    call gsi_gridcreate ( grid, im, jm, km )

    nbundles = lm
    allocate(GSI_ChemGuess_Bundle(nbundles))
    do nt=1,nbundles
       call GSI_BundleCreate ( GSI_ChemGuess_Bundle(nt), grid, 'Trace Gases', istatus, &
                               names3d=tgases3d,bundle_kind=r_kind ) ! only 3d for now
    enddo

    if (istatus/=0) then
        if(mype==0) write(6,*)trim(myname_),':  allocate error1, istatus=',&
                              istatus,im,jm,km,lm
        return
    endif

    if (verbose_) then
       if(mype==0) write(6,*) trim(myname_),': alloc() for chem-tracer done'
    endif
    tracer_grid_initialized=.true.

    return
  end subroutine create_
!EOC

!-------------------------------------------------------------------------
!BOP
!
! !IROUTINE:  destroy_ --- Deallocate grid and bundle holding chem guess
!
! !INTERFACE:
!
!!subroutine destroy_ (GSI_ChemGuess_Bundle, istatus) ! ultimately
  subroutine destroy_ (istatus)

! !USES:
    implicit none

! !INPUT PARAMETERS:

! !OUTPUT PARAMETERS:
  integer(i_kind), intent(out) :: istatus

! !INPPUT/OUTPUT PARAMETERS:
!!  type(GSI_Bundle) :: GSI_ChemGuess_Bundle

! !DESCRIPTION: Dealloc grids holding trace gases
!
! !REVISION HISTORY:
!   2010-04-10  todling  initial code
!
! !REMARKS:
!   language: f90
!   machine:  discover
!
! !AUTHOR:
!   Ricardo Todling  org: gmao      date: 2010-04-10
!
!EOP
!-------------------------------------------------------------------------
!BOC

    character(len=*), parameter :: myname_ = myname//'*destroy_'
    integer(i_kind) :: nt
    character(len=MAXSTR) :: var
    istatus=0

    if(.not.tracer_grid_initialized) return

     do nt=1,nbundles
        call GSI_BundleDestroy ( GSI_ChemGuess_Bundle(nt), istatus )
     enddo
     deallocate(GSI_ChemGuess_Bundle,stat=istatus)

    if (istatus/=0) then
        if(mype==0) write(6,*)trim(myname_),':  deallocate error1, istatus=',istatus
        return
    endif

    if (verbose_) then
       if(mype==0) write(6,*) trim(myname_),': dealloc() for chem-tracer done'
    endif
    tracer_grid_initialized=.false.

    return
  end subroutine destroy_
!EOC

! ----------------------------------------------------------
! From here down, inquiry function to make all object opaque
! ----------------------------------------------------------

!-------------------------------------------------------------------------
!BOP
!
! !IROUTINE:  get_int0d_ --- inquire rank-0 integer
!
! !INTERFACE:
  subroutine get_int0d_ ( desc, ivar, istatus )

! !USES:
  implicit none
!
! !DESCRIPTION: Rank-0 integer inquire routine; integer mnemonics:
! \begin{verbatim}
!      Known mnemonics        retrieve
!      ---------------        --------
!      dim                    total number of gases 
!      aerosols               number of aerosols
!      aerosols::3d           number of 3d aerosols
!      aerosols::2d           number of 2d aerosols
!      i4crtm::XXX            information related to CRTM usage of gas XXX
!      var::XXX               index of gas XXX in chem-bundle
! 
! \end{verbatim}
!  where XXX represents the name of the gas of interest. 
!
! !REVISION HISTORY:
!   2010-04-10  todling  initial code
!   2011-05-17  todling  protect against use of unavailable label
!
! !REMARKS:
!   language: f90
!   machine:  discover
!
! !AUTHOR:
!   Ricardo Todling  org: gmao      date: 2010-04-10
!
!EOP
!-------------------------------------------------------------------------
!BOC
  character(len=*),intent(in):: desc
  integer(i_kind),intent(out):: ivar
  integer(i_kind),intent(out):: istatus
  character(len=*),parameter::myname_=myname//'*get_int0d_'
  character(len=MAXSTR):: work
  integer(i_kind) ii,id,ln
  istatus=1
  ivar=0
  if(trim(desc)=='dim') then
     ivar = ntgases
     istatus=0
  else if(trim(desc)=='aerosols') then
     ivar = naero
     istatus=0
  else if(trim(desc)=='aerosols::3d') then
     ivar = n3daero
     istatus=0
  else if(trim(desc)=='aerosols::2d') then
     ivar = n2daero
     istatus=0
  else if(trim(desc)=='aerosols_4crtm::3d') then
     do ii=1,ng3d
        if (i4crtm3d(ii)==12) ivar=ivar+1
     enddo
     istatus=0
  else if(index(trim(desc),'i4crtm::')/=0) then
     ln=len_trim(desc)
     work=desc(9:ln)
     if(allocated(tgases)) then
        id=getindex(tgases,trim(work))
        if(id>0) ivar=i4crtm(id)
     else
        ivar=0
     endif
     istatus=0
  else if(desc(1:5)=='var::') then
     if(allocated(tgases)) then
        id=len_trim(desc)
        if(id>=6) ivar=getindex(tgases,desc(6:id))
     endif
     istatus=0
  else
     call die(myname_,'label unavailable :'//trim(desc),99)
  endif
  return
  end subroutine get_int0d_
!EOC

!-------------------------------------------------------------------------
!BOP
!
! !IROUTINE:  get_char0d_ --- inquire rank-0 character 
!
! !INTERFACE:
  subroutine get_char0d_ ( desc, ivar, istatus )
! !USES:
  implicit none
!
! !DESCRIPTION: Character-string mnemonics (rank-0):
! \begin{verbatim}
!      Known mnemonics        retrieve
!      ---------------        --------
!      list                   list of all gases
!      list::aerolols         list of aerosols only
!      list::tracers          list of trace gases (non-aerosols) only
! 
! \end{verbatim}
!  where XXX represents the name of the gas of interest. 
!
! !REVISION HISTORY:
!   2010-04-10  todling  initial code
!   2011-05-17  todling  protect against use of unavailable label
!
! !REMARKS:
!   language: f90
!   machine:  discover
!
! !AUTHOR:
!   Ricardo Todling  org: gmao      date: 2010-04-10
!
!EOP
!-------------------------------------------------------------------------
!BOC
  character(len=*),intent(in):: desc
  character(len=*),intent(out):: ivar
  integer(i_kind),intent(out):: istatus
  character(len=*),parameter::myname_=myname//'*get_char0d_'
  character(len=MAXSTR):: gaslist
  character(len=MAXSTR),allocatable:: work(:)
  integer(i_kind) is,ie,i,i0
  logical labfound
  labfound=.false.
  istatus=1
  ivar=''
  if(trim(desc)=='list'.or.trim(desc)=='olist') then
     labfound=.true.
     if(ntgases>0) then
        allocate(work(size(tgases)))
        work=tgases
        if(desc(1:1)=='o') work=usrname
        gaslist=trim(work(1))
        do i=2,ntgases
           i0=len_trim(gaslist)
           is=i0+1
           ie=is+len_trim(work(i))+1
           gaslist(is:ie)=','//work(i)
        enddo
        if(ntgases>1.and.gaslist(1:1)==',') gaslist=gaslist(2:ie)
        ivar = trim(gaslist)
        if(ivar/='') istatus=0
        deallocate(work)
     endif
  endif
  if(trim(desc)=='list::aerosols'.or.trim(desc)=='olist::aerosols') then
     labfound=.true.
     if(naero>0) then
        allocate(work(size(tgases)))
        work=tgases
        if(desc(1:1)=='o') work=usrname
        gaslist=''
        if(abs(i4crtm(1))>=10.and.abs(i4crtm(1))<20) gaslist=trim(work(1))
        do i=2,ntgases
           if(abs(i4crtm(i))>=10.and.abs(i4crtm(i))<20) then
              i0=len_trim(gaslist)
              is=i0+1
              ie=is+len_trim(work(i))+1
              gaslist(is:ie)=','//work(i)
           endif
        enddo
        if(ntgases>1.and.gaslist(1:1)==',') gaslist=gaslist(2:ie)
        ivar = trim(gaslist)
        if(ivar/='') istatus=0
        deallocate(work)
     endif
  endif
  if(trim(desc)=='list::tracers'.or.trim(desc)=='olist::tracers') then
     labfound=.true.
     if(ntgases>0) then
        allocate(work(size(tgases)))
        work=tgases
        if(desc(1:1)=='o') work=usrname
        gaslist=''
        if(abs(i4crtm(1))>=0.and.abs(i4crtm(1))<10) gaslist=trim(work(1))
        do i=2,ntgases
           if(abs(i4crtm(i))>=0.and.abs(i4crtm(i))<10) then
              i0=len_trim(gaslist)
              is=i0+1
              ie=is+len_trim(work(i))+1
              gaslist(is:ie)=','//work(i)
           endif
        enddo
        if(ntgases>1.and.gaslist(1:1)==',') gaslist=gaslist(2:ie)
        ivar = trim(gaslist)
        if(ivar/='') istatus=0
        deallocate(work)
     endif
  endif
  if (.not.labfound) then
     call die(myname_,'label unavailable :'//trim(desc),99)
  endif
  end subroutine get_char0d_
!EOC

!-------------------------------------------------------------------------
!BOP
!
! !IROUTINE:  get_char1d_ --- inquire rank-1 character 
!
! !INTERFACE:
  subroutine get_char1d_ ( desc, ivar, istatus )
! !USES:
  implicit none
!
! !DESCRIPTION: Rank-1 character inquire routine; character mnemonics:
! \begin{verbatim}
!      Known mnemonics        retrieve
!      ---------------        --------
!      gsinames               list of all trace gas names as known in GSI
!      usrnames               list of all user-defined gas names
!      aerosols               list of all aerosols
!      aerosols::3d           list of 3d aerosols
!      aerosols::2d           list of 2d aerosols
!      aerosols_4crtm::3d     list of 3d aerosols to be fed to CRTM
! 
! \end{verbatim}
!  where XXX represents the name of the gas of interest. 
!
! !REVISION HISTORY:
!   2010-04-10  todling  initial code
!   2011-04-06  ho-chung fix return status code
!   2011-05-17  todling  protect against use of unavailable label
!
! !REMARKS:
!   language: f90
!   machine:  discover
!
! !AUTHOR:
!   Ricardo Todling  org: gmao      date: 2010-04-10
!
!EOP
!-------------------------------------------------------------------------
!BOC
  character(len=*),intent(in):: desc
  character(len=*),intent(out):: ivar(:)
  integer(i_kind),intent(out):: istatus
  character(len=*),parameter::myname_=myname//'*get_char0d_'
  integer(i_kind) i,ii
  logical labfound
  labfound=.false.
  istatus=1
  ivar=''
  if(trim(desc)=='gsinames') then
     labfound=.true.
     if(size(ivar)>=size(tgases)) then
        if(allocated(tgases))then
          ivar = tgases
          istatus=0
        endif
     endif
  endif
  if(trim(desc)=='usrnames') then
     labfound=.true.
     if(size(ivar)>=size(usrname)) then
        if(allocated(usrname))then
          ivar = usrname
          istatus=0
        endif
     endif
  endif
  if(trim(desc)=='aerosols') then
     labfound=.true.
     if(size(ivar)>=naero) then
        ii=0
        do i=1,ntgases
           if(abs(i4crtm(i))>=10.and.abs(i4crtm(i))<20) then
              ii=ii+1
              ivar(ii)=tgases(ii) 
           endif
        enddo
        if(ii>0) istatus=0
     endif
  endif
  if(trim(desc)=='aerosols_4crtm::3d') then
     labfound=.true.
     if(size(ivar)>0) then
        ii=0
        do i=1,ng3d
           if(i4crtm3d(i)==12) then
              ii=ii+1
              ivar(ii)=tgases3d(i)
           endif
        enddo
        if(ii>0) istatus=0
     endif
  endif
  if(trim(desc)=='aerosols::3d') then
     labfound=.true.
     if(size(ivar)>=naero) then
        ii=0
        do i=1,ng3d
           if(abs(i4crtm3d(i))>=10.and.abs(i4crtm3d(i))<20) then
              ii=ii+1
              ivar(ii)=tgases3d(i) 
           endif
        enddo
        if(ii>0) istatus=0
     endif
  endif
  if(trim(desc)=='aerosols::2d') then
     labfound=.true.
     if(size(ivar)>=naero) then
        ii=0
        do i=1,ng2d
           if(abs(i4crtm2d(i))>=10.and.abs(i4crtm2d(i))<20) then
              ii=ii+1
              ivar(ii)=tgases2d(i) 
           endif
        enddo
        if(ii>0) istatus=0
     endif
  endif
  if (.not.labfound) then
     call die(myname_,'label unavailable :'//trim(desc),99)
  endif
  end subroutine get_char1d_
end module gsi_chemguess_mod
!EOC
