3 ! Updated to CESM1.0.3 (CAM5.1.01) by Balwinder.Singh@pnnl.gov
6 !----------------------------------------------------------------------------------------------
8 ! Purpose: Contains data and functions for manipulating advected and non-advected constituents.
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
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
23 use spmd_utils, only: masterproc
24 use abortutils, only: endrun
25 use cam_logfile, only: iulog
27 use module_cam_support, only: masterproc,endrun,iulog,pcnst =>pcnst_runtime
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.
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
51 character(len=16),allocatable, public :: cnst_name(:) ! constituent names
52 character(len=128),allocatable,public :: cnst_longname(:) ! long name of constituents
56 logical, public :: readtrace = .true. ! true => obtain initial tracer data from IC file
59 ! Constants for each tracer
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 ?
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 ?
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
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
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
110 integer :: padv = 0 ! index pointer to last advected tracer
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
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
123 !==============================================================================================
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 !-----------------------------------------------------------------------
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))
161 ! set tracer index and check validity, advected tracer
164 if (padv > pcnst) then
165 write(iulog,*) 'CNST_ADD: advected tracer index greater than pcnst = ', pcnst
167 call wrf_message(iulog)
172 ! set tracer name and constants
173 cnst_name(ind) = name
174 if ( present(longname) )then
175 cnst_longname(ind) = longname
177 cnst_longname(ind) = name
180 ! set whether to read initial values from initial file
181 if ( present(readiv) ) then
182 read_init_vals(ind) = readiv
184 read_init_vals(ind) = readtrace
187 ! set constituent mixing ratio type
188 if ( present(mixtype) )then
189 cnst_type(ind) = mixtype
191 cnst_type(ind) = 'wet'
195 ! (false: the module declaring the constituent is responsible for outfld calls)
196 if ( present(cam_outfld) ) then
197 cam_outfld_(ind) = cam_outfld
199 cam_outfld_(ind) = .true.
202 ! set upper boundary condition type
203 if ( present(fixed_ubc) ) then
204 cnst_fixed_ubc(ind) = fixed_ubc
206 cnst_fixed_ubc(ind) = .false.
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)
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
243 use module_cam_support, only: lower_case, pcnst_runtime
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
255 character(len=32) :: name_in, name_in_lc, name_cnst_lc
258 !-----------------------------------------------------------------------
260 ! Find tracer name in list
263 if (name == cnst_name(m)) then
270 call lower_case( name_in, name_in_lc )
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
281 ! if name='h2so4' and was not found, try name='sulf'
282 if (name_in_lc == 'h2so4') then
287 end do ! while (idone < 2)
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(:)
296 call wrf_message(iulog)
298 call endrun('CNST_GET_IND: name not found')
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
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)
332 write(iulog,*) 'CNST_GET_TYPE_BYIND, ind:', ind
334 call wrf_message(iulog)
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
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 !-----------------------------------------------------------------------
365 if (name == cnst_name(m)) then
366 cnst_get_type_byname = cnst_type(m)
372 write(iulog,*) 'CNST_GET_TYPE_BYNAME, name:', name, ' not found in list:', cnst_name(:)
374 call wrf_message(iulog)
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.
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
406 ! <Describe the algorithm(s) used in the routine.>
407 ! <Also include any applicable external references.>
409 ! Author: B.A. Boville
412 !-----------------------------------------------------------------------
414 if (padv /= pcnst) then
415 write(iulog,*)'CNST_CHK_DIM: number of advected tracer ',padv, ' not equal to pcnst = ',pcnst
417 call wrf_message(iulog)
423 write(iulog,*) 'Advected constituent list:'
425 call wrf_message(iulog)
428 write(iulog,'(i4,2x,a8,2x,a128,2x,a3)') i, cnst_name(i), cnst_longname(i), cnst_type(i)
430 call wrf_message(iulog)
435 ! Set names of advected tracer diagnostics
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)
450 end subroutine cnst_chk_dim
452 !==============================================================================
454 function cnst_cam_outfld(m)
455 !-----------------------------------------------------------------------
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