CMake netCDF Compatibility with WPS (#2121)
[WRF.git] / phys / module_cam_constituents.F
blob96991dcfbb8aba1d982399e46925449790b1922e
1 #define WRF_PORT
2 #define MODAL_AERO
3 ! Updated to CESM1.0.3 (CAM5.1.01) by Balwinder.Singh@pnnl.gov
4 module constituents
6 !----------------------------------------------------------------------------------------------
7
8 ! Purpose: Contains data and functions for manipulating advected and non-advected constituents.
10 ! Revision history:
11 !             B.A. Boville    Original version
12 ! June 2003   P. Rasch        Add wet/dry m.r. specifier
13 ! 2004-08-28  B. Eaton        Add query function to allow turning off the default CAM output of
14 !                             constituents so that chemistry module can make the outfld calls.
15 !                             Allow cnst_get_ind to return without aborting when constituent not
16 !                             found.
17 ! 2006-10-31  B. Eaton        Remove 'non-advected' constituent functionality.
18 !----------------------------------------------------------------------------------------------
19   use shr_kind_mod, only: r8 => shr_kind_r8
20   use physconst,    only: r_universal
22 #ifndef WRF_PORT 
23   use spmd_utils,   only: masterproc
24   use abortutils,   only: endrun
25   use cam_logfile,  only: iulog
26 #else
27   use module_cam_support,   only: masterproc,endrun,iulog,pcnst =>pcnst_runtime
28 #endif
29   implicit none
30   private
31   save
33 ! Public interfaces
35   public cnst_add             ! add a constituent to the list of advected constituents
36   public cnst_num_avail       ! returns the number of available slots in the constituent array
37   public cnst_get_ind         ! get the index of a constituent
38   public cnst_get_type_byind  ! get the type of a constituent
39   public cnst_get_type_byname ! get the type of a constituent
40   public cnst_read_iv         ! query whether constituent initial values are read from initial file
41   public cnst_chk_dim         ! check that number of constituents added equals dimensions (pcnst)
42   public cnst_cam_outfld      ! Returns true if default CAM output was specified in the cnst_add calls.
44 ! Public data
45 #ifndef WRF_PORT 
46   integer, parameter, public :: pcnst  = PCNST      ! number of advected constituents (including water vapor)
48   character(len=16), public :: cnst_name(pcnst)     ! constituent names
49   character(len=128),public :: cnst_longname(pcnst) ! long name of constituents
50 #else
51   character(len=16),allocatable, public :: cnst_name(:)     ! constituent names
52   character(len=128),allocatable,public :: cnst_longname(:) ! long name of constituents
53 #endif
55 ! Namelist variables
56   logical, public :: readtrace = .true.             ! true => obtain initial tracer data from IC file
59 ! Constants for each tracer
60 #ifndef WRF_PORT  
61   real(r8),    public :: cnst_cp  (pcnst)          ! specific heat at constant pressure (J/kg/K)
62   real(r8),    public :: cnst_cv  (pcnst)          ! specific heat at constant volume (J/kg/K)
63   real(r8),    public :: cnst_mw  (pcnst)          ! molecular weight (kg/kmole)
64   character*3, public :: cnst_type(pcnst)          ! wet or dry mixing ratio
65   real(r8),    public :: cnst_rgas(pcnst)          ! gas constant ()
66   real(r8),    public :: qmin     (pcnst)          ! minimum permitted constituent concentration (kg/kg)
67   real(r8),    public :: qmincg   (pcnst)          ! for backward compatibility only
68   logical,     public :: cnst_fixed_ubc(pcnst) = .false.  ! upper bndy condition = fixed ?
69 #else
70 real(r8),      allocatable, public :: cnst_cp  (:)          ! specific heat at constant pressure (J/kg/K)
71   real(r8),    allocatable, public :: cnst_cv  (:)          ! specific heat at constant volume (J/kg/K)
72   real(r8),    allocatable, public :: cnst_mw  (:)          ! molecular weight (kg/kmole)
73   character*3, allocatable, public :: cnst_type(:)          ! wet or dry mixing ratio
74   real(r8),    allocatable, public :: cnst_rgas(:)          ! gas constant ()
75   real(r8),    allocatable, public :: qmin     (:)          ! minimum permitted constituent concentration (kg/kg)
76   real(r8),    allocatable, public :: qmincg   (:)          ! for backward compatibility only
77   logical,     allocatable, public :: cnst_fixed_ubc(:)     ! upper bndy condition = fixed ?
78 #endif
80 !++bee - temporary... These names should be declared in the module that makes the addfld and outfld calls.
81 ! Lists of tracer names and diagnostics
82 #ifndef WRF_PORT  
83    character(len=16), public :: apcnst    (pcnst)   ! constituents after physics  (FV core only)
84    character(len=16), public :: bpcnst    (pcnst)   ! constituents before physics (FV core only)
85    character(len=16), public :: hadvnam   (pcnst)   ! names of horizontal advection tendencies
86    character(len=16), public :: vadvnam   (pcnst)   ! names of vertical advection tendencies
87    character(len=16), public :: dcconnam  (pcnst)   ! names of convection tendencies
88    character(len=16), public :: fixcnam   (pcnst)   ! names of species slt fixer tendencies
89    character(len=16), public :: tendnam   (pcnst)   ! names of total tendencies of species
90    character(len=16), public :: ptendnam  (pcnst)   ! names of total physics tendencies of species
91    character(len=16), public :: dmetendnam(pcnst)   ! names of dme adjusted tracers (FV)
92    character(len=16), public :: sflxnam   (pcnst)   ! names of surface fluxes of species
93    character(len=16), public :: tottnam   (pcnst)   ! names for horz + vert + fixer tendencies
94 #else
95    character(len=16), allocatable, public :: apcnst    (:)   ! constituents after physics  (FV core only)
96    character(len=16), allocatable, public :: bpcnst    (:)   ! constituents before physics (FV core only)
97    character(len=16), allocatable, public :: hadvnam   (:)   ! names of horizontal advection tendencies
98    character(len=16), allocatable, public :: vadvnam   (:)   ! names of vertical advection tendencies
99    character(len=16), allocatable, public :: dcconnam  (:)   ! names of convection tendencies
100    character(len=16), allocatable, public :: fixcnam   (:)   ! names of species slt fixer tendencies
101    character(len=16), allocatable, public :: tendnam   (:)   ! names of total tendencies of species
102    character(len=16), allocatable, public :: ptendnam  (:)   ! names of total physics tendencies of species
103    character(len=16), allocatable, public :: dmetendnam(:)   ! names of dme adjusted tracers (FV)
104    character(len=16), allocatable, public :: sflxnam   (:)   ! names of surface fluxes of species
105    character(len=16), allocatable, public :: tottnam   (:)   ! names for horz + vert + fixer tendencies
106 #endif
108 ! Private data
110   integer :: padv = 0                      ! index pointer to last advected tracer
111 #ifndef WRF_PORT
112   logical :: read_init_vals(pcnst)         ! true => read initial values from initial file
113   logical :: cam_outfld_(pcnst)            ! true  => default CAM output of constituents in kg/kg
114                                            ! false => chemistry is responsible for making outfld
115                                            !          calls for constituents
116 #else
117   logical, allocatable :: read_init_vals(:)         ! true => read initial values from initial file
118   logical, allocatable :: cam_outfld_(:)            ! true  => default CAM output of constituents in kg/kg
119                                            ! false => chemistry is responsible for making outfld
120                                            !          calls for constituents
121 #endif
123 !==============================================================================================
124 CONTAINS
125 !==============================================================================================
127   subroutine cnst_add (name, mwc, cpc, qminc, &
128                        ind, longname, readiv, mixtype, cam_outfld, fixed_ubc)
129 !----------------------------------------------------------------------- 
131 ! Purpose: Register a constituent to be advected by the large scale winds and transported by
132 !          subgrid scale processes.
134 !---------------------------------------------------------------------------------
136     character(len=*), intent(in) :: &
137        name      ! constituent name used as variable name in history file output (8 char max)
138     real(r8),intent(in)    :: mwc    ! constituent molecular weight (kg/kmol)
139     real(r8),intent(in)    :: cpc    ! constituent specific heat at constant pressure (J/kg/K)
140     real(r8),intent(in)    :: qminc  ! minimum value of mass mixing ratio (kg/kg)
141                                      ! normally 0., except water 1.E-12, for radiation.
142     integer, intent(out)   :: ind    ! global constituent index (in q array)
144     character(len=*), intent(in), optional :: &
145        longname    ! value for long_name attribute in netcdf output (128 char max, defaults to name)
146     logical,          intent(in), optional :: &
147        readiv      ! true => read initial values from initial file (default: true)
148     character(len=*), intent(in), optional :: &
149        mixtype     ! mixing ratio type (dry, wet)
150     logical,          intent(in), optional :: &
151        cam_outfld  ! true => default CAM output of constituent in kg/kg
152     logical,          intent(in), optional :: &
153        fixed_ubc ! true => const has a fixed upper bndy condition
155 !-----------------------------------------------------------------------
156 #ifdef WRF_PORT
157     !Allocate local arrays    
158     if(.NOT. allocated(read_init_vals)) allocate(read_init_vals(pcnst))
159     if(.NOT. allocated(cam_outfld_)) allocate(cam_outfld_(pcnst))
160 #endif
161 ! set tracer index and check validity, advected tracer
162     padv = padv+1
163     ind  = padv
164     if (padv > pcnst) then
165        write(iulog,*) 'CNST_ADD: advected tracer index greater than pcnst = ', pcnst
166 #ifdef WRF_PORT
167        call wrf_message(iulog)
168 #endif
169        call endrun
170     end if
172 ! set tracer name and constants
173     cnst_name(ind) = name
174     if ( present(longname) )then
175        cnst_longname(ind) = longname
176     else
177        cnst_longname(ind) = name
178     end if
180 ! set whether to read initial values from initial file
181     if ( present(readiv) ) then
182        read_init_vals(ind) = readiv
183     else
184        read_init_vals(ind) = readtrace
185     end if
187 ! set constituent mixing ratio type
188     if ( present(mixtype) )then
189        cnst_type(ind) = mixtype
190     else
191        cnst_type(ind) = 'wet'
192     end if
194 ! set outfld type 
195 ! (false: the module declaring the constituent is responsible for outfld calls)
196     if ( present(cam_outfld) ) then
197        cam_outfld_(ind) = cam_outfld
198     else
199        cam_outfld_(ind) = .true.
200     end if
202 ! set upper boundary condition type
203     if ( present(fixed_ubc) ) then
204        cnst_fixed_ubc(ind) = fixed_ubc
205     else
206        cnst_fixed_ubc(ind) = .false.
207     end if
209     cnst_cp  (ind) = cpc
210     cnst_mw  (ind) = mwc
211     qmin     (ind) = qminc
212     qmincg   (ind) = qminc
213     if (ind == 1) qmincg = 0._r8  ! This crap is replicate what was there before ****
215     cnst_rgas(ind) = r_universal * mwc
216     cnst_cv  (ind) = cpc - cnst_rgas(ind)
218     return
219   end subroutine cnst_add
221 !==============================================================================
223   function cnst_num_avail()
225      ! return number of available slots in the constituent array
227      integer cnst_num_avail
229      cnst_num_avail = pcnst - padv
231   end function cnst_num_avail
233 !==============================================================================
235   subroutine cnst_get_ind (name, ind, abort)
236 !----------------------------------------------------------------------- 
238 ! Purpose: Get the index of a constituent 
240 ! Author:  B.A. Boville
242 #ifdef WRF_PORT
243     use module_cam_support, only: lower_case, pcnst_runtime
244 #endif
245 !-----------------------------Arguments---------------------------------
247     character(len=*),  intent(in)  :: name  ! constituent name
248     integer,           intent(out) :: ind   ! global constituent index (in q array)
249     logical, optional, intent(in)  :: abort ! optional flag controlling abort
251 !---------------------------Local workspace-----------------------------
252     integer :: m                                   ! tracer index
253     logical :: abort_on_error
254 #ifdef WRF_PORT
255     character(len=32) :: name_in, name_in_lc, name_cnst_lc
256     integer           :: idone
257 #endif
258 !-----------------------------------------------------------------------
260 ! Find tracer name in list
261 #ifndef WRF_PORT
262     do m = 1, pcnst
263        if (name == cnst_name(m)) then
264           ind  = m
265           return
266        end if
267     end do
268 #else
269     name_in = name
270     call lower_case( name_in, name_in_lc )
271     idone = 0
272     do while (idone < 2)
273        do m = 1, pcnst_runtime
274           call lower_case( cnst_name(m), name_cnst_lc )
275           if (name_in_lc == name_cnst_lc) then
276              ind = m
277              return
278           end if
279        end do
280        idone = idone + 1
281        ! if name='h2so4' and was not found, try name='sulf'
282        if (name_in_lc == 'h2so4') then
283           name_in_lc = 'sulf'
284        else
285           idone = 2
286        end if
287     end do ! while (idone < 2)
288 #endif
289 ! Unrecognized name
290     abort_on_error = .true.
291     if ( present(abort) ) abort_on_error = abort
293     if ( abort_on_error ) then
294        write(iulog,*) 'CNST_GET_IND, name:', name,  ' not found in list:', cnst_name(:)
295 #ifdef WRF_PORT
296        call wrf_message(iulog)
297 #endif
298        call endrun('CNST_GET_IND: name not found')
299     end if
301 ! error return
302     ind = -1
304   end subroutine cnst_get_ind
306 !==============================================================================================
308   character*3 function cnst_get_type_byind (ind)
309 !----------------------------------------------------------------------- 
311 ! Purpose: Get the type of a constituent 
313 ! Method: 
314 ! <Describe the algorithm(s) used in the routine.> 
315 ! <Also include any applicable external references.> 
317 ! Author:  P. J. Rasch
319 !-----------------------------Arguments---------------------------------
321     integer, intent(in)   :: ind    ! global constituent index (in q array)
323 !---------------------------Local workspace-----------------------------
324     integer :: m                                   ! tracer index
326 !-----------------------------------------------------------------------
328     if (ind.le.pcnst) then
329        cnst_get_type_byind = cnst_type(ind)
330     else
331        ! Unrecognized name
332        write(iulog,*) 'CNST_GET_TYPE_BYIND, ind:', ind
333 #ifdef WRF_PORT
334        call wrf_message(iulog)
335 #endif
336        call endrun
337     endif
340   end function cnst_get_type_byind
342 !==============================================================================================
344   character*3 function cnst_get_type_byname (name)
345 !----------------------------------------------------------------------- 
347 ! Purpose: Get the type of a constituent 
349 ! Method: 
350 ! <Describe the algorithm(s) used in the routine.> 
351 ! <Also include any applicable external references.> 
353 ! Author:  P. J. Rasch
355 !-----------------------------Arguments---------------------------------
357     character(len=*), intent(in) :: name ! constituent name
359 !---------------------------Local workspace-----------------------------
360     integer :: m                                   ! tracer index
362 !-----------------------------------------------------------------------
364     do m = 1, pcnst
365        if (name == cnst_name(m)) then
366           cnst_get_type_byname = cnst_type(m)
367           return
368        end if
369     end do
371 ! Unrecognized name
372     write(iulog,*) 'CNST_GET_TYPE_BYNAME, name:', name,  ' not found in list:', cnst_name(:)
373 #ifdef WRF_PORT
374        call wrf_message(iulog)
375 #endif
376     call endrun
378   end function cnst_get_type_byname
380 !==============================================================================
381   function cnst_read_iv(m)
382 !----------------------------------------------------------------------- 
384 ! Purpose: Query whether constituent initial values are read from initial file.
386 ! Author:  B. Eaton
388 !-----------------------------Arguments---------------------------------
390     integer, intent(in) :: m    ! constituent index
392     logical :: cnst_read_iv     ! true => read initial values from inital file
393 !-----------------------------------------------------------------------
395     cnst_read_iv = read_init_vals(m)
396  end function cnst_read_iv
398 !==============================================================================
399   subroutine cnst_chk_dim
400 !----------------------------------------------------------------------- 
402 ! Purpose: Check that the number of registered constituents of each type is the
403 !          same as the dimension
405 ! Method: 
406 ! <Describe the algorithm(s) used in the routine.> 
407 ! <Also include any applicable external references.> 
409 ! Author:  B.A. Boville
411     integer i,m
412 !-----------------------------------------------------------------------
414     if (padv /= pcnst) then
415        write(iulog,*)'CNST_CHK_DIM: number of advected tracer ',padv, ' not equal to pcnst = ',pcnst
416 #ifdef WRF_PORT
417        call wrf_message(iulog)
418 #endif
419        call endrun ()
420     endif
422     if (masterproc) then
423        write(iulog,*) 'Advected constituent list:'
424 #ifdef WRF_PORT
425        call wrf_message(iulog)
426 #endif
427        do i = 1, pcnst
428           write(iulog,'(i4,2x,a8,2x,a128,2x,a3)') i, cnst_name(i), cnst_longname(i), cnst_type(i)
429 #ifdef WRF_PORT
430        call wrf_message(iulog)
431 #endif
432        end do
433     end if
435     ! Set names of advected tracer diagnostics
436     do m=1,pcnst
437        apcnst    (m)  = trim(cnst_name(m))//'AP'
438        bpcnst    (m)  = trim(cnst_name(m))//'BP'
439        hadvnam   (m)  = 'HA'//cnst_name(m)
440        vadvnam   (m)  = 'VA'//cnst_name(m)
441        fixcnam   (m)  = 'DF'//cnst_name(m)
442        tendnam   (m)  = 'TE'//cnst_name(m)
443        ptendnam  (m)  = 'PTE'//cnst_name(m)
444        dmetendnam(m)  = 'DME'//cnst_name(m)
445        tottnam   (m)  = 'TA'//cnst_name(m)
446        sflxnam(m)     = 'SF'//cnst_name(m)
447     end do
450   end subroutine cnst_chk_dim
452 !==============================================================================
454 function cnst_cam_outfld(m)
455 !----------------------------------------------------------------------- 
457 ! Purpose:
458 ! Query whether default CAM outfld calls should be made.
460 !----------------------------------------------------------------------- 
461    integer, intent(in) :: m                ! constituent index
462    logical             :: cnst_cam_outfld  ! true => use default CAM outfld calls
463 !-----------------------------------------------------------------------
465    cnst_cam_outfld = cam_outfld_(m)
467 end function cnst_cam_outfld
469 !==============================================================================
471 end module constituents