Line data Source code
1 : module rad_constituents
2 :
3 : !------------------------------------------------------------------------------------------------
4 : !
5 : ! Provide constituent distributions and properties to the radiation and
6 : ! cloud microphysics routines.
7 : !
8 : ! The logic to control which constituents are used in the climate calculations
9 : ! and which are used in diagnostic radiation calculations is contained in this module.
10 : !
11 : !------------------------------------------------------------------------------------------------
12 :
13 : use shr_kind_mod, only: r8 => shr_kind_r8
14 : use spmd_utils, only: masterproc
15 : use ppgrid, only: pcols, pver
16 : use physconst, only: rga
17 : use physics_types, only: physics_state
18 : use phys_control, only: use_simple_phys
19 : use constituents, only: cnst_get_ind
20 : use radconstants, only: nradgas, rad_gas_index
21 : use phys_prop, only: physprop_accum_unique_files, physprop_init, &
22 : physprop_get_id, ot_length
23 : use cam_history, only: addfld, fieldname_len, outfld, horiz_only
24 : use physics_buffer, only: physics_buffer_desc, pbuf_get_field, pbuf_get_index
25 :
26 :
27 : use cam_abortutils, only: endrun
28 : use cam_logfile, only: iulog
29 :
30 : implicit none
31 : private
32 : save
33 :
34 : ! Public interfaces
35 :
36 : public :: &
37 : rad_cnst_readnl, &! read namelist values and parse
38 : rad_cnst_init, &! find optics files and all constituents
39 : rad_cnst_get_info, &! return info about climate/diagnostic lists
40 : rad_cnst_get_mode_idx, &! return mode index of specified mode type
41 : rad_cnst_get_spec_idx, &! return specie index of specified specie type
42 : rad_cnst_get_gas, &! return pointer to mmr for gasses
43 : rad_cnst_get_aer_mmr, &! return pointer to mmr for aerosols
44 : rad_cnst_get_mam_mmr_idx, &! get constituent index of mam specie mmr (climate list only)
45 : rad_cnst_get_aer_props, &! return physical properties for aerosols
46 : rad_cnst_get_mode_props, &! return physical properties for aerosol modes
47 : rad_cnst_get_mode_num, &! return mode number mixing ratio
48 : rad_cnst_get_mode_num_idx, &! get constituent index of mode number m.r. (climate list only)
49 : rad_cnst_out, &! output constituent diagnostics (mass per layer and column burden)
50 : rad_cnst_get_call_list, &! return list of active climate/diagnostic calls to radiation
51 : rad_cnst_get_bin_props_by_idx, &
52 : rad_cnst_get_bin_mmr_by_idx, &
53 : rad_cnst_get_info_by_bin, &
54 : rad_cnst_get_info_by_bin_spec, &
55 : rad_cnst_get_bin_props, &
56 : rad_cnst_get_bin_num, &
57 : rad_cnst_get_bin_num_idx, &
58 : rad_cnst_get_carma_mmr_idx, &
59 : rad_cnst_get_bin_mmr
60 :
61 : public :: rad_cnst_num_name
62 :
63 : integer, parameter :: cs1 = 256
64 : integer, public, parameter :: N_DIAG = 10
65 : character(len=cs1), public :: iceopticsfile, liqopticsfile
66 : character(len=32), public :: icecldoptics,liqcldoptics
67 : logical, public :: oldcldoptics = .false.
68 :
69 : ! Private module data
70 :
71 : ! max number of strings in mode definitions
72 : integer, parameter :: n_mode_str = 120
73 :
74 : ! max number of strings in bin definitions
75 : integer, parameter :: n_bin_str = 640
76 :
77 : ! max number of externally mixed entities in the climate/diag lists
78 : integer, parameter :: n_rad_cnst = N_RAD_CNST
79 :
80 : ! Namelist variables
81 : character(len=cs1), dimension(n_mode_str) :: mode_defs = ' '
82 : character(len=cs1), dimension(n_bin_str) :: bin_defs = ' '
83 : character(len=cs1) :: rad_climate(n_rad_cnst) = ' '
84 : character(len=cs1) :: rad_diag_1(n_rad_cnst) = ' '
85 : character(len=cs1) :: rad_diag_2(n_rad_cnst) = ' '
86 : character(len=cs1) :: rad_diag_3(n_rad_cnst) = ' '
87 : character(len=cs1) :: rad_diag_4(n_rad_cnst) = ' '
88 : character(len=cs1) :: rad_diag_5(n_rad_cnst) = ' '
89 : character(len=cs1) :: rad_diag_6(n_rad_cnst) = ' '
90 : character(len=cs1) :: rad_diag_7(n_rad_cnst) = ' '
91 : character(len=cs1) :: rad_diag_8(n_rad_cnst) = ' '
92 : character(len=cs1) :: rad_diag_9(n_rad_cnst) = ' '
93 : character(len=cs1) :: rad_diag_10(n_rad_cnst) = ' '
94 :
95 : ! type to provide access to the components of a mode
96 : type :: mode_component_t
97 : integer :: nspec
98 : ! For "source" variables below, value is:
99 : ! 'N' if in pbuf (non-advected)
100 : ! 'A' if in state (advected)
101 : character(len= 1) :: source_num_a ! source of interstitial number conc field
102 : character(len= 32) :: camname_num_a ! name registered in pbuf or constituents for number mixing ratio of interstitial species
103 : character(len= 1) :: source_num_c ! source of cloud borne number conc field
104 : character(len= 32) :: camname_num_c ! name registered in pbuf or constituents for number mixing ratio of cloud borne species
105 : character(len= 1), pointer :: source_mmr_a(:) ! source of interstitial specie mmr fields
106 : character(len= 32), pointer :: camname_mmr_a(:) ! name registered in pbuf or constituents for mmr of interstitial components
107 : character(len= 1), pointer :: source_mmr_c(:) ! source of cloud borne specie mmr fields
108 : character(len= 32), pointer :: camname_mmr_c(:) ! name registered in pbuf or constituents for mmr of cloud borne components
109 : character(len= 32), pointer :: type(:) ! specie type (as used in MAM code)
110 : character(len=cs1), pointer :: props(:) ! file containing specie properties
111 : integer :: idx_num_a ! index in pbuf or constituents for number mixing ratio of interstitial species
112 : integer :: idx_num_c ! index in pbuf for number mixing ratio of interstitial species
113 : integer, pointer :: idx_mmr_a(:) ! index in pbuf or constituents for mmr of interstitial species
114 : integer, pointer :: idx_mmr_c(:) ! index in pbuf for mmr of interstitial species
115 : integer, pointer :: idx_props(:) ! ID used to access physical properties of mode species from phys_prop module
116 : end type mode_component_t
117 :
118 : ! type to provide access to all modes
119 : type :: modes_t
120 : integer :: nmodes
121 : character(len= 32), pointer :: names(:) ! names used to identify a mode in the climate/diag lists
122 : character(len= 32), pointer :: types(:) ! type of mode (as used in MAM code)
123 : type(mode_component_t), pointer :: comps(:) ! components which define the mode
124 : end type modes_t
125 :
126 : type(modes_t), target :: modes ! mode definitions
127 :
128 : ! type to provide access to the components of a bin
129 : type :: bin_component_t
130 : integer :: nspec
131 : ! For "source" variables below, value is:
132 : ! 'N' if in pbuf (non-advected)
133 : ! 'A' if in state (advected)
134 : character(len= 1) :: source_num_a ! source of interstitial number conc field
135 : character(len= 32) :: camname_num_a ! name registered in pbuf or constituents for number mixing ratio of interstitial species
136 : character(len= 1) :: source_num_c ! source of cloud borne number conc field
137 : character(len= 32) :: camname_num_c ! name registered in pbuf or constituents for number mixing ratio of cloud borne species
138 :
139 : character(len= 1) :: source_mass_a ! source of interstitial number conc field
140 : character(len= 32) :: camname_mass_a ! name registered in pbuf or constituents for number mixing ratio of interstitial species
141 : character(len= 1) :: source_mass_c ! source of cloud borne number conc field
142 : character(len= 32) :: camname_mass_c ! name registered in pbuf or constituents for number mixing ratio of cloud borne species
143 :
144 : character(len= 1), pointer :: source_mmr_a(:) ! source of interstitial mmr field
145 : character(len= 32), pointer :: camname_mmr_a(:) ! name registered in pbuf or constituents for mmr species
146 : character(len= 1), pointer :: source_mmr_c(:) ! source of cloud borne specie mmr fields
147 : character(len= 32), pointer :: camname_mmr_c(:) ! name registered in pbuf or constituents for mmr of cloud borne components
148 : character(len= 32), pointer :: type(:) ! species type
149 : character(len= 32), pointer :: morph(:) ! species morphology
150 : character(len=cs1), pointer :: props(:) ! file containing specie properties
151 :
152 : integer :: idx_num_a ! index in pbuf or constituents for number mixing ratio of interstitial species
153 : integer :: idx_num_c ! index in pbuf for number mixing ratio of cloud-borne species
154 : integer :: idx_mass_a ! index in pbuf or constituents for mass mixing ratio of interstitial species
155 : integer :: idx_mass_c ! index in pbuf for mass mixing ratio of cloud-borne species
156 :
157 : integer, pointer :: idx_mmr_a(:) ! index in pbuf or constituents for mmr of interstitial species
158 : integer, pointer :: idx_mmr_c(:) ! index in pbuf or constituents for mmr of cloud-borne species
159 : integer, pointer :: idx_props(:) ! ID used to access physical properties of mode species from phys_prop module
160 : end type bin_component_t
161 :
162 : ! type to provide access to all bins
163 : type :: bins_t
164 : integer :: nbins
165 : character(len= 32), pointer :: names(:) ! names used to identify a mode in the climate/diag lists
166 : type(bin_component_t), pointer :: comps(:) ! components which define the mode
167 : end type bins_t
168 :
169 : type(bins_t), target :: bins ! mode definitions
170 :
171 : ! type to provide access to the data parsed from the rad_climate and rad_diag_* strings
172 : type :: rad_cnst_namelist_t
173 : integer :: ncnst
174 : character(len= 1), pointer :: source(:) ! 'A' for state (advected), 'N' for pbuf (non-advected),
175 : ! 'M' for mode, 'Z' for zero
176 : character(len= 64), pointer :: camname(:) ! name registered in pbuf or constituents
177 : character(len=cs1), pointer :: radname(:) ! radname is the name as identfied in radiation,
178 : ! must be one of (rgaslist if a gas) or
179 : ! (/fullpath/filename.nc if an aerosol)
180 : character(len= 1), pointer :: type(:) ! 'A' if aerosol, 'G' if gas, 'M' if mode
181 : end type rad_cnst_namelist_t
182 :
183 : type(rad_cnst_namelist_t) :: namelist(0:N_DIAG) ! gas, bulk aerosol, and modal components used in
184 : ! climate/diagnostic calculations
185 :
186 : logical :: active_calls(0:N_DIAG) ! active_calls(i) is true if the i-th call to radiation is
187 : ! specified. Note that the 0th call is for the climate
188 : ! calculation which is always made.
189 :
190 : ! Storage for gas components in the climate/diagnostic lists
191 :
192 : type :: gas_t
193 : character(len=1) :: source ! A for state (advected), N for pbuf (non-advected), Z for zero
194 : character(len=64) :: camname ! name of constituent in physics state or buffer
195 : character(len=32) :: mass_name ! name for mass per layer field in history output
196 : integer :: idx ! index from constituents or from pbuf
197 : end type gas_t
198 :
199 : type :: gaslist_t
200 : integer :: ngas
201 : character(len=2) :: list_id ! set to " " for climate list, or two character integer
202 : ! (include leading zero) to identify diagnostic list
203 : type(gas_t), pointer :: gas(:) ! dimension(ngas) where ngas = nradgas is from radconstants
204 : end type gaslist_t
205 :
206 : type(gaslist_t), target :: gaslist(0:N_DIAG) ! gasses used in climate/diagnostic calculations
207 :
208 : ! Storage for bulk aerosol components in the climate/diagnostic lists
209 :
210 : type :: aerosol_t
211 : character(len=1) :: source ! A for state (advected), N for pbuf (non-advected), Z for zero
212 : character(len=64) :: camname ! name of constituent in physics state or buffer
213 : character(len=cs1) :: physprop_file ! physprop filename
214 : character(len=32) :: mass_name ! name for mass per layer field in history output
215 : integer :: idx ! index of constituent in physics state or buffer
216 : integer :: physprop_id ! ID used to access physical properties from phys_prop module
217 : end type aerosol_t
218 :
219 : type :: aerlist_t
220 : integer :: numaerosols ! number of aerosols
221 : character(len=2) :: list_id ! set to " " for climate list, or two character integer
222 : ! (include leading zero) to identify diagnostic list
223 : type(aerosol_t), pointer :: aer(:) ! dimension(numaerosols)
224 : end type aerlist_t
225 :
226 : type(aerlist_t), target :: aerosollist(0:N_DIAG) ! list of aerosols used in climate/diagnostic calcs
227 :
228 : ! storage for modal aerosol components in the climate/diagnostic lists
229 :
230 : type :: modelist_t
231 : integer :: nmodes ! number of modes
232 : character(len=2) :: list_id ! set to " " for climate list, or two character integer
233 : ! (include leading zero) to identify diagnostic list
234 : integer, pointer :: idx(:) ! index of the mode in the mode definition object
235 : character(len=cs1), pointer :: physprop_files(:) ! physprop filename
236 : integer, pointer :: idx_props(:) ! index of the mode properties in the physprop object
237 : end type modelist_t
238 :
239 : type(modelist_t), target :: ma_list(0:N_DIAG) ! list of aerosol modes used in climate/diagnostic calcs
240 :
241 : ! storage for modal aerosol components in the climate/diagnostic lists
242 :
243 : type :: binlist_t
244 : integer :: nbins ! number of bins
245 : character(len=2) :: list_id ! set to " " for climate list, or two character integer
246 : ! (include leading zero) to identify diagnostic list
247 : integer, pointer :: idx(:) ! index of the bin in the bin definition object
248 : character(len=cs1), pointer :: physprop_files(:) ! physprop filename
249 : integer, pointer :: idx_props(:) ! index of the bin properties in the physprop object
250 : end type binlist_t
251 :
252 : type(binlist_t), target :: sa_list(0:N_DIAG) ! list of aerosol bins used in climate/diagnostic calcs
253 :
254 : ! values for constituents with requested value of zero
255 : real(r8), allocatable, target :: zero_cols(:,:)
256 :
257 : ! define generic interface routines
258 : interface rad_cnst_get_info
259 : module procedure rad_cnst_get_info
260 : module procedure rad_cnst_get_info_by_mode
261 : module procedure rad_cnst_get_info_by_mode_spec
262 : module procedure rad_cnst_get_info_by_spectype
263 : end interface
264 :
265 : interface rad_cnst_get_aer_mmr
266 : module procedure rad_cnst_get_aer_mmr_by_idx
267 : module procedure rad_cnst_get_mam_mmr_by_idx
268 : end interface
269 :
270 : interface rad_cnst_get_aer_props
271 : module procedure rad_cnst_get_aer_props_by_idx
272 : module procedure rad_cnst_get_mam_props_by_idx
273 : end interface
274 :
275 : logical :: verbose = .true.
276 : character(len=1), parameter :: nl = achar(10)
277 :
278 : integer, parameter :: num_mode_types = 9
279 : integer, parameter :: num_spec_types = 8
280 : character(len=14), parameter :: mode_type_names(num_mode_types) = (/ &
281 : 'accum ', 'aitken ', 'primary_carbon', 'fine_seasalt ', &
282 : 'fine_dust ', 'coarse ', 'coarse_seasalt', 'coarse_dust ', &
283 : 'coarse_strat ' /)
284 : character(len=9), parameter :: spec_type_names(num_spec_types) = (/ &
285 : 'sulfate ', 'ammonium ', 'nitrate ', 'p-organic', &
286 : 's-organic', 'black-c ', 'seasalt ', 'dust '/)
287 :
288 : integer, parameter :: num_bin_morphs = 2
289 : character(len=8), parameter :: bin_morph_names(num_bin_morphs) = &
290 : (/ 'shell ', 'core ' /)
291 :
292 : !==============================================================================
293 : contains
294 : !==============================================================================
295 :
296 1536 : subroutine rad_cnst_readnl(nlfile)
297 :
298 : ! Read rad_cnst_nl namelist group. Parse input.
299 :
300 : use namelist_utils, only: find_group_name
301 : use units, only: getunit, freeunit
302 : use mpishorthand
303 :
304 : character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input
305 :
306 : ! Local variables
307 : integer :: unitn, ierr, i
308 : character(len=2) :: suffix
309 1536 : character(len=1), pointer :: ctype(:)
310 : character(len=*), parameter :: subname = 'rad_cnst_readnl'
311 :
312 : namelist /rad_cnst_nl/ mode_defs, &
313 : bin_defs, &
314 : rad_climate, &
315 : rad_diag_1, &
316 : rad_diag_2, &
317 : rad_diag_3, &
318 : rad_diag_4, &
319 : rad_diag_5, &
320 : rad_diag_6, &
321 : rad_diag_7, &
322 : rad_diag_8, &
323 : rad_diag_9, &
324 : rad_diag_10, &
325 : iceopticsfile, &
326 : liqopticsfile, &
327 : icecldoptics, &
328 : liqcldoptics, &
329 : oldcldoptics
330 :
331 : !-----------------------------------------------------------------------------
332 :
333 0 : if (use_simple_phys) return
334 :
335 1536 : if (masterproc) then
336 2 : unitn = getunit()
337 2 : open( unitn, file=trim(nlfile), status='old' )
338 2 : call find_group_name(unitn, 'rad_cnst_nl', status=ierr)
339 2 : if (ierr == 0) then
340 2 : read(unitn, rad_cnst_nl, iostat=ierr)
341 2 : if (ierr /= 0) then
342 0 : call endrun(subname // ':: ERROR reading namelist')
343 : end if
344 : end if
345 2 : close(unitn)
346 2 : call freeunit(unitn)
347 : end if
348 :
349 : #ifdef SPMD
350 : ! Broadcast namelist variables
351 1536 : call mpibcast (mode_defs, len(mode_defs(1))*n_mode_str, mpichar, 0, mpicom)
352 1536 : call mpibcast (bin_defs, len(bin_defs(1))*n_bin_str, mpichar, 0, mpicom)
353 1536 : call mpibcast (rad_climate, len(rad_climate(1))*n_rad_cnst, mpichar, 0, mpicom)
354 1536 : call mpibcast (rad_diag_1, len(rad_diag_1(1))*n_rad_cnst, mpichar, 0, mpicom)
355 1536 : call mpibcast (rad_diag_2, len(rad_diag_2(1))*n_rad_cnst, mpichar, 0, mpicom)
356 1536 : call mpibcast (rad_diag_3, len(rad_diag_3(1))*n_rad_cnst, mpichar, 0, mpicom)
357 1536 : call mpibcast (rad_diag_4, len(rad_diag_4(1))*n_rad_cnst, mpichar, 0, mpicom)
358 1536 : call mpibcast (rad_diag_5, len(rad_diag_5(1))*n_rad_cnst, mpichar, 0, mpicom)
359 1536 : call mpibcast (rad_diag_6, len(rad_diag_6(1))*n_rad_cnst, mpichar, 0, mpicom)
360 1536 : call mpibcast (rad_diag_7, len(rad_diag_7(1))*n_rad_cnst, mpichar, 0, mpicom)
361 1536 : call mpibcast (rad_diag_8, len(rad_diag_8(1))*n_rad_cnst, mpichar, 0, mpicom)
362 1536 : call mpibcast (rad_diag_9, len(rad_diag_9(1))*n_rad_cnst, mpichar, 0, mpicom)
363 1536 : call mpibcast (rad_diag_10, len(rad_diag_10(1))*n_rad_cnst, mpichar, 0, mpicom)
364 1536 : call mpibcast (iceopticsfile, len(iceopticsfile), mpichar, 0, mpicom)
365 1536 : call mpibcast (liqopticsfile, len(liqopticsfile), mpichar, 0, mpicom)
366 1536 : call mpibcast (liqcldoptics, len(liqcldoptics), mpichar, 0, mpicom)
367 1536 : call mpibcast (icecldoptics, len(icecldoptics), mpichar, 0, mpicom)
368 1536 : call mpibcast (oldcldoptics, 1, mpilog , 0, mpicom)
369 : #endif
370 :
371 : ! Parse the namelist input strings
372 :
373 : ! Mode definition stings
374 1536 : call parse_mode_defs(mode_defs, modes)
375 :
376 : ! Bin definition stings
377 1536 : call parse_bin_defs(bin_defs, bins)
378 :
379 : ! Lists of externally mixed entities for climate and diagnostic calculations
380 18432 : do i = 0,N_DIAG
381 1536 : select case (i)
382 : case(0)
383 1536 : call parse_rad_specifier(rad_climate, namelist(i))
384 : case (1)
385 1536 : call parse_rad_specifier(rad_diag_1, namelist(i))
386 : case (2)
387 1536 : call parse_rad_specifier(rad_diag_2, namelist(i))
388 : case (3)
389 1536 : call parse_rad_specifier(rad_diag_3, namelist(i))
390 : case (4)
391 1536 : call parse_rad_specifier(rad_diag_4, namelist(i))
392 : case (5)
393 1536 : call parse_rad_specifier(rad_diag_5, namelist(i))
394 : case (6)
395 1536 : call parse_rad_specifier(rad_diag_6, namelist(i))
396 : case (7)
397 1536 : call parse_rad_specifier(rad_diag_7, namelist(i))
398 : case (8)
399 1536 : call parse_rad_specifier(rad_diag_8, namelist(i))
400 : case (9)
401 1536 : call parse_rad_specifier(rad_diag_9, namelist(i))
402 : case (10)
403 16896 : call parse_rad_specifier(rad_diag_10, namelist(i))
404 : end select
405 : enddo
406 :
407 : ! were there any constituents specified for the nth diagnostic call?
408 : ! if so, radiation will make a call with those consituents
409 18432 : active_calls(:) = (namelist(:)%ncnst > 0)
410 :
411 : ! Initialize the gas and aerosol lists with the information from the
412 : ! namelist. This is done here so that this information is available via
413 : ! the query functions at the time when the register methods are called.
414 :
415 : ! Set the list_id fields which distinquish the climate and diagnostic lists
416 18432 : do i = 0, N_DIAG
417 18432 : if (active_calls(i)) then
418 1536 : if (i > 0) then
419 0 : write(suffix, fmt = '(i2.2)') i
420 : else
421 1536 : suffix=' '
422 : end if
423 1536 : aerosollist(i)%list_id = suffix
424 1536 : gaslist(i)%list_id = suffix
425 1536 : ma_list(i)%list_id = suffix
426 1536 : sa_list(i)%list_id = suffix
427 : end if
428 : end do
429 :
430 : ! Create a list of the unique set of filenames containing property data
431 :
432 : ! Start with the bulk aerosol species in the climate/diagnostic lists.
433 : ! The physprop_accum_unique_files routine has the side effect of returning the number
434 : ! of bulk aerosols in each list (they're identified by type='A').
435 18432 : do i = 0, N_DIAG
436 18432 : if (active_calls(i)) then
437 : call physprop_accum_unique_files(namelist(i)%radname, namelist(i)%type)
438 : endif
439 : enddo
440 :
441 : ! Add physprop files for the species from the mode definitions.
442 9216 : do i = 1, modes%nmodes
443 15360 : allocate(ctype(modes%comps(i)%nspec))
444 78336 : ctype = 'A'
445 7680 : call physprop_accum_unique_files(modes%comps(i)%props, ctype)
446 9216 : deallocate(ctype)
447 : end do
448 :
449 : ! Add physprop files for the species from the bin definitions.
450 1536 : do i = 1, bins%nbins
451 0 : allocate(ctype(bins%comps(i)%nspec))
452 0 : ctype = 'A'
453 0 : call physprop_accum_unique_files(bins%comps(i)%props, ctype)
454 1536 : deallocate(ctype)
455 : end do
456 :
457 : ! Initialize the gas, bulk aerosol, and modal aerosol lists. This step splits the
458 : ! input climate/diagnostic lists into the corresponding gas, bulk and modal aerosol
459 : ! lists.
460 1536 : if (masterproc) write(iulog,*) nl//subname//': Radiation constituent lists:'
461 18432 : do i = 0, N_DIAG
462 18432 : if (active_calls(i)) then
463 : call list_init1(namelist(i), gaslist(i), aerosollist(i), ma_list(i), sa_list(i))
464 :
465 1538 : if (masterproc .and. verbose) then
466 2 : call print_lists(gaslist(i), aerosollist(i), ma_list(i), sa_list(i))
467 : end if
468 :
469 : end if
470 : end do
471 :
472 1536 : if (masterproc .and. verbose) call print_modes(modes)
473 1536 : if (masterproc .and. verbose) call print_bins(bins)
474 :
475 1536 : end subroutine rad_cnst_readnl
476 :
477 : !================================================================================================
478 :
479 1536 : subroutine rad_cnst_init()
480 :
481 : ! The initialization of the gas and aerosol lists is finished by
482 : ! 1) read the physprop files
483 : ! 2) find the index of each constituent in the constituent or physics buffer arrays
484 : ! 3) find the index of the aerosol constituents used to access its properties from the
485 : ! physprop module.
486 :
487 : integer :: i
488 : logical, parameter :: stricttest = .true.
489 : character(len=*), parameter :: subname = 'rad_cnst_init'
490 : !-----------------------------------------------------------------------------
491 :
492 : ! memory to point to if zero value requested
493 1536 : allocate(zero_cols(pcols,pver))
494 837120 : zero_cols = 0._r8
495 :
496 : ! Allocate storage for the physical properties of each aerosol; read properties from
497 : ! the data files.
498 1536 : call physprop_init()
499 :
500 : ! Start checking that specified radiative constituents are present in the constituent
501 : ! or physics buffer arrays.
502 1536 : if (masterproc) write(iulog,*) nl//subname//': checking for radiative constituents'
503 :
504 : ! Finish initializing the mode definitions.
505 1536 : call init_mode_comps(modes)
506 :
507 : ! Finish initializing the bin definitions.
508 1536 : call init_bin_comps(bins)
509 :
510 : ! Finish initializing the gas, bulk aerosol, and mode lists.
511 18432 : do i = 0, N_DIAG
512 18432 : if (active_calls(i)) then
513 : call list_init2(gaslist(i), aerosollist(i), ma_list(i), sa_list(i))
514 : end if
515 : end do
516 :
517 : ! Check that all gases supported by the radiative transfer code have been specified.
518 : if (stricttest) then
519 13824 : do i = 1, nradgas
520 13824 : if (gaslist(0)%gas(i)%source .eq. 'Z' ) then
521 0 : call endrun(subname//': list of radiative gasses must include all radiation gasses for the climate specication')
522 : endif
523 : enddo
524 : endif
525 :
526 : ! Initialize history output of climate diagnostic quantities
527 1536 : call rad_gas_diag_init(gaslist(0))
528 1536 : call rad_aer_diag_init(aerosollist(0))
529 :
530 :
531 1536 : end subroutine rad_cnst_init
532 :
533 : !================================================================================================
534 :
535 614400 : subroutine rad_cnst_get_gas(list_idx, gasname, state, pbuf, mmr)
536 :
537 : ! Return pointer to mass mixing ratio for the gas from the specified
538 : ! climate or diagnostic list.
539 :
540 : ! Arguments
541 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
542 : character(len=*), intent(in) :: gasname
543 : type(physics_state), target, intent(in) :: state
544 : type(physics_buffer_desc), pointer :: pbuf(:)
545 : real(r8), pointer :: mmr(:,:)
546 :
547 : ! Local variables
548 : integer :: lchnk
549 : integer :: igas
550 : integer :: idx
551 : character(len=1) :: source
552 : type(gaslist_t), pointer :: list
553 : character(len=*), parameter :: subname = 'rad_cnst_get_gas'
554 : !-----------------------------------------------------------------------------
555 :
556 614400 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
557 614400 : list => gaslist(list_idx)
558 : else
559 0 : write(iulog,*) subname//': list_idx =', list_idx
560 0 : call endrun(subname//': list_idx out of bounds')
561 : endif
562 :
563 614400 : lchnk = state%lchnk
564 :
565 : ! Get index of gas in internal arrays. rad_gas_index will abort if the
566 : ! specified gasname is not recognized by the radiative transfer code.
567 614400 : igas = rad_gas_index(trim(gasname))
568 :
569 : ! Get data source
570 614400 : source = list%gas(igas)%source
571 614400 : idx = list%gas(igas)%idx
572 460800 : select case( source )
573 : case ('A')
574 460800 : mmr => state%q(:,:,idx)
575 : case ('N')
576 153600 : call pbuf_get_field(pbuf, idx, mmr)
577 : case ('Z')
578 614400 : mmr => zero_cols
579 : end select
580 :
581 614400 : end subroutine rad_cnst_get_gas
582 :
583 : !================================================================================================
584 :
585 0 : function rad_cnst_num_name(list_idx, spc_name_in, num_name_out, mode_out, spec_out ) result(found)
586 :
587 : ! for a given species name spc_name_in return (optionals):
588 : ! num_name_out -- corresponding number density species name
589 : ! mode_out -- corresponding mode number
590 : ! spec_out -- corresponding species number within the mode
591 :
592 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
593 : character(len=*),intent(in) :: spc_name_in
594 : character(len=*),intent(out):: num_name_out
595 : integer,optional,intent(out):: mode_out
596 : integer,optional,intent(out):: spec_out
597 :
598 : logical :: found
599 :
600 : ! Local variables
601 : type(modelist_t), pointer :: m_list ! local pointer to mode list of interest
602 : integer :: n,m, mm
603 : integer :: nmodes
604 : integer :: nspecs
605 : character(len= 32) :: spec_name
606 :
607 0 : found = .false.
608 :
609 0 : m_list => ma_list(list_idx)
610 0 : nmodes = m_list%nmodes
611 :
612 0 : do n = 1,nmodes
613 0 : mm = m_list%idx(n)
614 0 : nspecs = modes%comps(mm)%nspec
615 0 : do m = 1,nspecs
616 0 : spec_name = modes%comps(mm)%camname_mmr_a(m)
617 0 : if (spc_name_in == spec_name) then
618 0 : num_name_out = modes%comps(mm)%camname_num_a
619 0 : found = .true.
620 0 : if (present(mode_out)) then
621 0 : mode_out = n
622 : endif
623 0 : if (present(spec_out)) then
624 0 : spec_out = m
625 : endif
626 0 : return
627 : endif
628 : enddo
629 : enddo
630 :
631 : return
632 :
633 0 : end function
634 :
635 : !================================================================================================
636 :
637 969216 : subroutine rad_cnst_get_info(list_idx, gasnames, aernames, &
638 : use_data_o3, ngas, naero, nmodes, nbins)
639 :
640 : ! Return info about gas and aerosol lists
641 :
642 : ! Arguments
643 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
644 : character(len=64), optional, intent(out) :: gasnames(:)
645 : character(len=64), optional, intent(out) :: aernames(:)
646 : logical, optional, intent(out) :: use_data_o3
647 : integer, optional, intent(out) :: naero
648 : integer, optional, intent(out) :: ngas
649 : integer, optional, intent(out) :: nmodes
650 : integer, optional, intent(out) :: nbins
651 :
652 : ! Local variables
653 : type(gaslist_t), pointer :: g_list ! local pointer to gas list of interest
654 : type(aerlist_t), pointer :: a_list ! local pointer to aerosol list of interest
655 : type(modelist_t), pointer :: m_list ! local pointer to mode list of interest
656 : type(binlist_t), pointer :: s_list ! local pointer to bin list of interest
657 :
658 : integer :: i
659 : integer :: arrlen ! length of assumed shape array
660 : integer :: gaslen ! length of assumed shape array
661 : integer :: igas ! index of a gas in the gas list
662 : character(len=1) :: source ! A for state, N for pbuf, Z for zero
663 :
664 : character(len=*), parameter :: subname = 'rad_cnst_get_info'
665 : !-----------------------------------------------------------------------------
666 :
667 969216 : g_list => gaslist(list_idx)
668 969216 : a_list => aerosollist(list_idx)
669 969216 : m_list => ma_list(list_idx)
670 969216 : s_list => sa_list(list_idx)
671 :
672 : ! number of bulk aerosols in list
673 969216 : if (present(naero)) then
674 78336 : naero = a_list%numaerosols
675 : endif
676 :
677 : ! number of aerosol modes in list
678 969216 : if (present(nmodes)) then
679 894720 : nmodes = m_list%nmodes
680 : endif
681 :
682 : ! number of aerosol bins in list
683 969216 : if (present(nbins)) then
684 157440 : nbins = s_list%nbins
685 : endif
686 :
687 : ! number of gases in list
688 969216 : if (present(ngas)) then
689 0 : ngas = g_list%ngas
690 : endif
691 :
692 : ! names of aerosols in list
693 969216 : if (present(aernames)) then
694 :
695 : ! check that output array is long enough
696 1536 : arrlen = size(aernames)
697 1536 : if (arrlen < a_list%numaerosols) then
698 0 : write(iulog,*) subname//': ERROR: naero=', a_list%numaerosols, ' arrlen=', arrlen
699 0 : call endrun(subname//': ERROR: aernames too short')
700 : end if
701 :
702 1536 : do i = 1, a_list%numaerosols
703 1536 : aernames(i) = a_list%aer(i)%camname
704 : end do
705 :
706 : end if
707 :
708 : ! names of gas in list
709 969216 : if (present(gasnames)) then
710 :
711 : ! check that output array is long enough
712 0 : gaslen = size(gasnames)
713 0 : if (gaslen < g_list%ngas) then
714 0 : write(iulog,*) subname//': ERROR: ngas=', g_list%ngas, ' gaslen=', gaslen
715 0 : call endrun(subname//': ERROR: gasnames too short')
716 : end if
717 :
718 0 : do i = 1, g_list%ngas
719 0 : gasnames(i) = g_list%gas(i)%camname
720 : end do
721 :
722 : end if
723 :
724 : ! Does the climate calculation use data ozone?
725 969216 : if (present(use_data_o3)) then
726 :
727 : ! get index of O3 in gas list
728 0 : igas = rad_gas_index('O3')
729 :
730 : ! Get data source
731 0 : source = g_list%gas(igas)%source
732 :
733 0 : use_data_o3 = .false.
734 0 : if (source == 'N') use_data_o3 = .true.
735 : endif
736 :
737 969216 : end subroutine rad_cnst_get_info
738 :
739 : !================================================================================================
740 :
741 1037887568 : subroutine rad_cnst_get_info_by_mode(list_idx, m_idx, &
742 0 : mode_type, num_name, num_name_cw, nspec)
743 :
744 : ! Return info about modal aerosol lists
745 :
746 : ! Arguments
747 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
748 : integer, intent(in) :: m_idx ! index of mode in the specified list
749 : character(len=32), optional, intent(out) :: mode_type ! type of mode (as used in MAM code)
750 : character(len=32), optional, intent(out) :: num_name ! name of interstitial number mixing ratio
751 : character(len=32), optional, intent(out) :: num_name_cw ! name of cloud borne number mixing ratio
752 : integer, optional, intent(out) :: nspec ! number of species in the mode
753 :
754 : ! Local variables
755 : type(modelist_t), pointer :: m_list ! local pointer to mode list of interest
756 :
757 : integer :: nmodes
758 : integer :: mm
759 :
760 : character(len=*), parameter :: subname = 'rad_cnst_get_info_by_mode'
761 : !-----------------------------------------------------------------------------
762 :
763 1037887568 : m_list => ma_list(list_idx)
764 :
765 : ! check for valid mode index
766 1037887568 : nmodes = m_list%nmodes
767 1037887568 : if (m_idx < 1 .or. m_idx > nmodes) then
768 0 : write(iulog,*) subname//': ERROR - invalid mode index: ', m_idx
769 0 : call endrun(subname//': ERROR - invalid mode index')
770 : end if
771 :
772 : ! get index into the mode definition object
773 1037887568 : mm = m_list%idx(m_idx)
774 :
775 : ! mode type
776 1037887568 : if (present(mode_type)) then
777 751367504 : mode_type = modes%types(mm)
778 : endif
779 :
780 : ! number of species in the mode
781 1037887568 : if (present(nspec)) then
782 274242048 : nspec = modes%comps(mm)%nspec
783 : endif
784 :
785 : ! name of interstitial number mixing ratio
786 1037887568 : if (present(num_name)) then
787 12293376 : num_name = modes%comps(mm)%camname_num_a
788 : endif
789 :
790 : ! name of cloud borne number mixing ratio
791 1037887568 : if (present(num_name_cw)) then
792 12291840 : num_name_cw = modes%comps(mm)%camname_num_c
793 : endif
794 :
795 969216 : end subroutine rad_cnst_get_info_by_mode
796 :
797 : !================================================================================================
798 :
799 0 : subroutine rad_cnst_get_info_by_bin(list_idx, m_idx, &
800 0 : bin_name, num_name, num_name_cw, mmr_name, mmr_name_cw, nspec)
801 :
802 : ! Return info about CARMA aerosol lists
803 :
804 : ! Arguments
805 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
806 : integer, intent(in) :: m_idx ! index of bin in the specified list
807 : character(len=*), optional, intent(out) :: bin_name
808 : character(len=32), optional, intent(out) :: num_name ! name of interstitial number mixing ratio
809 : character(len=32), optional, intent(out) :: num_name_cw ! name of cloud borne number mixing ratio
810 : character(len=32), optional, intent(out) :: mmr_name ! name of interstitial mass mixing ratio
811 : character(len=32), optional, intent(out) :: mmr_name_cw ! name of cloud borne mass mixing ratio
812 : integer, optional, intent(out) :: nspec ! number of species in the mode
813 :
814 : ! Local variables
815 : type(binlist_t), pointer :: s_list ! local pointer to mode list of interest
816 :
817 : integer :: nbins
818 : integer :: mm
819 :
820 : character(len=*), parameter :: subname = 'rad_cnst_get_info_by_bin'
821 : !-----------------------------------------------------------------------------
822 :
823 0 : s_list => sa_list(list_idx)
824 :
825 : ! check for valid mode index
826 0 : nbins = s_list%nbins
827 0 : if (m_idx < 1 .or. m_idx > nbins) then
828 0 : write(iulog,*) subname//': ERROR - invalid bin index: ', m_idx
829 0 : call endrun(subname//': ERROR - invalid bin index')
830 : end if
831 :
832 : ! get index into the mode definition object
833 0 : mm = s_list%idx(m_idx)
834 :
835 : ! number of species in the mode
836 0 : if (present(nspec)) then
837 0 : nspec = bins%comps(mm)%nspec
838 : endif
839 :
840 : ! bin name
841 0 : if (present(bin_name)) then
842 0 : bin_name = bins%names(m_idx)
843 : end if
844 :
845 : ! name of interstitial number mixing ratio
846 0 : if (present(num_name)) then
847 0 : num_name = bins%comps(mm)%camname_num_a
848 : endif
849 :
850 : ! name of cloud borne number mixing ratio
851 0 : if (present(num_name_cw)) then
852 0 : num_name_cw = bins%comps(mm)%camname_num_c
853 : endif
854 :
855 : ! name of interstitial mass mixing ratio
856 0 : if (present(mmr_name)) then
857 0 : mmr_name = bins%comps(mm)%camname_mass_a
858 : endif
859 :
860 : ! name of cloud borne mass mixing ratio
861 0 : if (present(mmr_name_cw)) then
862 0 : mmr_name_cw = bins%comps(mm)%camname_mass_c
863 : endif
864 :
865 1037887568 : end subroutine rad_cnst_get_info_by_bin
866 :
867 : !================================================================================================
868 0 : subroutine rad_cnst_get_info_by_bin_spec(list_idx, m_idx, s_idx, &
869 0 : spec_type, spec_morph, spec_name, spec_name_cw)
870 :
871 : ! Return info about CARMA aerosol lists
872 :
873 : ! Arguments
874 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
875 : integer, intent(in) :: m_idx ! index of bin in the specified list
876 : integer, intent(in) :: s_idx ! index of species in the specified mode
877 : character(len=32), optional, intent(out) :: spec_type ! type of species
878 : character(len=32), optional, intent(out) :: spec_morph ! type of species
879 : character(len=32), optional, intent(out) :: spec_name ! name of interstitial species
880 : character(len=32), optional, intent(out) :: spec_name_cw ! name of cloud borne species
881 :
882 : ! Local variables
883 : type(binlist_t), pointer :: s_list ! local pointer to mode list of interest
884 : integer :: nbins, nspec
885 : integer :: mm
886 :
887 : character(len=*), parameter :: subname = 'rad_cnst_get_info_by_bin_spec'
888 : !-----------------------------------------------------------------------------
889 :
890 0 : s_list => sa_list(list_idx)
891 :
892 : ! check for valid mode index
893 0 : nbins = s_list%nbins
894 0 : if (m_idx < 1 .or. m_idx > nbins) then
895 0 : write(iulog,*) subname//': ERROR - invalid bin index: ', m_idx
896 0 : call endrun(subname//': ERROR - invalid bin index')
897 : end if
898 :
899 : ! get index into the mode definition object
900 0 : mm = s_list%idx(m_idx)
901 :
902 : ! check for valid species index
903 0 : nspec = bins%comps(mm)%nspec
904 0 : if (s_idx < 1 .or. s_idx > nspec) then
905 0 : write(iulog,*) subname//': ERROR - invalid specie index: ', s_idx
906 0 : call endrun(subname//': ERROR - invalid specie index')
907 : end if
908 :
909 0 : if (present(spec_type)) then
910 0 : spec_type = bins%comps(mm)%type(s_idx)
911 : endif
912 0 : if (present(spec_morph)) then
913 0 : spec_morph = bins%comps(mm)%morph(s_idx)
914 : endif
915 0 : if (present(spec_name)) then
916 0 : spec_name = bins%comps(mm)%camname_mmr_a(s_idx)
917 : endif
918 0 : if (present(spec_name_cw)) then
919 0 : spec_name_cw = bins%comps(mm)%camname_mmr_c(s_idx)
920 : endif
921 :
922 0 : end subroutine rad_cnst_get_info_by_bin_spec
923 :
924 : !================================================================================================
925 2379508006 : subroutine rad_cnst_get_info_by_mode_spec(list_idx, m_idx, s_idx, &
926 0 : spec_type, spec_name, spec_name_cw)
927 :
928 : ! Return info about modal aerosol lists
929 :
930 : ! Arguments
931 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
932 : integer, intent(in) :: m_idx ! index of mode in the specified list
933 : integer, intent(in) :: s_idx ! index of specie in the specified mode
934 : character(len=32), optional, intent(out) :: spec_type ! type of specie
935 : character(len=32), optional, intent(out) :: spec_name ! name of interstitial specie
936 : character(len=32), optional, intent(out) :: spec_name_cw ! name of cloud borne specie
937 :
938 : ! Local variables
939 : type(modelist_t), pointer :: m_list ! local pointer to mode list of interest
940 :
941 : integer :: nmodes
942 : integer :: nspec
943 : integer :: mm
944 :
945 : character(len=*), parameter :: subname = 'rad_cnst_get_info_by_mode_spec'
946 : !-----------------------------------------------------------------------------
947 :
948 2379508006 : m_list => ma_list(list_idx)
949 :
950 : ! check for valid mode index
951 2379508006 : nmodes = m_list%nmodes
952 2379508006 : if (m_idx < 1 .or. m_idx > nmodes) then
953 0 : write(iulog,*) subname//': ERROR - invalid mode index: ', m_idx
954 0 : call endrun(subname//': ERROR - invalid mode index')
955 : end if
956 :
957 : ! get index into the mode definition object
958 2379508006 : mm = m_list%idx(m_idx)
959 :
960 : ! check for valid specie index
961 2379508006 : nspec = modes%comps(mm)%nspec
962 2379508006 : if (s_idx < 1 .or. s_idx > nspec) then
963 0 : write(iulog,*) subname//': ERROR - invalid specie index: ', s_idx
964 0 : call endrun(subname//': ERROR - invalid specie index')
965 : end if
966 :
967 : ! specie type
968 2379508006 : if (present(spec_type)) then
969 2265965350 : spec_type = modes%comps(mm)%type(s_idx)
970 : endif
971 :
972 : ! interstitial specie name
973 2379508006 : if (present(spec_name)) then
974 113608704 : spec_name = modes%comps(mm)%camname_mmr_a(s_idx)
975 : endif
976 :
977 : ! cloud borne specie name
978 2379508006 : if (present(spec_name_cw)) then
979 11340288 : spec_name_cw = modes%comps(mm)%camname_mmr_c(s_idx)
980 : endif
981 :
982 0 : end subroutine rad_cnst_get_info_by_mode_spec
983 :
984 : !================================================================================================
985 :
986 0 : subroutine rad_cnst_get_info_by_spectype(list_idx, spectype, mode_idx, spec_idx)
987 :
988 : ! Return info about modes in the specified climate/diagnostics list
989 :
990 : ! Arguments
991 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
992 : character(len=*), intent(in) :: spectype ! species type
993 : integer, optional, intent(out) :: mode_idx ! index of a mode that contains a specie of spectype
994 : integer, optional, intent(out) :: spec_idx ! index of the species of spectype
995 :
996 : ! Local variables
997 : type(modelist_t), pointer :: m_list ! local pointer to mode list of interest
998 :
999 : integer :: i, nmodes, m_idx, nspec, ispec
1000 : logical :: found_spectype
1001 :
1002 : character(len=*), parameter :: subname = 'rad_cnst_get_info_by_spectype'
1003 : !-----------------------------------------------------------------------------
1004 :
1005 0 : m_list => ma_list(list_idx)
1006 :
1007 : ! number of modes in specified list
1008 0 : nmodes = m_list%nmodes
1009 :
1010 : ! loop through modes in specified climate/diagnostic list
1011 0 : found_spectype = .false.
1012 0 : do i = 1, nmodes
1013 :
1014 : ! get index of the mode in the definition object
1015 0 : m_idx = m_list%idx(i)
1016 :
1017 : ! number of species in the mode
1018 0 : nspec = modes%comps(m_idx)%nspec
1019 :
1020 : ! loop through species looking for spectype
1021 0 : do ispec = 1, nspec
1022 :
1023 0 : if (trim(modes%comps(m_idx)%type(ispec)) == trim(spectype)) then
1024 0 : if (present(mode_idx)) mode_idx = i
1025 0 : if (present(spec_idx)) spec_idx = ispec
1026 0 : found_spectype = .true.
1027 0 : exit
1028 : end if
1029 : end do
1030 :
1031 0 : if (found_spectype) exit
1032 : end do
1033 :
1034 0 : if (.not. found_spectype) then
1035 0 : if (present(mode_idx)) mode_idx = -1
1036 0 : if (present(spec_idx)) spec_idx = -1
1037 : end if
1038 :
1039 2379508006 : end subroutine rad_cnst_get_info_by_spectype
1040 :
1041 : !================================================================================================
1042 :
1043 1536 : function rad_cnst_get_mode_idx(list_idx, mode_type) result(mode_idx)
1044 :
1045 : ! Return mode index of the specified type in the specified climate/diagnostics list.
1046 : ! Return -1 if not found.
1047 :
1048 : ! Arguments
1049 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
1050 : character(len=*), intent(in) :: mode_type ! mode type
1051 :
1052 : ! Return value
1053 : integer :: mode_idx ! mode index
1054 :
1055 : ! Local variables
1056 : type(modelist_t), pointer :: m_list
1057 :
1058 : integer :: i, nmodes, m_idx
1059 :
1060 : character(len=*), parameter :: subname = 'rad_cnst_get_mode_idx'
1061 : !-----------------------------------------------------------------------------
1062 :
1063 : ! if mode type not found return -1
1064 1536 : mode_idx = -1
1065 :
1066 : ! specified mode list
1067 1536 : m_list => ma_list(list_idx)
1068 :
1069 : ! number of modes in specified list
1070 1536 : nmodes = m_list%nmodes
1071 :
1072 : ! loop through modes in specified climate/diagnostic list
1073 7680 : do i = 1, nmodes
1074 :
1075 : ! get index of the mode in the definition object
1076 7680 : m_idx = m_list%idx(i)
1077 :
1078 : ! look in mode definition object (modes) for the mode types
1079 7680 : if (trim(modes%types(m_idx)) == trim(mode_type)) then
1080 1536 : mode_idx = i
1081 1536 : exit
1082 : end if
1083 : end do
1084 :
1085 1536 : end function rad_cnst_get_mode_idx
1086 :
1087 : !================================================================================================
1088 :
1089 0 : function rad_cnst_get_spec_idx(list_idx, mode_idx, spec_type) result(spec_idx)
1090 :
1091 : ! Return specie index of the specified type in the specified mode of the specified
1092 : ! climate/diagnostics list. Return -1 if not found.
1093 :
1094 : ! Arguments
1095 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
1096 : integer, intent(in) :: mode_idx ! mode index
1097 : character(len=*), intent(in) :: spec_type ! specie type
1098 :
1099 : ! Return value
1100 : integer :: spec_idx ! specie index
1101 :
1102 : ! Local variables
1103 : type(modelist_t), pointer :: m_list
1104 : type(mode_component_t), pointer :: mode_comps
1105 :
1106 : integer :: i, m_idx, nspec
1107 :
1108 : character(len=*), parameter :: subname = 'rad_cnst_get_spec_idx'
1109 : !-----------------------------------------------------------------------------
1110 :
1111 : ! if specie type not found return -1
1112 0 : spec_idx = -1
1113 :
1114 : ! modes in specified list
1115 0 : m_list => ma_list(list_idx)
1116 :
1117 : ! get index of the specified mode in the definition object
1118 0 : m_idx = m_list%idx(mode_idx)
1119 :
1120 : ! object containing the components of the mode
1121 0 : mode_comps => modes%comps(m_idx)
1122 :
1123 : ! number of species in specified mode
1124 0 : nspec = mode_comps%nspec
1125 :
1126 : ! loop through species in specified mode
1127 0 : do i = 1, nspec
1128 :
1129 : ! look in mode definition object (modes) for the mode types
1130 0 : if (trim(mode_comps%type(i)) == trim(spec_type)) then
1131 0 : spec_idx = i
1132 0 : exit
1133 : end if
1134 : end do
1135 :
1136 0 : end function rad_cnst_get_spec_idx
1137 :
1138 : !================================================================================================
1139 :
1140 79872 : subroutine rad_cnst_get_call_list(call_list)
1141 :
1142 : ! Return info about which climate/diagnostic calculations are requested
1143 :
1144 : ! Arguments
1145 : logical, intent(out) :: call_list(0:N_DIAG)
1146 : !-----------------------------------------------------------------------------
1147 :
1148 79872 : call_list(:) = active_calls(:)
1149 :
1150 79872 : end subroutine rad_cnst_get_call_list
1151 :
1152 : !================================================================================================
1153 :
1154 38400 : subroutine rad_cnst_out(list_idx, state, pbuf)
1155 :
1156 : ! Output the mass per layer, and total column burdens for gas and aerosol
1157 : ! constituents in either the climate or diagnostic lists
1158 :
1159 : ! Arguments
1160 : integer, intent(in) :: list_idx
1161 : type(physics_state), target, intent(in) :: state
1162 : type(physics_buffer_desc), pointer :: pbuf(:)
1163 :
1164 :
1165 : ! Local variables
1166 : integer :: i, naer, ngas, lchnk, ncol
1167 : integer :: idx
1168 : character(len=1) :: source
1169 : character(len=32) :: name, cbname
1170 : real(r8) :: mass(pcols,pver)
1171 : real(r8) :: cb(pcols)
1172 38400 : real(r8), pointer :: mmr(:,:)
1173 : type(aerlist_t), pointer :: aerlist
1174 : type(gaslist_t), pointer :: g_list
1175 : character(len=*), parameter :: subname = 'rad_cnst_out'
1176 : !-----------------------------------------------------------------------------
1177 :
1178 38400 : lchnk = state%lchnk
1179 38400 : ncol = state%ncol
1180 :
1181 : ! Associate pointer with requested aerosol list
1182 38400 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
1183 38400 : aerlist => aerosollist(list_idx)
1184 : else
1185 0 : write(iulog,*) subname//': list_idx = ', list_idx
1186 0 : call endrun(subname//': list_idx out of range')
1187 : endif
1188 :
1189 38400 : naer = aerlist%numaerosols
1190 38400 : do i = 1, naer
1191 :
1192 0 : source = aerlist%aer(i)%source
1193 0 : idx = aerlist%aer(i)%idx
1194 0 : name = aerlist%aer(i)%mass_name
1195 : ! construct name for column burden field by replacing the 'm_' prefix by 'cb_'
1196 0 : cbname = 'cb_' // name(3:len_trim(name))
1197 :
1198 0 : select case( source )
1199 : case ('A')
1200 0 : mmr => state%q(:,:,idx)
1201 : case ('N')
1202 0 : call pbuf_get_field(pbuf, idx, mmr)
1203 : end select
1204 :
1205 0 : mass(:ncol,:) = mmr(:ncol,:) * state%pdeldry(:ncol,:) * rga
1206 0 : call outfld(trim(name), mass, pcols, lchnk)
1207 :
1208 0 : cb(:ncol) = sum(mass(:ncol,:),2)
1209 38400 : call outfld(trim(cbname), cb, pcols, lchnk)
1210 :
1211 : end do
1212 :
1213 : ! Associate pointer with requested gas list
1214 38400 : g_list => gaslist(list_idx)
1215 :
1216 38400 : ngas = g_list%ngas
1217 345600 : do i = 1, ngas
1218 :
1219 307200 : source = g_list%gas(i)%source
1220 307200 : idx = g_list%gas(i)%idx
1221 307200 : name = g_list%gas(i)%mass_name
1222 307200 : cbname = 'cb_' // name(3:len_trim(name))
1223 230400 : select case( source )
1224 : case ('A')
1225 230400 : mmr => state%q(:,:,idx)
1226 : case ('N')
1227 307200 : call pbuf_get_field(pbuf, idx, mmr)
1228 : end select
1229 :
1230 151695360 : mass(:ncol,:) = mmr(:ncol,:) * state%pdeldry(:ncol,:) * rga
1231 307200 : call outfld(trim(name), mass, pcols, lchnk)
1232 :
1233 146288640 : cb(:ncol) = sum(mass(:ncol,:),2)
1234 345600 : call outfld(trim(cbname), cb, pcols, lchnk)
1235 :
1236 : end do
1237 :
1238 38400 : end subroutine rad_cnst_out
1239 :
1240 : !================================================================================================
1241 : ! Private methods
1242 : !================================================================================================
1243 :
1244 1536 : subroutine init_mode_comps(modes)
1245 :
1246 : ! Initialize the mode definitions by looking up the relevent indices in the
1247 : ! constituent and pbuf arrays, and getting the physprop IDs
1248 :
1249 : ! Arguments
1250 : type(modes_t), intent(inout) :: modes
1251 :
1252 : ! Local variables
1253 : integer :: m, ispec, nspec
1254 :
1255 : character(len=*), parameter :: routine = 'init_mode_comps'
1256 : !-----------------------------------------------------------------------------
1257 :
1258 9216 : do m = 1, modes%nmodes
1259 :
1260 : ! indices for number mixing ratio components
1261 7680 : modes%comps(m)%idx_num_a = get_cam_idx(modes%comps(m)%source_num_a, modes%comps(m)%camname_num_a, routine)
1262 7680 : modes%comps(m)%idx_num_c = get_cam_idx(modes%comps(m)%source_num_c, modes%comps(m)%camname_num_c, routine)
1263 :
1264 : ! allocate memory for species
1265 7680 : nspec = modes%comps(m)%nspec
1266 : allocate( &
1267 : modes%comps(m)%idx_mmr_a(nspec), &
1268 0 : modes%comps(m)%idx_mmr_c(nspec), &
1269 38400 : modes%comps(m)%idx_props(nspec) )
1270 :
1271 79872 : do ispec = 1, nspec
1272 :
1273 : ! indices for species mixing ratio components
1274 0 : modes%comps(m)%idx_mmr_a(ispec) = get_cam_idx(modes%comps(m)%source_mmr_a(ispec), &
1275 70656 : modes%comps(m)%camname_mmr_a(ispec), routine)
1276 0 : modes%comps(m)%idx_mmr_c(ispec) = get_cam_idx(modes%comps(m)%source_mmr_c(ispec), &
1277 70656 : modes%comps(m)%camname_mmr_c(ispec), routine)
1278 :
1279 : ! get physprop ID
1280 70656 : modes%comps(m)%idx_props(ispec) = physprop_get_id(modes%comps(m)%props(ispec))
1281 78336 : if (modes%comps(m)%idx_props(ispec) == -1) then
1282 0 : call endrun(routine//' : ERROR idx not found for '//trim(modes%comps(m)%props(ispec)))
1283 : end if
1284 :
1285 : end do
1286 :
1287 : end do
1288 :
1289 1536 : end subroutine init_mode_comps
1290 :
1291 : !================================================================================================
1292 :
1293 1536 : subroutine init_bin_comps(bins)
1294 :
1295 : ! Initialize the mode definitions by looking up the relevent indices in the
1296 : ! constituent and pbuf arrays, and getting the physprop IDs
1297 :
1298 : ! Arguments
1299 : type(bins_t), intent(inout) :: bins
1300 :
1301 : ! Local variables
1302 : integer :: m, ispec, nspec
1303 :
1304 : character(len=*), parameter :: routine = 'init_bin_comps'
1305 : !-----------------------------------------------------------------------------
1306 :
1307 1536 : do m = 1, bins%nbins
1308 :
1309 : ! indices for number mixing ratio components
1310 0 : bins%comps(m)%idx_num_a = get_cam_idx(bins%comps(m)%source_num_a, bins%comps(m)%camname_num_a, routine)
1311 0 : bins%comps(m)%idx_num_c = get_cam_idx(bins%comps(m)%source_num_c, bins%comps(m)%camname_num_c, routine)
1312 0 : if ( bins%comps(m)%source_mass_a /= 'NOTSET' .and. bins%comps(m)%camname_mass_a /= 'NOTSET' ) then
1313 0 : bins%comps(m)%idx_mass_a = get_cam_idx(bins%comps(m)%source_mass_a, bins%comps(m)%camname_mass_a, routine)
1314 : endif
1315 0 : if ( bins%comps(m)%source_mass_c /= 'NOTSET' .and. bins%comps(m)%camname_mass_c /= 'NOTSET' ) then
1316 0 : bins%comps(m)%idx_mass_c = get_cam_idx(bins%comps(m)%source_mass_c, bins%comps(m)%camname_mass_c, routine)
1317 : endif
1318 :
1319 : ! allocate memory for species
1320 0 : nspec = bins%comps(m)%nspec
1321 : allocate( &
1322 : bins%comps(m)%idx_mmr_a(nspec), &
1323 0 : bins%comps(m)%idx_mmr_c(nspec), &
1324 0 : bins%comps(m)%idx_props(nspec) )
1325 :
1326 1536 : do ispec = 1, nspec
1327 :
1328 : ! indices for species mixing ratio components
1329 0 : bins%comps(m)%idx_mmr_a(ispec) = get_cam_idx(bins%comps(m)%source_mmr_a(ispec), &
1330 0 : bins%comps(m)%camname_mmr_a(ispec), routine)
1331 0 : bins%comps(m)%idx_mmr_c(ispec) = get_cam_idx(bins%comps(m)%source_mmr_c(ispec), &
1332 0 : bins%comps(m)%camname_mmr_c(ispec), routine)
1333 :
1334 : ! get physprop ID
1335 0 : bins%comps(m)%idx_props(ispec) = physprop_get_id(bins%comps(m)%props(ispec))
1336 0 : if (bins%comps(m)%idx_props(ispec) == -1) then
1337 0 : call endrun(routine//' : ERROR idx not found for '//trim(bins%comps(m)%props(ispec)))
1338 : end if
1339 :
1340 : end do
1341 :
1342 : end do
1343 :
1344 1536 : end subroutine init_bin_comps
1345 :
1346 : !================================================================================================
1347 :
1348 168960 : integer function get_cam_idx(source, name, routine)
1349 :
1350 : ! get index of name in internal CAM array; either the constituent array
1351 : ! or the physics buffer
1352 :
1353 : character(len=*), intent(in) :: source
1354 : character(len=*), intent(in) :: name
1355 : character(len=*), intent(in) :: routine ! name of calling routine
1356 :
1357 : integer :: idx
1358 : integer :: errcode
1359 : !-----------------------------------------------------------------------------
1360 :
1361 168960 : if (source(1:1) == 'N') then
1362 :
1363 81408 : idx = pbuf_get_index(trim(name),errcode)
1364 81408 : if (errcode < 0) then
1365 0 : call endrun(routine//' ERROR: cannot find physics buffer field '//trim(name))
1366 : end if
1367 :
1368 87552 : else if (source(1:1) == 'A') then
1369 :
1370 87552 : call cnst_get_ind(trim(name), idx, abort=.false.)
1371 87552 : if (idx < 0) then
1372 0 : call endrun(routine//' ERROR: cannot find constituent field '//trim(name))
1373 : end if
1374 :
1375 0 : else if (source(1:1) == 'Z') then
1376 :
1377 0 : idx = -1
1378 :
1379 : else
1380 :
1381 0 : call endrun(routine//' ERROR: invalid source for specie '//trim(name))
1382 :
1383 : end if
1384 :
1385 168960 : get_cam_idx = idx
1386 :
1387 168960 : end function get_cam_idx
1388 :
1389 : !================================================================================================
1390 :
1391 1536 : subroutine list_init1(namelist, gaslist, aerlist, ma_list, sa_list)
1392 :
1393 : ! Initialize the gas and bulk and modal aerosol lists with the
1394 : ! entities specified in the climate or diagnostic lists.
1395 :
1396 : ! This first phase initialization just sets the information that
1397 : ! is available at the time the namelist is read.
1398 :
1399 : type(rad_cnst_namelist_t), intent(in) :: namelist ! parsed namelist input for climate or diagnostic lists
1400 :
1401 : type(gaslist_t), intent(inout) :: gaslist
1402 : type(aerlist_t), intent(inout) :: aerlist
1403 : type(modelist_t), intent(inout) :: ma_list
1404 : type(binlist_t), intent(inout) :: sa_list
1405 :
1406 : ! Local variables
1407 : integer :: ii, m, naero, nmodes, nbins
1408 : integer :: igas, ba_idx, ma_idx, sa_idx
1409 : integer :: istat
1410 : character(len=*), parameter :: routine = 'list_init1'
1411 : !-----------------------------------------------------------------------------
1412 :
1413 : ! nradgas is set by the radiative transfer code
1414 1536 : gaslist%ngas = nradgas
1415 :
1416 : ! Determine the number of bulk aerosols and aerosol modes in the list
1417 1536 : naero = 0
1418 1536 : nmodes = 0
1419 1536 : nbins = 0
1420 21504 : do ii = 1, namelist%ncnst
1421 19968 : if (trim(namelist%type(ii)) == 'A') naero = naero + 1
1422 19968 : if (trim(namelist%type(ii)) == 'M') nmodes = nmodes + 1
1423 21504 : if (trim(namelist%type(ii)) == 'B') nbins = nbins + 1
1424 : end do
1425 1536 : aerlist%numaerosols = naero
1426 1536 : ma_list%nmodes = nmodes
1427 1536 : sa_list%nbins = nbins
1428 :
1429 : ! allocate storage for the aerosol, gas, and mode lists
1430 : allocate( &
1431 : aerlist%aer(aerlist%numaerosols), &
1432 : gaslist%gas(gaslist%ngas), &
1433 : ma_list%idx(ma_list%nmodes), &
1434 : ma_list%physprop_files(ma_list%nmodes), &
1435 : ma_list%idx_props(ma_list%nmodes), &
1436 : sa_list%idx(sa_list%nbins), &
1437 : sa_list%physprop_files(sa_list%nbins), &
1438 : sa_list%idx_props(sa_list%nbins), &
1439 16896 : stat=istat)
1440 1536 : if (istat /= 0) call endrun(routine//': allocate ERROR; aero and gas list components')
1441 :
1442 1536 : if (masterproc .and. verbose) then
1443 2 : if (len_trim(gaslist%list_id) == 0) then
1444 2 : write(iulog,*) nl//' '//routine//': namelist input for climate list'
1445 : else
1446 0 : write(iulog,*) nl//' '//routine//': namelist input for diagnostic list:'//gaslist%list_id
1447 : end if
1448 : end if
1449 :
1450 : ! Loop over the radiatively active components specified in the namelist
1451 1536 : ba_idx = 0
1452 1536 : ma_idx = 0
1453 1536 : sa_idx = 0
1454 21504 : do ii = 1, namelist%ncnst
1455 :
1456 19968 : if (masterproc .and. verbose) &
1457 0 : write(iulog,*) " rad namelist spec: "// trim(namelist%source(ii)) &
1458 26 : //":"//trim(namelist%camname(ii))//":"//trim(namelist%radname(ii))
1459 :
1460 : ! Check that the source specifier is legal.
1461 0 : if (namelist%source(ii) /= 'A' .and. namelist%source(ii) /= 'M' .and. &
1462 19968 : namelist%source(ii) /= 'N' .and. namelist%source(ii) /= 'Z' .and. &
1463 : namelist%source(ii) /= 'B' ) then
1464 : call endrun(routine//": source must either be A, B, M, N or Z:"//&
1465 0 : " illegal specifier in namelist input: "//namelist%source(ii))
1466 : end if
1467 :
1468 : ! Add component to appropriate list (gas, modal or bulk aerosol)
1469 21504 : if (namelist%type(ii) == 'A') then
1470 :
1471 : ! Add to bulk aerosol list
1472 0 : ba_idx = ba_idx + 1
1473 :
1474 0 : aerlist%aer(ba_idx)%source = namelist%source(ii)
1475 0 : aerlist%aer(ba_idx)%camname = namelist%camname(ii)
1476 0 : aerlist%aer(ba_idx)%physprop_file = namelist%radname(ii)
1477 :
1478 19968 : else if (namelist%type(ii) == 'M') then
1479 :
1480 : ! Add to modal aerosol list
1481 7680 : ma_idx = ma_idx + 1
1482 :
1483 : ! Look through the mode definitions for the name of the specified mode. The
1484 : ! index into the modes object all the information relevent to the mode definition.
1485 7680 : ma_list%idx(ma_idx) = -1
1486 23040 : do m = 1, modes%nmodes
1487 23040 : if (trim(namelist%camname(ii)) == trim(modes%names(m))) then
1488 7680 : ma_list%idx(ma_idx) = m
1489 7680 : exit
1490 : end if
1491 : end do
1492 7680 : if (ma_list%idx(ma_idx) == -1) &
1493 0 : call endrun(routine//' ERROR cannot find mode name '//trim(namelist%camname(ii)))
1494 :
1495 : ! Also save the name of the physprop file
1496 7680 : ma_list%physprop_files(ma_idx) = namelist%radname(ii)
1497 :
1498 12288 : else if (namelist%type(ii) == 'B') then
1499 :
1500 : ! Add to modal aerosol list
1501 0 : sa_idx = sa_idx + 1
1502 :
1503 : ! Look through the bin definitions for the name of the specified bin. The
1504 : ! index into the modes object all the information relevent to the mode definition.
1505 0 : sa_list%idx(sa_idx) = -1
1506 0 : do m = 1, bins%nbins
1507 0 : if (trim(namelist%camname(ii)) == trim(bins%names(m))) then
1508 0 : sa_list%idx(sa_idx) = m
1509 0 : exit
1510 : end if
1511 : end do
1512 0 : if (sa_list%idx(sa_idx) == -1) &
1513 0 : call endrun(routine//' ERROR cannot find bin name '//trim(namelist%camname(ii)))
1514 :
1515 : ! Also save the name of the physprop file
1516 0 : sa_list%physprop_files(sa_idx) = namelist%radname(ii)
1517 :
1518 : else
1519 :
1520 : ! Add to gas list
1521 :
1522 : ! The radiative transfer code requires the input of a specific set of gases
1523 : ! which is hardwired into the code. The CAM interface to the RT code uses
1524 : ! the names in the radconstants module to refer to these gases. The user
1525 : ! interface (namelist) also uses these names to identify the gases treated
1526 : ! by the RT code. We use the index order set in radconstants for convenience
1527 : ! only.
1528 :
1529 : ! First check that the gas name specified by the user is allowed.
1530 : ! rad_gas_index will abort on illegal names.
1531 12288 : igas = rad_gas_index(namelist%radname(ii))
1532 :
1533 : ! Set values in the igas index
1534 12288 : gaslist%gas(igas)%source = namelist%source(ii)
1535 12288 : gaslist%gas(igas)%camname = namelist%camname(ii)
1536 :
1537 : end if
1538 : end do
1539 :
1540 1536 : end subroutine list_init1
1541 :
1542 : !================================================================================================
1543 :
1544 1536 : subroutine list_init2(gaslist, aerlist, ma_list, sa_list)
1545 :
1546 : ! Final initialization phase gets the component indices in the constituent array
1547 : ! and the physics buffer, and indices into physprop module.
1548 :
1549 : type(gaslist_t), intent(inout) :: gaslist
1550 : type(aerlist_t), intent(inout) :: aerlist
1551 : type(modelist_t), intent(inout) :: ma_list
1552 : type(binlist_t), intent(inout) :: sa_list
1553 :
1554 : ! Local variables
1555 : integer :: i
1556 : character(len=*), parameter :: routine = 'list_init2'
1557 : !-----------------------------------------------------------------------------
1558 :
1559 : ! Loop over gases
1560 13824 : do i = 1, gaslist%ngas
1561 :
1562 : ! locate the specie mixing ratio in the pbuf or state
1563 13824 : gaslist%gas(i)%idx = get_cam_idx(gaslist%gas(i)%source, gaslist%gas(i)%camname, routine)
1564 :
1565 : end do
1566 :
1567 : ! Loop over bulk aerosols
1568 1536 : do i = 1, aerlist%numaerosols
1569 :
1570 : ! locate the specie mixing ratio in the pbuf or state
1571 0 : aerlist%aer(i)%idx = get_cam_idx(aerlist%aer(i)%source, aerlist%aer(i)%camname, routine)
1572 :
1573 : ! get the physprop_id from the phys_prop module
1574 1536 : aerlist%aer(i)%physprop_id = physprop_get_id(aerlist%aer(i)%physprop_file)
1575 :
1576 : end do
1577 :
1578 : ! Loop over modes
1579 9216 : do i = 1, ma_list%nmodes
1580 :
1581 : ! get the physprop_id from the phys_prop module
1582 9216 : ma_list%idx_props(i) = physprop_get_id(ma_list%physprop_files(i))
1583 :
1584 : end do
1585 :
1586 : ! Loop over bins
1587 1536 : do i = 1, sa_list%nbins
1588 :
1589 : ! get the physprop_id from the phys_prop module
1590 1536 : sa_list%idx_props(i) = physprop_get_id(sa_list%physprop_files(i))
1591 :
1592 : end do
1593 :
1594 1536 : end subroutine list_init2
1595 :
1596 : !================================================================================================
1597 :
1598 1536 : subroutine rad_gas_diag_init(glist)
1599 :
1600 : ! Add diagnostic fields to the master fieldlist.
1601 :
1602 : type(gaslist_t), intent(inout) :: glist
1603 :
1604 : integer :: i, ngas
1605 : character(len=64) :: name
1606 : character(len=2) :: list_id
1607 : character(len=4) :: suffix
1608 : character(len=128):: long_name
1609 : character(len=32) :: long_name_description
1610 : !-----------------------------------------------------------------------------
1611 :
1612 1536 : ngas = glist%ngas
1613 1536 : if (ngas == 0) return
1614 :
1615 : ! Determine whether this is a climate or diagnostic list.
1616 1536 : list_id = glist%list_id
1617 1536 : if (len_trim(list_id) == 0) then
1618 1536 : suffix = '_c'
1619 1536 : long_name_description = ' used in climate calculation'
1620 : else
1621 0 : suffix = '_d' // list_id
1622 0 : long_name_description = ' used in diagnostic calculation'
1623 : end if
1624 :
1625 13824 : do i = 1, ngas
1626 :
1627 : ! construct names for mass per layer diagnostics
1628 12288 : name = 'm_' // trim(glist%gas(i)%camname) // trim(suffix)
1629 12288 : glist%gas(i)%mass_name = name
1630 12288 : long_name = trim(glist%gas(i)%camname)//' mass per layer'//long_name_description
1631 24576 : call addfld(trim(name), (/ 'lev' /), 'A', 'kg/m^2', trim(long_name))
1632 :
1633 : ! construct names for column burden diagnostics
1634 12288 : name = 'cb_' // trim(glist%gas(i)%camname) // trim(suffix)
1635 12288 : long_name = trim(glist%gas(i)%camname)//' column burden'//long_name_description
1636 12288 : call addfld(trim(name), horiz_only, 'A', 'kg/m^2', trim(long_name))
1637 :
1638 : ! error check for name length
1639 13824 : if (len_trim(name) > fieldname_len) then
1640 0 : write(iulog,*) 'rad_gas_diag_init: '//trim(name)//' longer than ', fieldname_len, ' characters'
1641 0 : call endrun('rad_gas_diag_init: name too long: '//trim(name))
1642 : end if
1643 :
1644 : end do
1645 :
1646 : end subroutine rad_gas_diag_init
1647 :
1648 : !================================================================================================
1649 :
1650 1536 : subroutine rad_aer_diag_init(alist)
1651 :
1652 : ! Add diagnostic fields to the master fieldlist.
1653 :
1654 : type(aerlist_t), intent(inout) :: alist
1655 :
1656 : integer :: i, naer
1657 : character(len=64) :: name
1658 : character(len=2) :: list_id
1659 : character(len=4) :: suffix
1660 : character(len=128):: long_name
1661 : character(len=32) :: long_name_description
1662 : !-----------------------------------------------------------------------------
1663 :
1664 1536 : naer = alist%numaerosols
1665 1536 : if (naer == 0) return
1666 :
1667 : ! Determine whether this is a climate or diagnostic list.
1668 0 : list_id = alist%list_id
1669 0 : if (len_trim(list_id) == 0) then
1670 0 : suffix = '_c'
1671 0 : long_name_description = ' used in climate calculation'
1672 : else
1673 0 : suffix = '_d' // list_id
1674 0 : long_name_description = ' used in diagnostic calculation'
1675 : end if
1676 :
1677 0 : do i = 1, naer
1678 :
1679 : ! construct names for mass per layer diagnostic fields
1680 0 : name = 'm_' // trim(alist%aer(i)%camname) // trim(suffix)
1681 0 : alist%aer(i)%mass_name = name
1682 0 : long_name = trim(alist%aer(i)%camname)//' mass per layer'//long_name_description
1683 0 : call addfld(trim(name), (/ 'lev' /), 'A', 'kg/m^2', trim(long_name))
1684 :
1685 : ! construct names for column burden diagnostic fields
1686 0 : name = 'cb_' // trim(alist%aer(i)%camname) // trim(suffix)
1687 0 : long_name = trim(alist%aer(i)%camname)//' column burden'//long_name_description
1688 0 : call addfld(trim(name), horiz_only, 'A', 'kg/m^2', trim(long_name))
1689 :
1690 : ! error check for name length
1691 0 : if (len_trim(name) > fieldname_len) then
1692 0 : write(iulog,*) 'rad_aer_diag_init: '//trim(name)//' longer than ', fieldname_len, ' characters'
1693 0 : call endrun('rad_aer_diag_init: name too long: '//trim(name))
1694 : end if
1695 :
1696 : end do
1697 :
1698 : end subroutine rad_aer_diag_init
1699 :
1700 :
1701 : !================================================================================================
1702 :
1703 1536 : subroutine parse_mode_defs(nl_in, modes)
1704 :
1705 : ! Parse the mode definition specifiers. The specifiers are of the form:
1706 : !
1707 : ! 'mode_name:mode_type:=',
1708 : ! 'source_num_a:camname_num_a:source_num_c:camname_num_c:num_mr:+',
1709 : ! 'source_mmr_a:camname_mmr_a:source_mmr_c:camname_mmr_c:spec_type:prop_file[:+]'[,]
1710 : ! ['source_mmr_a:camname_mmr_a:source_mmr_c:camname_mmr_c:spec_type:prop_file][:+][']
1711 : !
1712 : ! where the ':' separated fields are:
1713 : ! mode_name -- name of the mode.
1714 : ! mode_type -- type of mode. Valid values are from the MAM code.
1715 : ! = -- this line terminator identifies the initial string in a
1716 : ! mode definition
1717 : ! + -- this line terminator indicates that the mode definition is
1718 : ! continued in the next string
1719 : ! source_num_a -- Source of interstitial number mixing ratio, 'A', 'N', or 'Z'
1720 : ! camname_num_a -- the name of the interstitial number component. This name must be
1721 : ! registered in the constituent arrays when source=A or in the
1722 : ! physics buffer when source=N
1723 : ! source_num_c -- Source of cloud borne number mixing ratio, 'A', 'N', or 'Z'
1724 : ! camname_num_c -- the name of the cloud borne number component. This name must be
1725 : ! registered in the constituent arrays when source=A or in the
1726 : ! physics buffer when source=N
1727 : ! source_mmr_a -- Source of interstitial specie mass mixing ratio, 'A', 'N' or 'Z'
1728 : ! camname_mmr_a -- the name of the interstitial specie. This name must be
1729 : ! registered in the constituent arrays when source=A or in the
1730 : ! physics buffer when source=N
1731 : ! source_mmr_c -- Source of cloud borne specie mass mixing ratio, 'A', 'N' or 'Z'
1732 : ! camname_mmr_c -- the name of the cloud borne specie. This name must be
1733 : ! registered in the constituent arrays when source=A or in the
1734 : ! physics buffer when source=N
1735 : ! spec_type -- species type. Valid values far from the MAM code, except that
1736 : ! the value 'num_mr' designates a number mixing ratio and has no
1737 : ! associated field for the prop_file. There can only be one entry
1738 : ! with the num_mr type in a mode definition.
1739 : ! prop_file -- For aerosol species this is a filename, which is
1740 : ! identified by a ".nc" suffix. The file contains optical and
1741 : ! other physical properties of the aerosol.
1742 : !
1743 : ! A mode definition must contain only 1 string for the number mixing ratio components
1744 : ! and at least 1 string for the species.
1745 :
1746 :
1747 : character(len=*), intent(inout) :: nl_in(:) ! namelist input (blanks are removed on output)
1748 : type(modes_t), intent(inout) :: modes ! structure containing parsed input
1749 :
1750 : ! Local variables
1751 : integer :: m
1752 : integer :: istat
1753 : integer :: nmodes, nstr
1754 : integer :: mbeg, mcur
1755 : integer :: nspec, ispec
1756 : integer :: strlen, iend, ipos
1757 : logical :: num_mr_found
1758 : character(len=*), parameter :: routine = 'parse_mode_defs'
1759 1536 : character(len=len(nl_in(1))) :: tmpstr
1760 : character(len=1) :: tmp_src_a
1761 : character(len=32) :: tmp_name_a
1762 : character(len=1) :: tmp_src_c
1763 : character(len=32) :: tmp_name_c
1764 : character(len=32) :: tmp_type
1765 : !-------------------------------------------------------------------------
1766 :
1767 : ! Determine number of modes defined by counting number of strings that are
1768 : ! terminated by ':='
1769 : ! (algorithm stops counting at first blank element).
1770 1536 : nmodes = 0
1771 1536 : nstr = 0
1772 87552 : do m = 1, n_mode_str
1773 :
1774 87552 : if (len_trim(nl_in(m)) == 0) exit
1775 86016 : nstr = nstr + 1
1776 :
1777 : ! There are no fields in the input strings in which a blank character is allowed.
1778 : ! To simplify the parsing go through the input strings and remove blanks.
1779 86016 : tmpstr = adjustl(nl_in(m))
1780 86016 : nl_in(m) = tmpstr
1781 : do
1782 86016 : strlen = len_trim(nl_in(m))
1783 86016 : ipos = index(nl_in(m), ' ')
1784 86016 : if (ipos == 0 .or. ipos > strlen) exit
1785 0 : tmpstr = nl_in(m)(:ipos-1) // nl_in(m)(ipos+1:strlen)
1786 86016 : nl_in(m) = tmpstr
1787 : end do
1788 : ! count strings with ':=' terminator
1789 87552 : if (nl_in(m)(strlen-1:strlen) == ':=') nmodes = nmodes + 1
1790 :
1791 : end do
1792 1536 : modes%nmodes = nmodes
1793 :
1794 : ! return if no modes defined
1795 1536 : if (nmodes == 0) return
1796 :
1797 : ! allocate components that depend on nmodes
1798 : allocate( &
1799 : modes%names(nmodes), &
1800 : modes%types(nmodes), &
1801 : modes%comps(nmodes), &
1802 9216 : stat=istat )
1803 1536 : if (istat > 0) then
1804 0 : write(iulog,*) routine//': ERROR: cannot allocate storage for modes. nmodes=', nmodes
1805 0 : call endrun(routine//': ERROR allocating storage for modes')
1806 : end if
1807 :
1808 1536 : mcur = 1 ! index of current string being processed
1809 :
1810 : ! loop over modes
1811 9216 : do m = 1, nmodes
1812 :
1813 7680 : mbeg = mcur ! remember the first string of a mode
1814 :
1815 : ! check that first string in mode definition is ':=' terminated
1816 7680 : iend = len_trim(nl_in(mcur))
1817 7680 : if (nl_in(mcur)(iend-1:iend) /= ':=') call parse_error('= not found', nl_in(mcur))
1818 :
1819 : ! count species in mode definition. definition will contain 1 string with
1820 : ! with a ':+' terminator for each specie
1821 7680 : nspec = 0
1822 7680 : mcur = mcur + 1
1823 70656 : do
1824 78336 : iend = len_trim(nl_in(mcur))
1825 78336 : if (nl_in(mcur)(iend-1:iend) /= ':+') exit
1826 70656 : nspec = nspec + 1
1827 70656 : mcur = mcur + 1
1828 : end do
1829 :
1830 : ! a mode must have at least one specie
1831 7680 : if (nspec == 0) call parse_error('mode must have at least one specie', nl_in(mbeg))
1832 :
1833 : ! allocate components that depend on number of species
1834 : allocate( &
1835 0 : modes%comps(m)%source_mmr_a(nspec), &
1836 0 : modes%comps(m)%camname_mmr_a(nspec), &
1837 0 : modes%comps(m)%source_mmr_c(nspec), &
1838 0 : modes%comps(m)%camname_mmr_c(nspec), &
1839 0 : modes%comps(m)%type(nspec), &
1840 0 : modes%comps(m)%props(nspec), &
1841 69120 : stat=istat)
1842 :
1843 7680 : if (istat > 0) then
1844 0 : write(iulog,*) routine//': ERROR: cannot allocate storage for species. nspec=', nspec
1845 0 : call endrun(routine//': ERROR allocating storage for species')
1846 : end if
1847 :
1848 : ! initialize components
1849 7680 : modes%comps(m)%nspec = nspec
1850 7680 : modes%comps(m)%source_num_a = ' '
1851 7680 : modes%comps(m)%camname_num_a = ' '
1852 7680 : modes%comps(m)%source_num_c = ' '
1853 7680 : modes%comps(m)%camname_num_c = ' '
1854 78336 : do ispec = 1, nspec
1855 70656 : modes%comps(m)%source_mmr_a(ispec) = ' '
1856 70656 : modes%comps(m)%camname_mmr_a(ispec) = ' '
1857 70656 : modes%comps(m)%source_mmr_c(ispec) = ' '
1858 70656 : modes%comps(m)%camname_mmr_c(ispec) = ' '
1859 70656 : modes%comps(m)%type(ispec) = ' '
1860 78336 : modes%comps(m)%props(ispec) = ' '
1861 : end do
1862 :
1863 : ! return to first string in mode definition
1864 7680 : mcur = mbeg
1865 7680 : tmpstr = nl_in(mcur)
1866 :
1867 : ! mode name
1868 7680 : ipos = index(tmpstr, ':')
1869 7680 : if (ipos < 2) call parse_error('mode name not found', tmpstr)
1870 7680 : modes%names(m) = tmpstr(:ipos-1)
1871 7680 : tmpstr = tmpstr(ipos+1:)
1872 :
1873 : ! mode type
1874 7680 : ipos = index(tmpstr, ':')
1875 7680 : if (ipos == 0) call parse_error('mode type not found', tmpstr)
1876 : ! check for valid mode type
1877 7680 : call check_mode_type(tmpstr, 1, ipos-1)
1878 7680 : modes%types(m) = tmpstr(:ipos-1)
1879 7680 : tmpstr = tmpstr(ipos+1:)
1880 :
1881 : ! mode type must be followed by '='
1882 7680 : if (tmpstr(1:1) /= '=') call parse_error('= not found', tmpstr)
1883 :
1884 : ! move to next string
1885 7680 : mcur = mcur + 1
1886 7680 : tmpstr = nl_in(mcur)
1887 :
1888 : ! process mode component strings
1889 : num_mr_found = .false. ! keep track of whether number mixing ratio component is found
1890 : ispec = 0 ! keep track of the number of species found
1891 : do
1892 :
1893 : ! source of interstitial component
1894 78336 : ipos = index(tmpstr, ':')
1895 78336 : if (ipos < 2) call parse_error('expect to find source field first', tmpstr)
1896 : ! check for valid source
1897 78336 : if (tmpstr(:ipos-1) /= 'A' .and. tmpstr(:ipos-1) /= 'N' .and. tmpstr(:ipos-1) /= 'Z') &
1898 0 : call parse_error('source must be A, N or Z', tmpstr)
1899 78336 : tmp_src_a = tmpstr(:ipos-1)
1900 78336 : tmpstr = tmpstr(ipos+1:)
1901 :
1902 : ! name of interstitial component
1903 78336 : ipos = index(tmpstr, ':')
1904 78336 : if (ipos == 0) call parse_error('next separator not found', tmpstr)
1905 78336 : tmp_name_a = tmpstr(:ipos-1)
1906 78336 : tmpstr = tmpstr(ipos+1:)
1907 :
1908 : ! source of cloud borne component
1909 78336 : ipos = index(tmpstr, ':')
1910 78336 : if (ipos < 2) call parse_error('expect to find a source field', tmpstr)
1911 : ! check for valid source
1912 78336 : if (tmpstr(:ipos-1) /= 'A' .and. tmpstr(:ipos-1) /= 'N' .and. tmpstr(:ipos-1) /= 'Z') &
1913 0 : call parse_error('source must be A, N or Z', tmpstr)
1914 78336 : tmp_src_c = tmpstr(:ipos-1)
1915 78336 : tmpstr = tmpstr(ipos+1:)
1916 :
1917 : ! name of cloud borne component
1918 78336 : ipos = index(tmpstr, ':')
1919 78336 : if (ipos == 0) call parse_error('next separator not found', tmpstr)
1920 78336 : tmp_name_c = tmpstr(:ipos-1)
1921 78336 : tmpstr = tmpstr(ipos+1:)
1922 :
1923 : ! component type
1924 78336 : ipos = scan(tmpstr, ': ')
1925 78336 : if (ipos == 0) call parse_error('next separator not found', tmpstr)
1926 :
1927 78336 : if (tmpstr(:ipos-1) == 'num_mr') then
1928 :
1929 : ! there can only be one number mixing ratio component
1930 7680 : if (num_mr_found) call parse_error('more than 1 number component', nl_in(mcur))
1931 :
1932 7680 : num_mr_found = .true.
1933 7680 : modes%comps(m)%source_num_a = tmp_src_a
1934 7680 : modes%comps(m)%camname_num_a = tmp_name_a
1935 7680 : modes%comps(m)%source_num_c = tmp_src_c
1936 7680 : modes%comps(m)%camname_num_c = tmp_name_c
1937 7680 : tmpstr = tmpstr(ipos+1:)
1938 :
1939 : else
1940 :
1941 : ! check for valid specie type
1942 70656 : call check_specie_type(tmpstr, 1, ipos-1)
1943 70656 : tmp_type = tmpstr(:ipos-1)
1944 70656 : tmpstr = tmpstr(ipos+1:)
1945 :
1946 : ! get the properties file
1947 70656 : ipos = scan(tmpstr, ': ')
1948 70656 : if (ipos == 0) call parse_error('next separator not found', tmpstr)
1949 : ! check for valid filename -- must have .nc extension
1950 70656 : if (tmpstr(ipos-3:ipos-1) /= '.nc') &
1951 0 : call parse_error('filename not valid', tmpstr)
1952 :
1953 70656 : ispec = ispec + 1
1954 70656 : modes%comps(m)%source_mmr_a(ispec) = tmp_src_a
1955 70656 : modes%comps(m)%camname_mmr_a(ispec) = tmp_name_a
1956 70656 : modes%comps(m)%source_mmr_c(ispec) = tmp_src_c
1957 70656 : modes%comps(m)%camname_mmr_c(ispec) = tmp_name_c
1958 70656 : modes%comps(m)%type(ispec) = tmp_type
1959 70656 : modes%comps(m)%props(ispec) = tmpstr(:ipos-1)
1960 70656 : tmpstr = tmpstr(ipos+1:)
1961 : end if
1962 :
1963 : ! check if there are more components. either the current character is
1964 : ! a ' ' which means this string is the final mode component, or the character
1965 : ! is a '+' which means there are more components
1966 78336 : if (tmpstr(1:1) == ' ') exit
1967 :
1968 70656 : if (tmpstr(1:1) /= '+') &
1969 0 : call parse_error('+ field not found', tmpstr)
1970 :
1971 : ! continue to next component...
1972 70656 : mcur = mcur + 1
1973 78336 : tmpstr = nl_in(mcur)
1974 : end do
1975 :
1976 : ! check that a number component was found
1977 7680 : if (.not. num_mr_found) call parse_error('number component not found', nl_in(mbeg))
1978 :
1979 : ! check that the right number of species were found
1980 7680 : if (ispec /= nspec) call parse_error('component parsing got wrong number of species', nl_in(mbeg))
1981 :
1982 : ! continue to next mode...
1983 7680 : mcur = mcur + 1
1984 9216 : tmpstr = nl_in(mcur)
1985 : end do
1986 :
1987 : !------------------------------------------------------------------------------------------------
1988 : contains
1989 : !------------------------------------------------------------------------------------------------
1990 :
1991 : ! internal subroutines used for error checking and reporting
1992 :
1993 0 : subroutine parse_error(msg, str)
1994 :
1995 : character(len=*), intent(in) :: msg
1996 : character(len=*), intent(in) :: str
1997 :
1998 0 : write(iulog,*) routine//': ERROR: '//msg
1999 0 : write(iulog,*) ' input string: '//trim(str)
2000 0 : call endrun(routine//': ERROR: '//msg)
2001 :
2002 0 : end subroutine parse_error
2003 :
2004 : !------------------------------------------------------------------------------------------------
2005 :
2006 70656 : subroutine check_specie_type(str, ib, ie)
2007 :
2008 : character(len=*), intent(in) :: str
2009 : integer, intent(in) :: ib, ie
2010 :
2011 : integer :: i
2012 :
2013 348672 : do i = 1, num_spec_types
2014 348672 : if (str(ib:ie) == trim(spec_type_names(i))) return
2015 : end do
2016 :
2017 0 : call parse_error('specie type not valid', str(ib:ie))
2018 :
2019 : end subroutine check_specie_type
2020 :
2021 : !------------------------------------------------------------------------------------------------
2022 :
2023 7680 : subroutine check_mode_type(str, ib, ie)
2024 :
2025 : character(len=*), intent(in) :: str
2026 : integer, intent(in) :: ib, ie ! begin, end character of mode type substring
2027 :
2028 : integer :: i
2029 :
2030 32256 : do i = 1, num_mode_types
2031 32256 : if (str(ib:ie) == trim(mode_type_names(i))) return
2032 : end do
2033 :
2034 0 : call parse_error('mode type not valid', str(ib:ie))
2035 :
2036 : end subroutine check_mode_type
2037 :
2038 : !------------------------------------------------------------------------------------------------
2039 :
2040 : end subroutine parse_mode_defs
2041 :
2042 : !================================================================================================
2043 :
2044 1536 : subroutine parse_bin_defs(nl_in, bins)
2045 :
2046 : ! Parse the bin definition specifiers. The specifiers are of the form:
2047 : !
2048 : ! 'bin_name:=',
2049 : ! 'source_num_a:camname_num_a:source_num_c:camname_num_c:num_mr:+',
2050 : ! 'source_mmr_a:camname_mmr_a:source_mmr_c:camname_mmr_c:spec_type:prop_file[:+]'[,]
2051 : ! ['source_mmr_a:camname_mmr_a:source_mmr_c:camname_mmr_c:spec_type:prop_file][:+][']
2052 : !
2053 : ! where the ':' separated fields are:
2054 : ! bin_name -- name of the bin.
2055 : ! = -- this line terminator identifies the initial string in a
2056 : ! mode definition
2057 : ! + -- this line terminator indicates that the mode definition is
2058 : ! continued in the next string
2059 : ! source_num_a -- Source of interstitial number mixing ratio, 'A', 'N', or 'Z'
2060 : ! camname_num_a -- the name of the interstitial number component. This name must be
2061 : ! registered in the constituent arrays when source=A or in the
2062 : ! physics buffer when source=N
2063 : ! source_num_c -- Source of cloud borne number mixing ratio, 'A', 'N', or 'Z'
2064 : ! camname_num_c -- the name of the cloud borne number component. This name must be
2065 : ! registered in the constituent arrays when source=A or in the
2066 : ! physics buffer when source=N
2067 : ! source_mmr_a -- Source of interstitial specie mass mixing ratio, 'A', 'N' or 'Z'
2068 : ! camname_mmr_a -- the name of the interstitial specie. This name must be
2069 : ! registered in the constituent arrays when source=A or in the
2070 : ! physics buffer when source=N
2071 : ! source_mmr_c -- Source of cloud borne specie mass mixing ratio, 'A', 'N' or 'Z'
2072 : ! camname_mmr_c -- the name of the cloud borne specie. This name must be
2073 : ! registered in the constituent arrays when source=A or in the
2074 : ! physics buffer when source=N
2075 : ! spec_type -- species type. Valid values are particle, shell, and core.
2076 : ! prop_file -- For aerosol species this is a filename, which is
2077 : ! identified by a ".nc" suffix. The file contains optical and
2078 : ! other physical properties of the aerosol.
2079 : !
2080 : ! A bin definition must contain at least 1 string for the species and can contain
2081 : ! a maximum of 1 particle type.
2082 :
2083 :
2084 : character(len=*), intent(inout) :: nl_in(:) ! namelist input (blanks are removed on output)
2085 : type(bins_t), intent(inout) :: bins ! structure containing parsed input
2086 :
2087 : ! Local variables
2088 : logical :: num_mr_found, mass_mr_found
2089 : logical :: particle_mr_found
2090 : integer :: m
2091 : integer :: istat
2092 : integer :: nbins, nstr, istr
2093 : integer :: mbeg, mcur
2094 : integer :: nspec, ispec
2095 : integer :: strlen, ibeg, iend, ipos
2096 : logical :: part_mr_found
2097 : character(len=*), parameter :: routine = 'parse_bin_defs'
2098 1536 : character(len=len(nl_in(1))) :: tmpstr
2099 : character(len=1) :: tmp_src_a
2100 : character(len=32) :: tmp_name_a
2101 : character(len=1) :: tmp_src_c
2102 : character(len=32) :: tmp_name_c
2103 : character(len=32) :: tmp_type
2104 : character(len=32) :: tmp_morph
2105 : !-------------------------------------------------------------------------
2106 :
2107 : ! Determine number of bins defined by counting number of strings that are
2108 : ! terminated by ':='
2109 : ! (algorithm stops counting at first blank element).
2110 1536 : nbins = 0
2111 1536 : nstr = 0
2112 1536 : do m = 1, n_bin_str
2113 :
2114 1536 : if (len_trim(nl_in(m)) == 0) exit
2115 0 : nstr = nstr + 1
2116 :
2117 : ! There are no fields in the input strings in which a blank character is allowed.
2118 : ! To simplify the parsing go through the input strings and remove blanks.
2119 0 : tmpstr = adjustl(nl_in(m))
2120 0 : nl_in(m) = tmpstr
2121 : do
2122 0 : strlen = len_trim(nl_in(m))
2123 0 : ipos = index(nl_in(m), ' ')
2124 0 : if (ipos == 0 .or. ipos > strlen) exit
2125 0 : tmpstr = nl_in(m)(:ipos-1) // nl_in(m)(ipos+1:strlen)
2126 0 : nl_in(m) = tmpstr
2127 : end do
2128 : ! count strings with ':=' terminator
2129 1536 : if (nl_in(m)(strlen-1:strlen) == ':=') nbins = nbins + 1
2130 :
2131 : end do
2132 1536 : bins%nbins = nbins
2133 :
2134 : ! return if no bins defined
2135 1536 : if (nbins == 0) return
2136 :
2137 : ! allocate components that depend on nmodes
2138 : allocate( &
2139 : bins%names(nbins), &
2140 : bins%comps(nbins), &
2141 0 : stat=istat )
2142 0 : if (istat > 0) then
2143 0 : write(iulog,*) routine//': ERROR: cannot allocate storage for bins. nbins=', nbins
2144 0 : call endrun(routine//': ERROR allocating storage for bins')
2145 : end if
2146 :
2147 0 : mcur = 1 ! index of current string being processed
2148 :
2149 : ! loop over bins
2150 0 : bins_loop: do m = 1, nbins
2151 :
2152 0 : mbeg = mcur ! remember the first string of a bin
2153 :
2154 : ! check that first string in bin definition is ':=' terminated
2155 0 : iend = len_trim(nl_in(mcur))
2156 0 : if (nl_in(mcur)(iend-1:iend) /= ':=') call parse_error('= not found', nl_in(mcur))
2157 :
2158 : ! count species in bin definition. definition will contain 1 string with
2159 : ! with a ':+' terminator for each specie
2160 0 : nspec = 0
2161 0 : mcur = mcur + 1
2162 0 : do
2163 0 : iend = len_trim(nl_in(mcur))
2164 0 : if (nl_in(mcur)(iend-1:iend) /= ':+') exit
2165 0 : if (nl_in(mcur)(iend-4:iend) /= 'mmr:+') nspec = nspec + 1
2166 0 : mcur = mcur + 1
2167 : end do
2168 :
2169 : ! a bin must have at least one specie
2170 0 : if (nspec == 0) call parse_error('bin must have at least one specie', nl_in(mbeg))
2171 :
2172 : ! allocate components that depend on number of species
2173 : allocate( &
2174 0 : bins%comps(m)%source_mmr_a(nspec), &
2175 0 : bins%comps(m)%camname_mmr_a(nspec), &
2176 0 : bins%comps(m)%source_mmr_c(nspec), &
2177 0 : bins%comps(m)%camname_mmr_c(nspec), &
2178 0 : bins%comps(m)%type(nspec), &
2179 0 : bins%comps(m)%morph(nspec), &
2180 0 : bins%comps(m)%props(nspec), &
2181 0 : stat=istat)
2182 :
2183 0 : if (istat > 0) then
2184 0 : write(iulog,*) routine//': ERROR: cannot allocate storage for species. nspec=', nspec
2185 0 : call endrun(routine//': ERROR allocating storage for species')
2186 : end if
2187 :
2188 : ! initialize components
2189 0 : bins%comps(m)%nspec = nspec
2190 0 : bins%comps(m)%source_num_a = ' '
2191 0 : bins%comps(m)%camname_num_a = ' '
2192 0 : bins%comps(m)%source_num_c = ' '
2193 0 : bins%comps(m)%camname_num_c = ' '
2194 0 : bins%comps(m)%source_mass_a = 'NOTSET'
2195 0 : bins%comps(m)%camname_mass_a = 'NOTSET'
2196 0 : bins%comps(m)%source_mass_c = 'NOTSET'
2197 0 : bins%comps(m)%camname_mass_c = 'NOTSET'
2198 0 : do ispec = 1, nspec
2199 0 : bins%comps(m)%source_mmr_a(ispec) = ' '
2200 0 : bins%comps(m)%camname_mmr_a(ispec) = ' '
2201 0 : bins%comps(m)%source_mmr_c(ispec) = ' '
2202 0 : bins%comps(m)%camname_mmr_c(ispec) = ' '
2203 0 : bins%comps(m)%type(ispec) = ' '
2204 0 : bins%comps(m)%props(ispec) = ' '
2205 : end do
2206 :
2207 : ! return to first string in mode definition
2208 0 : mcur = mbeg
2209 0 : tmpstr = nl_in(mcur)
2210 :
2211 : ! bin name
2212 0 : ipos = index(tmpstr, ':')
2213 0 : if (ipos < 2) call parse_error('bin name not found', tmpstr)
2214 0 : bins%names(m) = tmpstr(:ipos-1)
2215 0 : tmpstr = tmpstr(ipos+1:)
2216 :
2217 : ! bin name must be followed by '='
2218 0 : if (tmpstr(1:1) /= '=') call parse_error('= not found', tmpstr)
2219 :
2220 : ! move to next string
2221 0 : mcur = mcur + 1
2222 0 : tmpstr = nl_in(mcur)
2223 :
2224 : ! process bin component strings
2225 0 : particle_mr_found = .false. ! keep track of whether particle mixing ratio component is found
2226 0 : num_mr_found = .false. ! keep track of whether number mixing ratio component is found
2227 0 : mass_mr_found = .false. ! keep track of whether number mixing ratio component is found
2228 0 : ispec = 0 ! keep track of the number of species found
2229 : comps_loop: do
2230 :
2231 : ! source of interstitial component
2232 0 : ipos = index(tmpstr, ':')
2233 0 : if (ipos < 2) call parse_error('expect to find source field first', tmpstr)
2234 : ! check for valid source
2235 0 : if (tmpstr(:ipos-1) /= 'A' .and. tmpstr(:ipos-1) /= 'N' .and. tmpstr(:ipos-1) /= 'Z') &
2236 0 : call parse_error('source must be A, N or Z', tmpstr)
2237 0 : tmp_src_a = tmpstr(:ipos-1)
2238 0 : tmpstr = tmpstr(ipos+1:)
2239 :
2240 : ! name of interstitial component
2241 0 : ipos = index(tmpstr, ':')
2242 0 : if (ipos == 0) call parse_error('next separator not found', tmpstr)
2243 0 : tmp_name_a = tmpstr(:ipos-1)
2244 0 : tmpstr = tmpstr(ipos+1:)
2245 :
2246 : ! source of cloud borne component
2247 0 : ipos = index(tmpstr, ':')
2248 0 : if (ipos < 2) call parse_error('expect to find a source field', tmpstr)
2249 : ! check for valid source
2250 0 : if (tmpstr(:ipos-1) /= 'A' .and. tmpstr(:ipos-1) /= 'N' .and. tmpstr(:ipos-1) /= 'Z') &
2251 0 : call parse_error('source must be A, N or Z', tmpstr)
2252 0 : tmp_src_c = tmpstr(:ipos-1)
2253 0 : tmpstr = tmpstr(ipos+1:)
2254 :
2255 : ! name of cloud borne component
2256 0 : ipos = index(tmpstr, ':')
2257 0 : if (ipos == 0) call parse_error('next separator not found', tmpstr)
2258 0 : tmp_name_c = tmpstr(:ipos-1)
2259 0 : tmpstr = tmpstr(ipos+1:)
2260 :
2261 : ! component type
2262 0 : ipos = scan(tmpstr, ': ')
2263 0 : if (ipos == 0) call parse_error('next separator not found', tmpstr)
2264 :
2265 0 : if (tmpstr(:ipos-1) == 'num') then
2266 :
2267 : ! there can only be one number mixing ratio component
2268 0 : if (num_mr_found) call parse_error('more than 1 number component', nl_in(mcur))
2269 :
2270 0 : num_mr_found = .true.
2271 0 : bins%comps(m)%source_num_a = tmp_src_a
2272 0 : bins%comps(m)%camname_num_a = tmp_name_a
2273 0 : bins%comps(m)%source_num_c = tmp_src_c
2274 0 : bins%comps(m)%camname_num_c = tmp_name_c
2275 0 : tmpstr = tmpstr(ipos+1:)
2276 :
2277 0 : else if (tmpstr(:ipos-1) == 'mmr') then
2278 :
2279 : ! there can only be one number mixing ratio component
2280 0 : if (mass_mr_found) call parse_error('more than 1 mass mixing ratio component', nl_in(mcur))
2281 :
2282 0 : mass_mr_found = .true.
2283 0 : bins%comps(m)%source_mass_a = tmp_src_a
2284 0 : bins%comps(m)%camname_mass_a = tmp_name_a
2285 0 : bins%comps(m)%source_mass_c = tmp_src_c
2286 0 : bins%comps(m)%camname_mass_c = tmp_name_c
2287 0 : tmpstr = tmpstr(ipos+1:)
2288 :
2289 : else
2290 :
2291 : ! check for valid species type
2292 0 : call check_bin_type(tmpstr, 1, ipos-1)
2293 0 : tmp_type = tmpstr(:ipos-1)
2294 0 : tmpstr = tmpstr(ipos+1:)
2295 :
2296 0 : ipos = index(tmpstr, ':')
2297 0 : if (ipos == 0) call parse_error('next separator not found', tmpstr)
2298 :
2299 : ! check for valid species type
2300 0 : call check_bin_morph(tmpstr, 1, ipos-1)
2301 0 : tmp_morph = tmpstr(:ipos-1)
2302 0 : tmpstr = tmpstr(ipos+1:)
2303 :
2304 : ! get the properties file
2305 0 : ipos = scan(tmpstr, ': ')
2306 0 : if (ipos == 0) call parse_error('next separator not found', tmpstr)
2307 :
2308 : ! check for valid filename -- must have .nc extension
2309 0 : if (tmpstr(ipos-3:ipos-1) /= '.nc') &
2310 0 : call parse_error('filename not valid', tmpstr)
2311 :
2312 0 : ispec = ispec + 1
2313 :
2314 0 : bins%comps(m)%source_mmr_a(ispec) = tmp_src_a
2315 0 : bins%comps(m)%camname_mmr_a(ispec) = tmp_name_a
2316 0 : bins%comps(m)%source_mmr_c(ispec) = tmp_src_c
2317 0 : bins%comps(m)%camname_mmr_c(ispec) = tmp_name_c
2318 0 : bins%comps(m)%type(ispec) = tmp_type
2319 0 : bins%comps(m)%morph(ispec) = tmp_morph
2320 :
2321 0 : bins%comps(m)%props(ispec) = tmpstr(:ipos-1)
2322 0 : tmpstr = tmpstr(ipos+1:)
2323 :
2324 : endif
2325 :
2326 : ! check if there are more components. either the current character is
2327 : ! a ' ' which means this string is the final mode component, or the character
2328 : ! is a '+' which means there are more components
2329 0 : if (tmpstr(1:1) == ' ') then
2330 : exit comps_loop
2331 : endif
2332 :
2333 0 : if (tmpstr(1:1) /= '+') &
2334 0 : call parse_error('+ field not found', tmpstr)
2335 :
2336 : ! continue to next component...
2337 0 : mcur = mcur + 1
2338 0 : tmpstr = nl_in(mcur)
2339 : end do comps_loop
2340 :
2341 :
2342 : ! check that a number component was found
2343 0 : if (.not. num_mr_found) call parse_error('number component not found', nl_in(mbeg))
2344 :
2345 : ! check that the right number of species were found
2346 0 : if (ispec /= nspec) then
2347 0 : write(*,*) 'ispec, nspec = ',ispec, nspec
2348 : call parse_error('component parsing got wrong number of species', nl_in(mbeg))
2349 : endif
2350 :
2351 : ! continue to next bin...
2352 0 : mcur = mcur + 1
2353 0 : tmpstr = nl_in(mcur)
2354 : end do bins_loop
2355 :
2356 : !------------------------------------------------------------------------------------------------
2357 : contains
2358 : !------------------------------------------------------------------------------------------------
2359 :
2360 : ! internal subroutines used for error checking and reporting
2361 :
2362 0 : subroutine parse_error(msg, str)
2363 :
2364 : character(len=*), intent(in) :: msg
2365 : character(len=*), intent(in) :: str
2366 :
2367 0 : write(iulog,*) routine//': ERROR: '//msg
2368 0 : write(iulog,*) ' input string: '//trim(str)
2369 0 : call endrun(routine//': ERROR: '//msg)
2370 :
2371 0 : end subroutine parse_error
2372 :
2373 : !------------------------------------------------------------------------------------------------
2374 :
2375 0 : subroutine check_bin_morph(str, ib, ie)
2376 :
2377 : character(len=*), intent(in) :: str
2378 : integer, intent(in) :: ib, ie
2379 :
2380 : integer :: i
2381 :
2382 0 : do i = 1, num_bin_morphs
2383 0 : if (str(ib:ie) == trim(bin_morph_names(i))) return
2384 : end do
2385 :
2386 0 : call parse_error('bin morph not valid', str(ib:ie))
2387 :
2388 : end subroutine check_bin_morph
2389 :
2390 : !------------------------------------------------------------------------------------------------
2391 0 : subroutine check_bin_type(str, ib, ie)
2392 :
2393 : character(len=*), intent(in) :: str
2394 : integer, intent(in) :: ib, ie ! begin, end character of mode type substring
2395 :
2396 : integer :: i
2397 :
2398 0 : do i = 1, num_spec_types
2399 0 : if (str(ib:ie) == trim(spec_type_names(i))) return
2400 : end do
2401 :
2402 0 : call parse_error('bin species type not valid', str(ib:ie))
2403 :
2404 : end subroutine check_bin_type
2405 :
2406 : !------------------------------------------------------------------------------------------------
2407 :
2408 : end subroutine parse_bin_defs
2409 :
2410 : !================================================================================================
2411 :
2412 16896 : subroutine parse_rad_specifier(specifier, namelist_data)
2413 :
2414 : !-----------------------------------------------------------------------------
2415 : ! Private method for parsing the radiation namelist specifiers. The specifiers
2416 : ! are of the form 'source_camname:radname' where:
2417 : ! source -- either 'N' for pbuf (non-advected) or 'A' for state (advected)
2418 : ! camname -- the name of a constituent that must be found in the constituent
2419 : ! component of the state when source=A or in the physics buffer
2420 : ! when source=N
2421 : ! radname -- For gases this is a name that identifies the constituent to the
2422 : ! radiative transfer codes. These names are contained in the
2423 : ! radconstants module. For aerosols this is a filename, which is
2424 : ! identified by a ".nc" suffix. The file contains optical and
2425 : ! other physical properties of the aerosol.
2426 : !
2427 : ! This code also identifies whether the constituent is a gas or an aerosol
2428 : ! and adds that info to a structure that stores the parsed data.
2429 : !-----------------------------------------------------------------------------
2430 :
2431 : character(len=*), dimension(:), intent(in) :: specifier
2432 : type(rad_cnst_namelist_t), intent(inout) :: namelist_data
2433 :
2434 : ! Local variables
2435 : integer :: number, i, j
2436 : integer :: ipos, strlen
2437 : integer :: astat
2438 : character(len=cs1) :: tmpstr
2439 : character(len=1) :: source(n_rad_cnst)
2440 : character(len=64) :: camname(n_rad_cnst)
2441 : character(len=cs1) :: radname(n_rad_cnst)
2442 : character(len=1) :: type(n_rad_cnst)
2443 : !-------------------------------------------------------------------------
2444 :
2445 16896 : number = 0
2446 :
2447 36864 : parse_loop: do i = 1, n_rad_cnst
2448 36864 : if ( len_trim(specifier(i)) == 0 ) then
2449 : exit parse_loop
2450 : endif
2451 :
2452 : ! There are no fields in the input strings in which a blank character is allowed.
2453 : ! To simplify the parsing go through the input strings and remove blanks.
2454 19968 : tmpstr = adjustl(specifier(i))
2455 0 : do
2456 19968 : strlen = len_trim(tmpstr)
2457 19968 : ipos = index(tmpstr, ' ')
2458 19968 : if (ipos == 0 .or. ipos > strlen) exit
2459 19968 : tmpstr = tmpstr(:ipos-1) // tmpstr(ipos+1:strlen)
2460 : end do
2461 :
2462 : ! Locate the ':' separating source from camname.
2463 19968 : j = index(tmpstr, ':')
2464 19968 : source(i) = tmpstr(:j-1)
2465 19968 : tmpstr = tmpstr(j+1:)
2466 :
2467 : ! locate the ':' separating camname from radname
2468 19968 : j = scan(tmpstr, ':')
2469 :
2470 19968 : camname(i) = tmpstr(:j-1)
2471 19968 : radname(i) = tmpstr(j+1:)
2472 :
2473 : ! determine the type of constituent
2474 19968 : if (source(i) == 'M') then
2475 7680 : type(i) = 'M'
2476 12288 : else if (source(i) == 'B') then
2477 0 : type(i) = 'B'
2478 12288 : else if(index(radname(i),".nc") .gt. 0) then
2479 0 : type(i) = 'A'
2480 : else
2481 12288 : type(i) = 'G'
2482 : end if
2483 :
2484 36864 : number = number+1
2485 : end do parse_loop
2486 :
2487 16896 : namelist_data%ncnst = number
2488 :
2489 16896 : if (number == 0) return
2490 :
2491 3072 : allocate(namelist_data%source (number), stat=astat)
2492 1536 : if( astat/= 0 ) call endrun('parse_rad_specifier: not able to allocate namelist_data%source')
2493 4608 : allocate(namelist_data%camname(number), stat=astat)
2494 0 : if( astat/= 0 ) call endrun('parse_rad_specifier: not able to allocate namelist_data%camname')
2495 4608 : allocate(namelist_data%radname(number), stat=astat)
2496 0 : if( astat/= 0 ) call endrun('parse_rad_specifier: not able to allocate namelist_data%radname')
2497 3072 : allocate(namelist_data%type(number), stat=astat)
2498 0 : if( astat/= 0 ) call endrun('parse_rad_specifier: not able to allocate namelist_data%type')
2499 :
2500 21504 : namelist_data%source(:namelist_data%ncnst) = source (:namelist_data%ncnst)
2501 21504 : namelist_data%camname(:namelist_data%ncnst) = camname(:namelist_data%ncnst)
2502 21504 : namelist_data%radname(:namelist_data%ncnst) = radname(:namelist_data%ncnst)
2503 21504 : namelist_data%type(:namelist_data%ncnst) = type(:namelist_data%ncnst)
2504 :
2505 : end subroutine parse_rad_specifier
2506 :
2507 : !================================================================================================
2508 :
2509 0 : subroutine rad_cnst_get_aer_mmr_by_idx(list_idx, aer_idx, state, pbuf, mmr)
2510 :
2511 : ! Return pointer to mass mixing ratio for the aerosol from the specified
2512 : ! climate or diagnostic list.
2513 :
2514 : ! Arguments
2515 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
2516 : integer, intent(in) :: aer_idx
2517 : type(physics_state), target, intent(in) :: state
2518 : type(physics_buffer_desc), pointer :: pbuf(:)
2519 : real(r8), pointer :: mmr(:,:)
2520 :
2521 : ! Local variables
2522 : integer :: lchnk
2523 : integer :: idx
2524 : character(len=1) :: source
2525 : type(aerlist_t), pointer :: aerlist
2526 : character(len=*), parameter :: subname = 'rad_cnst_get_aer_mmr_by_idx'
2527 : !-----------------------------------------------------------------------------
2528 :
2529 0 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
2530 0 : aerlist => aerosollist(list_idx)
2531 : else
2532 0 : write(iulog,*) subname//': list_idx =', list_idx
2533 0 : call endrun(subname//': list_idx out of bounds')
2534 : endif
2535 :
2536 0 : lchnk = state%lchnk
2537 :
2538 : ! Check for valid input aerosol index
2539 0 : if (aer_idx < 1 .or. aer_idx > aerlist%numaerosols) then
2540 0 : write(iulog,*) subname//': aer_idx= ', aer_idx, ' numaerosols= ', aerlist%numaerosols
2541 0 : call endrun(subname//': aerosol list index out of range')
2542 : end if
2543 :
2544 : ! Get data source
2545 0 : source = aerlist%aer(aer_idx)%source
2546 0 : idx = aerlist%aer(aer_idx)%idx
2547 0 : select case( source )
2548 : case ('A')
2549 0 : mmr => state%q(:,:,idx)
2550 : case ('N')
2551 0 : call pbuf_get_field(pbuf, idx, mmr)
2552 : case ('Z')
2553 0 : mmr => zero_cols
2554 : end select
2555 :
2556 0 : end subroutine rad_cnst_get_aer_mmr_by_idx
2557 :
2558 : !================================================================================================
2559 :
2560 4778991680 : subroutine rad_cnst_get_mam_mmr_by_idx(list_idx, mode_idx, spec_idx, phase, state, pbuf, mmr)
2561 :
2562 : ! Return pointer to mass mixing ratio for the modal aerosol specie from the specified
2563 : ! climate or diagnostic list.
2564 :
2565 : ! Arguments
2566 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
2567 : integer, intent(in) :: mode_idx ! mode index
2568 : integer, intent(in) :: spec_idx ! index of specie in the mode
2569 : character(len=1), intent(in) :: phase ! 'a' for interstitial, 'c' for cloud borne
2570 : type(physics_state), target, intent(in) :: state
2571 : type(physics_buffer_desc), pointer :: pbuf(:)
2572 : real(r8), pointer :: mmr(:,:)
2573 :
2574 : ! Local variables
2575 : integer :: m_idx
2576 : integer :: idx
2577 : integer :: lchnk
2578 : character(len=1) :: source
2579 : type(modelist_t), pointer :: mlist
2580 : character(len=*), parameter :: subname = 'rad_cnst_get_mam_mmr_by_idx'
2581 : !-----------------------------------------------------------------------------
2582 :
2583 4778991680 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
2584 4778991680 : mlist => ma_list(list_idx)
2585 : else
2586 0 : write(iulog,*) subname//': list_idx =', list_idx
2587 0 : call endrun(subname//': list_idx out of bounds')
2588 : endif
2589 :
2590 : ! Check for valid mode index
2591 4778991680 : if (mode_idx < 1 .or. mode_idx > mlist%nmodes) then
2592 0 : write(iulog,*) subname//': mode_idx= ', mode_idx, ' nmodes= ', mlist%nmodes
2593 0 : call endrun(subname//': mode list index out of range')
2594 : end if
2595 :
2596 : ! Get the index for the corresponding mode in the mode definition object
2597 4778991680 : m_idx = mlist%idx(mode_idx)
2598 :
2599 : ! Check for valid specie index
2600 4778991680 : if (spec_idx < 1 .or. spec_idx > modes%comps(m_idx)%nspec) then
2601 0 : write(iulog,*) subname//': spec_idx= ', spec_idx, ' nspec= ', modes%comps(m_idx)%nspec
2602 0 : call endrun(subname//': specie list index out of range')
2603 : end if
2604 :
2605 : ! Get data source
2606 4778991680 : if (phase == 'a') then
2607 3729655840 : source = modes%comps(m_idx)%source_mmr_a(spec_idx)
2608 3729655840 : idx = modes%comps(m_idx)%idx_mmr_a(spec_idx)
2609 1049335840 : else if (phase == 'c') then
2610 1049335840 : source = modes%comps(m_idx)%source_mmr_c(spec_idx)
2611 1049335840 : idx = modes%comps(m_idx)%idx_mmr_c(spec_idx)
2612 : else
2613 0 : write(iulog,*) subname//': phase= ', phase
2614 0 : call endrun(subname//': unrecognized phase; must be "a" or "c"')
2615 : end if
2616 :
2617 4778991680 : lchnk = state%lchnk
2618 :
2619 3729655840 : select case( source )
2620 : case ('A')
2621 3729655840 : mmr => state%q(:,:,idx)
2622 : case ('N')
2623 1049335840 : call pbuf_get_field(pbuf, idx, mmr)
2624 : case ('Z')
2625 4778991680 : mmr => zero_cols
2626 : end select
2627 :
2628 4778991680 : end subroutine rad_cnst_get_mam_mmr_by_idx
2629 :
2630 : !================================================================================================
2631 :
2632 0 : subroutine rad_cnst_get_bin_mmr_by_idx(list_idx, bin_idx, spec_idx, phase, state, pbuf, mmr)
2633 :
2634 : ! Return pointer to mass mixing ratio for the modal aerosol specie from the specified
2635 : ! climate or diagnostic list.
2636 :
2637 : ! Arguments
2638 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
2639 : integer, intent(in) :: bin_idx ! mode index
2640 : integer, intent(in) :: spec_idx ! index of specie in the mode
2641 : character(len=1), intent(in) :: phase ! 'a' for interstitial, 'c' for cloud borne
2642 : type(physics_state), target, intent(in) :: state
2643 : type(physics_buffer_desc), pointer :: pbuf(:)
2644 : real(r8), pointer :: mmr(:,:)
2645 :
2646 : ! Local variables
2647 : integer :: s_idx
2648 : integer :: idx
2649 : integer :: lchnk
2650 : character(len=1) :: source
2651 : type(binlist_t), pointer :: slist
2652 : character(len=*), parameter :: subname = 'rad_cnst_get_bin_mmr_by_idx'
2653 : !-----------------------------------------------------------------------------
2654 :
2655 0 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
2656 0 : slist => sa_list(list_idx)
2657 : else
2658 0 : write(iulog,*) subname//': list_idx =', list_idx
2659 0 : call endrun(subname//': list_idx out of bounds')
2660 : endif
2661 :
2662 : ! Check for valid mode index
2663 0 : if (bin_idx < 1 .or. bin_idx > slist%nbins) then
2664 0 : write(iulog,*) subname//': bin_idx= ', bin_idx, ' nbins= ', slist%nbins
2665 0 : call endrun(subname//': bin list index out of range')
2666 : end if
2667 :
2668 : ! Get the index for the corresponding mode in the mode definition object
2669 0 : s_idx = slist%idx(bin_idx)
2670 :
2671 : ! Check for valid specie index
2672 0 : if (spec_idx < 1 .or. spec_idx > bins%comps(s_idx)%nspec) then
2673 0 : write(iulog,*) subname//': spec_idx= ', spec_idx, ' nspec= ', bins%comps(s_idx)%nspec
2674 0 : call endrun(subname//': specie list index out of range')
2675 : end if
2676 :
2677 : ! Get data source
2678 0 : if (phase == 'a') then
2679 0 : source = bins%comps(s_idx)%source_mmr_a(spec_idx)
2680 0 : idx = bins%comps(s_idx)%idx_mmr_a(spec_idx)
2681 0 : else if (phase == 'c') then
2682 0 : source = bins%comps(s_idx)%source_mmr_c(spec_idx)
2683 0 : idx = bins%comps(s_idx)%idx_mmr_c(spec_idx)
2684 : else
2685 0 : write(iulog,*) subname//': phase= ', phase
2686 0 : call endrun(subname//': unrecognized phase; must be "a" or "c"')
2687 : end if
2688 :
2689 0 : lchnk = state%lchnk
2690 :
2691 0 : select case( source )
2692 : case ('A')
2693 0 : mmr => state%q(:,:,idx)
2694 : case ('N')
2695 0 : call pbuf_get_field(pbuf, idx, mmr)
2696 : case ('Z')
2697 0 : mmr => zero_cols
2698 : end select
2699 :
2700 0 : end subroutine rad_cnst_get_bin_mmr_by_idx
2701 :
2702 : !================================================================================================
2703 :
2704 0 : subroutine rad_cnst_get_mam_mmr_idx(mode_idx, spec_idx, idx)
2705 :
2706 : ! Return constituent index of mam specie mass mixing ratio for aerosol modes in
2707 : ! the climate list.
2708 :
2709 : ! This is a special routine to allow direct access to information in the
2710 : ! constituent array inside physics parameterizations that have been passed,
2711 : ! and are operating over the entire constituent array. The interstitial phase
2712 : ! is assumed since that's what is contained in the constituent array.
2713 :
2714 : ! Arguments
2715 : integer, intent(in) :: mode_idx ! mode index
2716 : integer, intent(in) :: spec_idx ! index of specie in the mode
2717 : integer, intent(out) :: idx ! index of specie in the constituent array
2718 :
2719 : ! Local variables
2720 : integer :: m_idx
2721 : type(modelist_t), pointer :: mlist
2722 : character(len=*), parameter :: subname = 'rad_cnst_get_mam_mmr_idx'
2723 : !-----------------------------------------------------------------------------
2724 :
2725 : ! assume climate list (i.e., species are in the constituent array)
2726 0 : mlist => ma_list(0)
2727 :
2728 : ! Check for valid mode index
2729 0 : if (mode_idx < 1 .or. mode_idx > mlist%nmodes) then
2730 0 : write(iulog,*) subname//': mode_idx= ', mode_idx, ' nmodes= ', mlist%nmodes
2731 0 : call endrun(subname//': mode list index out of range')
2732 : end if
2733 :
2734 : ! Get the index for the corresponding mode in the mode definition object
2735 0 : m_idx = mlist%idx(mode_idx)
2736 :
2737 : ! Check for valid specie index
2738 0 : if (spec_idx < 1 .or. spec_idx > modes%comps(m_idx)%nspec) then
2739 0 : write(iulog,*) subname//': spec_idx= ', spec_idx, ' nspec= ', modes%comps(m_idx)%nspec
2740 0 : call endrun(subname//': specie list index out of range')
2741 : end if
2742 :
2743 : ! Assume data source is interstitial since that's what's in the constituent array
2744 0 : idx = modes%comps(m_idx)%idx_mmr_a(spec_idx)
2745 :
2746 0 : end subroutine rad_cnst_get_mam_mmr_idx
2747 :
2748 : !================================================================================================
2749 :
2750 0 : subroutine rad_cnst_get_carma_mmr_idx(bin_idx, spec_idx, idx)
2751 :
2752 : ! Return constituent index of camra species mass mixing ratio for aerosol bins in
2753 : ! the climate list.
2754 :
2755 : ! This is a special routine to allow direct access to information in the
2756 : ! constituent array inside physics parameterizations that have been passed,
2757 : ! and are operating over the entire constituent array. The interstitial phase
2758 : ! is assumed since that's what is contained in the constituent array.
2759 :
2760 : ! Arguments
2761 : integer, intent(in) :: bin_idx ! bin index
2762 : integer, intent(in) :: spec_idx ! index of specie in the bin
2763 : integer, intent(out) :: idx ! index of specie in the constituent array
2764 :
2765 : ! Local variables
2766 : integer :: b_idx
2767 : type(binlist_t), pointer :: slist
2768 : character(len=*), parameter :: subname = 'rad_cnst_get_carma_mmr_idx'
2769 : !-----------------------------------------------------------------------------
2770 :
2771 : ! assume climate list (i.e., species are in the constituent array)
2772 0 : slist => sa_list(0)
2773 :
2774 : ! Check for valid bin index
2775 0 : if (bin_idx < 1 .or. bin_idx > slist%nbins) then
2776 0 : write(iulog,*) subname//': bin_idx= ', bin_idx, ' nbins= ', slist%nbins
2777 0 : call endrun(subname//': bin list index out of range')
2778 : end if
2779 :
2780 : ! Get the index for the corresponding bin in the bin definition object
2781 0 : b_idx = slist%idx(bin_idx)
2782 :
2783 : ! Check for valid specie index
2784 0 : if (spec_idx < 1 .or. spec_idx > bins%comps(b_idx)%nspec) then
2785 0 : write(iulog,*) subname//': spec_idx= ', spec_idx, ' nspec= ', bins%comps(b_idx)%nspec
2786 0 : call endrun(subname//': specie list index out of range')
2787 : end if
2788 :
2789 : ! Assume data source is interstitial since that's what's in the constituent array
2790 0 : idx = bins%comps(b_idx)%idx_mmr_a(spec_idx)
2791 :
2792 0 : end subroutine rad_cnst_get_carma_mmr_idx
2793 :
2794 : !================================================================================================
2795 :
2796 0 : subroutine rad_cnst_get_bin_mmr(list_idx, bin_idx, phase, state, pbuf, mmr)
2797 :
2798 : ! Return pointer to mass mixing ratio for the aerosol bin from the specified
2799 : ! climate or diagnostic list.
2800 :
2801 : ! Arguments
2802 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
2803 : integer, intent(in) :: bin_idx ! bin index
2804 : character(len=1), intent(in) :: phase ! 'a' for interstitial, 'c' for cloud borne
2805 : type(physics_state), target, intent(in) :: state
2806 : type(physics_buffer_desc), pointer :: pbuf(:)
2807 : real(r8), pointer :: mmr(:,:)
2808 :
2809 : ! Local variables
2810 : integer :: m_idx
2811 : integer :: idx
2812 : integer :: lchnk
2813 : character(len=1) :: source
2814 : type(binlist_t), pointer :: slist
2815 : character(len=*), parameter :: subname = 'rad_cnst_get_bin_mmr'
2816 : !-----------------------------------------------------------------------------
2817 :
2818 0 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
2819 0 : slist => sa_list(list_idx)
2820 : else
2821 0 : write(iulog,*) subname//': list_idx =', list_idx
2822 0 : call endrun(subname//': list_idx out of bounds')
2823 : endif
2824 :
2825 : ! Check for valid bin index
2826 0 : if (bin_idx < 1 .or. bin_idx > slist%nbins) then
2827 0 : write(iulog,*) subname//': bin_idx= ', bin_idx, ' nbins= ', slist%nbins
2828 0 : call endrun(subname//': bin list index out of range')
2829 : end if
2830 :
2831 : ! Get the index for the corresponding bin in the bin definition object
2832 0 : m_idx = slist%idx(bin_idx)
2833 :
2834 : ! Get data source
2835 0 : if (phase == 'a') then
2836 0 : source = bins%comps(m_idx)%source_mass_a
2837 0 : idx = bins%comps(m_idx)%idx_mass_a
2838 0 : else if (phase == 'c') then
2839 0 : source = bins%comps(m_idx)%source_mass_c
2840 0 : idx = bins%comps(m_idx)%idx_mass_c
2841 : else
2842 0 : write(iulog,*) subname//': phase= ', phase
2843 0 : call endrun(subname//': unrecognized phase; must be "a" or "c"')
2844 : end if
2845 :
2846 0 : lchnk = state%lchnk
2847 :
2848 0 : select case( source )
2849 : case ('A')
2850 0 : mmr => state%q(:,:,idx)
2851 : case ('N')
2852 0 : call pbuf_get_field(pbuf, idx, mmr)
2853 : case ('Z')
2854 0 : mmr => zero_cols
2855 : end select
2856 :
2857 0 : end subroutine rad_cnst_get_bin_mmr
2858 :
2859 : !================================================================================================
2860 :
2861 389601206 : subroutine rad_cnst_get_mode_num(list_idx, mode_idx, phase, state, pbuf, num)
2862 :
2863 : ! Return pointer to number mixing ratio for the aerosol mode from the specified
2864 : ! climate or diagnostic list.
2865 :
2866 : ! Arguments
2867 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
2868 : integer, intent(in) :: mode_idx ! mode index
2869 : character(len=1), intent(in) :: phase ! 'a' for interstitial, 'c' for cloud borne
2870 : type(physics_state), target, intent(in) :: state
2871 : type(physics_buffer_desc), pointer :: pbuf(:)
2872 : real(r8), pointer :: num(:,:)
2873 :
2874 : ! Local variables
2875 : integer :: m_idx
2876 : integer :: idx
2877 : integer :: lchnk
2878 : character(len=1) :: source
2879 : type(modelist_t), pointer :: mlist
2880 : character(len=*), parameter :: subname = 'rad_cnst_get_mode_num'
2881 : !-----------------------------------------------------------------------------
2882 :
2883 389601206 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
2884 389601206 : mlist => ma_list(list_idx)
2885 : else
2886 0 : write(iulog,*) subname//': list_idx =', list_idx
2887 0 : call endrun(subname//': list_idx out of bounds')
2888 : endif
2889 :
2890 : ! Check for valid mode index
2891 389601206 : if (mode_idx < 1 .or. mode_idx > mlist%nmodes) then
2892 0 : write(iulog,*) subname//': mode_idx= ', mode_idx, ' nmodes= ', mlist%nmodes
2893 0 : call endrun(subname//': mode list index out of range')
2894 : end if
2895 :
2896 : ! Get the index for the corresponding mode in the mode definition object
2897 389601206 : m_idx = mlist%idx(mode_idx)
2898 :
2899 : ! Get data source
2900 389601206 : if (phase == 'a') then
2901 197582683 : source = modes%comps(m_idx)%source_num_a
2902 197582683 : idx = modes%comps(m_idx)%idx_num_a
2903 192018523 : else if (phase == 'c') then
2904 192018523 : source = modes%comps(m_idx)%source_num_c
2905 192018523 : idx = modes%comps(m_idx)%idx_num_c
2906 : else
2907 0 : write(iulog,*) subname//': phase= ', phase
2908 0 : call endrun(subname//': unrecognized phase; must be "a" or "c"')
2909 : end if
2910 :
2911 389601206 : lchnk = state%lchnk
2912 :
2913 197582683 : select case( source )
2914 : case ('A')
2915 197582683 : num => state%q(:,:,idx)
2916 : case ('N')
2917 192018523 : call pbuf_get_field(pbuf, idx, num)
2918 : case ('Z')
2919 389601206 : num => zero_cols
2920 : end select
2921 :
2922 389601206 : end subroutine rad_cnst_get_mode_num
2923 :
2924 : !================================================================================================
2925 :
2926 0 : subroutine rad_cnst_get_bin_num(list_idx, bin_idx, phase, state, pbuf, num)
2927 :
2928 : ! Return pointer to number mixing ratio for the aerosol bin from the specified
2929 : ! climate or diagnostic list.
2930 :
2931 : ! Arguments
2932 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
2933 : integer, intent(in) :: bin_idx ! bin index
2934 : character(len=1), intent(in) :: phase ! 'a' for interstitial, 'c' for cloud borne
2935 : type(physics_state), target, intent(in) :: state
2936 : type(physics_buffer_desc), pointer :: pbuf(:)
2937 : real(r8), pointer :: num(:,:)
2938 :
2939 : ! Local variables
2940 : integer :: m_idx
2941 : integer :: idx
2942 : integer :: lchnk
2943 : character(len=1) :: source
2944 : type(binlist_t), pointer :: slist
2945 : character(len=*), parameter :: subname = 'rad_cnst_get_bin_num'
2946 : !-----------------------------------------------------------------------------
2947 :
2948 0 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
2949 0 : slist => sa_list(list_idx)
2950 : else
2951 0 : write(iulog,*) subname//': list_idx =', list_idx
2952 0 : call endrun(subname//': list_idx out of bounds')
2953 : endif
2954 :
2955 : ! Check for valid bin index
2956 0 : if (bin_idx < 1 .or. bin_idx > slist%nbins) then
2957 0 : write(iulog,*) subname//': bin_idx= ', bin_idx, ' nbins= ', slist%nbins
2958 0 : call endrun(subname//': bin list index out of range')
2959 : end if
2960 :
2961 : ! Get the index for the corresponding bin in the bin definition object
2962 0 : m_idx = slist%idx(bin_idx)
2963 :
2964 : ! Get data source
2965 0 : if (phase == 'a') then
2966 0 : source = bins%comps(m_idx)%source_num_a
2967 0 : idx = bins%comps(m_idx)%idx_num_a
2968 0 : else if (phase == 'c') then
2969 0 : source = bins%comps(m_idx)%source_num_c
2970 0 : idx = bins%comps(m_idx)%idx_num_c
2971 : else
2972 0 : write(iulog,*) subname//': phase= ', phase
2973 0 : call endrun(subname//': unrecognized phase; must be "a" or "c"')
2974 : end if
2975 :
2976 0 : lchnk = state%lchnk
2977 :
2978 0 : select case( source )
2979 : case ('A')
2980 0 : num => state%q(:,:,idx)
2981 : case ('N')
2982 0 : call pbuf_get_field(pbuf, idx, num)
2983 : case ('Z')
2984 0 : num => zero_cols
2985 : end select
2986 :
2987 0 : end subroutine rad_cnst_get_bin_num
2988 :
2989 : !================================================================================================
2990 :
2991 0 : subroutine rad_cnst_get_mode_num_idx(mode_idx, cnst_idx)
2992 :
2993 : ! Return constituent index of mode number mixing ratio for the aerosol mode in
2994 : ! the climate list.
2995 :
2996 : ! This is a special routine to allow direct access to information in the
2997 : ! constituent array inside physics parameterizations that have been passed,
2998 : ! and are operating over the entire constituent array. The interstitial phase
2999 : ! is assumed since that's what is contained in the constituent array.
3000 :
3001 : ! Arguments
3002 : integer, intent(in) :: mode_idx ! mode index
3003 : integer, intent(out) :: cnst_idx ! constituent index
3004 :
3005 : ! Local variables
3006 : integer :: m_idx
3007 : character(len=1) :: source
3008 : type(modelist_t), pointer :: mlist
3009 : character(len=*), parameter :: subname = 'rad_cnst_get_mode_num'
3010 : !-----------------------------------------------------------------------------
3011 :
3012 : ! assume climate list
3013 0 : mlist => ma_list(0)
3014 :
3015 : ! Check for valid mode index
3016 0 : if (mode_idx < 1 .or. mode_idx > mlist%nmodes) then
3017 0 : write(iulog,*) subname//': mode_idx= ', mode_idx, ' nmodes= ', mlist%nmodes
3018 0 : call endrun(subname//': mode list index out of range')
3019 : end if
3020 :
3021 : ! Get the index for the corresponding mode in the mode definition object
3022 0 : m_idx = mlist%idx(mode_idx)
3023 :
3024 : ! Check that source is 'A' which means the index is for the constituent array
3025 0 : source = modes%comps(m_idx)%source_num_a
3026 0 : if (source /= 'A') then
3027 0 : write(iulog,*) subname//': source= ', source
3028 0 : call endrun(subname//': requested mode number index not in constituent array')
3029 : end if
3030 :
3031 : ! Return index in constituent array
3032 0 : cnst_idx = modes%comps(m_idx)%idx_num_a
3033 :
3034 0 : end subroutine rad_cnst_get_mode_num_idx
3035 :
3036 : !================================================================================================
3037 :
3038 0 : subroutine rad_cnst_get_bin_num_idx(bin_idx, cnst_idx)
3039 :
3040 : ! Return constituent index of bin number mixing ratio for the aerosol bin in
3041 : ! the climate list.
3042 :
3043 : ! This is a special routine to allow direct access to information in the
3044 : ! constituent array inside physics parameterizations that have been passed,
3045 : ! and are operating over the entire constituent array. The interstitial phase
3046 : ! is assumed since that's what is contained in the constituent array.
3047 :
3048 : ! Arguments
3049 : integer, intent(in) :: bin_idx ! bin index
3050 : integer, intent(out) :: cnst_idx ! constituent index
3051 :
3052 : ! Local variables
3053 : integer :: b_idx
3054 : character(len=1) :: source
3055 : type(binlist_t), pointer :: slist
3056 : character(len=*), parameter :: subname = 'rad_cnst_get_bin_num_idx'
3057 : !-----------------------------------------------------------------------------
3058 :
3059 : ! assume climate list
3060 0 : slist => sa_list(0)
3061 :
3062 : ! Check for valid bin index
3063 0 : if (bin_idx < 1 .or. bin_idx > slist%nbins) then
3064 0 : write(iulog,*) subname//': bin_idx= ', bin_idx, ' nbins= ', slist%nbins
3065 0 : call endrun(subname//': bin list index out of range')
3066 : end if
3067 :
3068 : ! Get the index for the corresponding bin in the bin definition object
3069 0 : b_idx = slist%idx(bin_idx)
3070 :
3071 : ! Check that source is 'A' which means the index is for the constituent array
3072 0 : source = bins%comps(b_idx)%source_num_a
3073 0 : if (source /= 'A') then
3074 0 : write(iulog,*) subname//': source= ', source
3075 0 : call endrun(subname//': requested bin number index not in constituent array')
3076 : end if
3077 :
3078 : ! Return index in constituent array
3079 0 : cnst_idx = bins%comps(b_idx)%idx_num_a
3080 :
3081 0 : end subroutine rad_cnst_get_bin_num_idx
3082 :
3083 : !================================================================================================
3084 :
3085 : integer function rad_cnst_get_aer_idx(list_idx, aer_name)
3086 :
3087 : ! Return the index of aerosol aer_name in the list specified by list_idx.
3088 :
3089 : ! Arguments
3090 : integer, intent(in) :: list_idx ! 0 for climate list, 1-N_DIAG for diagnostic lists
3091 : character(len=*), intent(in) :: aer_name ! aerosol name (in state or pbuf)
3092 :
3093 : ! Local variables
3094 : integer :: i, aer_idx
3095 : type(aerlist_t), pointer :: aerlist
3096 : character(len=*), parameter :: subname = "rad_cnst_get_aer_idx"
3097 : !-------------------------------------------------------------------------
3098 :
3099 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
3100 : aerlist => aerosollist(list_idx)
3101 : else
3102 : write(iulog,*) subname//': list_idx =', list_idx
3103 : call endrun(subname//': list_idx out of bounds')
3104 : endif
3105 :
3106 : ! Get index in aerosol list for requested name
3107 : aer_idx = -1
3108 : do i = 1, aerlist%numaerosols
3109 : if (trim(aer_name) == trim(aerlist%aer(i)%camname)) then
3110 : aer_idx = i
3111 : exit
3112 : end if
3113 : end do
3114 :
3115 : if (aer_idx == -1) call endrun(subname//": ERROR - name not found")
3116 :
3117 : rad_cnst_get_aer_idx = aer_idx
3118 :
3119 : end function rad_cnst_get_aer_idx
3120 :
3121 : !================================================================================================
3122 :
3123 0 : subroutine rad_cnst_get_aer_props_by_idx(list_idx, &
3124 0 : aer_idx, opticstype, &
3125 : sw_hygro_ext, sw_hygro_ssa, sw_hygro_asm, lw_hygro_ext, &
3126 : sw_nonhygro_ext, sw_nonhygro_ssa, sw_nonhygro_asm, &
3127 : sw_nonhygro_scat, sw_nonhygro_ascat, lw_ext, &
3128 : refindex_aer_sw, refindex_aer_lw, &
3129 : r_sw_ext, r_sw_scat, r_sw_ascat, r_lw_abs, mu, &
3130 0 : aername, density_aer, hygro_aer, dryrad_aer, dispersion_aer, num_to_mass_aer)
3131 :
3132 : ! Return requested properties for the aerosol from the specified
3133 : ! climate or diagnostic list.
3134 :
3135 : use phys_prop, only: physprop_get
3136 :
3137 :
3138 : ! Arguments
3139 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
3140 : integer, intent(in) :: aer_idx ! index of the aerosol
3141 : character(len=ot_length), optional, intent(out) :: opticstype
3142 : real(r8), optional, pointer :: sw_hygro_ext(:,:)
3143 : real(r8), optional, pointer :: sw_hygro_ssa(:,:)
3144 : real(r8), optional, pointer :: sw_hygro_asm(:,:)
3145 : real(r8), optional, pointer :: lw_hygro_ext(:,:)
3146 : real(r8), optional, pointer :: sw_nonhygro_ext(:)
3147 : real(r8), optional, pointer :: sw_nonhygro_ssa(:)
3148 : real(r8), optional, pointer :: sw_nonhygro_asm(:)
3149 : real(r8), optional, pointer :: sw_nonhygro_scat(:)
3150 : real(r8), optional, pointer :: sw_nonhygro_ascat(:)
3151 : real(r8), optional, pointer :: lw_ext(:)
3152 : complex(r8), optional, pointer :: refindex_aer_sw(:)
3153 : complex(r8), optional, pointer :: refindex_aer_lw(:)
3154 : character(len=20), optional, intent(out) :: aername
3155 : real(r8), optional, intent(out) :: density_aer
3156 : real(r8), optional, intent(out) :: hygro_aer
3157 : real(r8), optional, intent(out) :: dryrad_aer
3158 : real(r8), optional, intent(out) :: dispersion_aer
3159 : real(r8), optional, intent(out) :: num_to_mass_aer
3160 :
3161 : real(r8), optional, pointer :: r_sw_ext(:,:)
3162 : real(r8), optional, pointer :: r_sw_scat(:,:)
3163 : real(r8), optional, pointer :: r_sw_ascat(:,:)
3164 : real(r8), optional, pointer :: r_lw_abs(:,:)
3165 : real(r8), optional, pointer :: mu(:)
3166 :
3167 : ! Local variables
3168 : integer :: id
3169 : character(len=*), parameter :: subname = 'rad_cnst_get_aer_props_by_idx'
3170 : type(aerlist_t), pointer :: aerlist
3171 : !------------------------------------------------------------------------------------
3172 :
3173 0 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
3174 0 : aerlist => aerosollist(list_idx)
3175 : else
3176 0 : write(iulog,*) subname//': list_idx = ', list_idx
3177 0 : call endrun(subname//': list_idx out of range')
3178 : endif
3179 :
3180 0 : if (aer_idx < 1 .or. aer_idx > aerlist%numaerosols) then
3181 0 : write(iulog,*) subname//': aerosol list index out of range: ', aer_idx ,' list index: ',list_idx
3182 0 : call endrun(subname//': aer_idx out of range')
3183 : end if
3184 :
3185 0 : id = aerlist%aer(aer_idx)%physprop_id
3186 :
3187 0 : if (present(opticstype)) call physprop_get(id, opticstype=opticstype)
3188 :
3189 0 : if (present(sw_hygro_ext)) call physprop_get(id, sw_hygro_ext=sw_hygro_ext)
3190 0 : if (present(sw_hygro_ssa)) call physprop_get(id, sw_hygro_ssa=sw_hygro_ssa)
3191 0 : if (present(sw_hygro_asm)) call physprop_get(id, sw_hygro_asm=sw_hygro_asm)
3192 0 : if (present(lw_hygro_ext)) call physprop_get(id, lw_hygro_abs=lw_hygro_ext)
3193 :
3194 0 : if (present(sw_nonhygro_ext)) call physprop_get(id, sw_nonhygro_ext=sw_nonhygro_ext)
3195 0 : if (present(sw_nonhygro_ssa)) call physprop_get(id, sw_nonhygro_ssa=sw_nonhygro_ssa)
3196 0 : if (present(sw_nonhygro_asm)) call physprop_get(id, sw_nonhygro_asm=sw_nonhygro_asm)
3197 0 : if (present(sw_nonhygro_scat)) call physprop_get(id, sw_nonhygro_scat=sw_nonhygro_scat)
3198 0 : if (present(sw_nonhygro_ascat)) call physprop_get(id, sw_nonhygro_ascat=sw_nonhygro_ascat)
3199 0 : if (present(lw_ext)) call physprop_get(id, lw_abs=lw_ext)
3200 :
3201 0 : if (present(refindex_aer_sw)) call physprop_get(id, refindex_aer_sw=refindex_aer_sw)
3202 0 : if (present(refindex_aer_lw)) call physprop_get(id, refindex_aer_lw=refindex_aer_lw)
3203 :
3204 0 : if (present(aername)) call physprop_get(id, aername=aername)
3205 0 : if (present(density_aer)) call physprop_get(id, density_aer=density_aer)
3206 0 : if (present(hygro_aer)) call physprop_get(id, hygro_aer=hygro_aer)
3207 0 : if (present(dryrad_aer)) call physprop_get(id, dryrad_aer=dryrad_aer)
3208 0 : if (present(dispersion_aer)) call physprop_get(id, dispersion_aer=dispersion_aer)
3209 0 : if (present(num_to_mass_aer)) call physprop_get(id, num_to_mass_aer=num_to_mass_aer)
3210 :
3211 0 : if (present(r_lw_abs)) call physprop_get(id, r_lw_abs=r_lw_abs)
3212 0 : if (present(r_sw_ext)) call physprop_get(id, r_sw_ext=r_sw_ext)
3213 0 : if (present(r_sw_scat)) call physprop_get(id, r_sw_scat=r_sw_scat)
3214 0 : if (present(r_sw_ascat)) call physprop_get(id, r_sw_ascat=r_sw_ascat)
3215 0 : if (present(mu)) call physprop_get(id, mu=mu)
3216 :
3217 0 : end subroutine rad_cnst_get_aer_props_by_idx
3218 :
3219 : !================================================================================================
3220 :
3221 3842548546 : subroutine rad_cnst_get_mam_props_by_idx(list_idx, &
3222 0 : mode_idx, spec_idx, opticstype, &
3223 : sw_hygro_ext, sw_hygro_ssa, sw_hygro_asm, lw_hygro_ext, &
3224 : sw_nonhygro_ext, sw_nonhygro_ssa, sw_nonhygro_asm, &
3225 : sw_nonhygro_scat, sw_nonhygro_ascat, lw_ext, &
3226 : refindex_aer_sw, refindex_aer_lw, &
3227 : r_sw_ext, r_sw_scat, r_sw_ascat, r_lw_abs, mu, &
3228 0 : aername, density_aer, hygro_aer, dryrad_aer, dispersion_aer, &
3229 0 : num_to_mass_aer, spectype)
3230 :
3231 : ! Return requested properties for the aerosol from the specified
3232 : ! climate or diagnostic list.
3233 :
3234 0 : use phys_prop, only: physprop_get
3235 :
3236 : ! Arguments
3237 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
3238 : integer, intent(in) :: mode_idx ! mode index
3239 : integer, intent(in) :: spec_idx ! index of specie in the mode
3240 : character(len=ot_length), optional, intent(out) :: opticstype
3241 : real(r8), optional, pointer :: sw_hygro_ext(:,:)
3242 : real(r8), optional, pointer :: sw_hygro_ssa(:,:)
3243 : real(r8), optional, pointer :: sw_hygro_asm(:,:)
3244 : real(r8), optional, pointer :: lw_hygro_ext(:,:)
3245 : real(r8), optional, pointer :: sw_nonhygro_ext(:)
3246 : real(r8), optional, pointer :: sw_nonhygro_ssa(:)
3247 : real(r8), optional, pointer :: sw_nonhygro_asm(:)
3248 : real(r8), optional, pointer :: sw_nonhygro_scat(:)
3249 : real(r8), optional, pointer :: sw_nonhygro_ascat(:)
3250 : real(r8), optional, pointer :: lw_ext(:)
3251 : complex(r8), optional, pointer :: refindex_aer_sw(:)
3252 : complex(r8), optional, pointer :: refindex_aer_lw(:)
3253 :
3254 : real(r8), optional, pointer :: r_sw_ext(:,:)
3255 : real(r8), optional, pointer :: r_sw_scat(:,:)
3256 : real(r8), optional, pointer :: r_sw_ascat(:,:)
3257 : real(r8), optional, pointer :: r_lw_abs(:,:)
3258 : real(r8), optional, pointer :: mu(:)
3259 :
3260 : character(len=20), optional, intent(out) :: aername
3261 : real(r8), optional, intent(out) :: density_aer
3262 : real(r8), optional, intent(out) :: hygro_aer
3263 : real(r8), optional, intent(out) :: dryrad_aer
3264 : real(r8), optional, intent(out) :: dispersion_aer
3265 : real(r8), optional, intent(out) :: num_to_mass_aer
3266 : character(len=32), optional, intent(out) :: spectype
3267 :
3268 : ! Local variables
3269 : integer :: m_idx, id
3270 : type(modelist_t), pointer :: mlist
3271 : character(len=*), parameter :: subname = 'rad_cnst_get_mam_props_by_idx'
3272 : !------------------------------------------------------------------------------------
3273 :
3274 3842548546 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
3275 3842548546 : mlist => ma_list(list_idx)
3276 : else
3277 0 : write(iulog,*) subname//': list_idx = ', list_idx
3278 0 : call endrun(subname//': list_idx out of range')
3279 : endif
3280 :
3281 : ! Check for valid mode index
3282 3842548546 : if (mode_idx < 1 .or. mode_idx > mlist%nmodes) then
3283 0 : write(iulog,*) subname//': mode_idx= ', mode_idx, ' nmodes= ', mlist%nmodes
3284 0 : call endrun(subname//': mode list index out of range')
3285 : end if
3286 :
3287 : ! Get the index for the corresponding mode in the mode definition object
3288 3842548546 : m_idx = mlist%idx(mode_idx)
3289 :
3290 : ! Check for valid specie index
3291 3842548546 : if (spec_idx < 1 .or. spec_idx > modes%comps(m_idx)%nspec) then
3292 0 : write(iulog,*) subname//': spec_idx= ', spec_idx, ' nspec= ', modes%comps(m_idx)%nspec
3293 0 : call endrun(subname//': specie list index out of range')
3294 : end if
3295 :
3296 3842548546 : id = modes%comps(m_idx)%idx_props(spec_idx)
3297 :
3298 3842548546 : if (present(opticstype)) call physprop_get(id, opticstype=opticstype)
3299 :
3300 3842548546 : if (present(sw_hygro_ext)) call physprop_get(id, sw_hygro_ext=sw_hygro_ext)
3301 3842548546 : if (present(sw_hygro_ssa)) call physprop_get(id, sw_hygro_ssa=sw_hygro_ssa)
3302 3842548546 : if (present(sw_hygro_asm)) call physprop_get(id, sw_hygro_asm=sw_hygro_asm)
3303 3842548546 : if (present(lw_hygro_ext)) call physprop_get(id, lw_hygro_abs=lw_hygro_ext)
3304 :
3305 3842548546 : if (present(sw_nonhygro_ext)) call physprop_get(id, sw_nonhygro_ext=sw_nonhygro_ext)
3306 3842548546 : if (present(sw_nonhygro_ssa)) call physprop_get(id, sw_nonhygro_ssa=sw_nonhygro_ssa)
3307 3842548546 : if (present(sw_nonhygro_asm)) call physprop_get(id, sw_nonhygro_asm=sw_nonhygro_asm)
3308 3842548546 : if (present(sw_nonhygro_scat)) call physprop_get(id, sw_nonhygro_scat=sw_nonhygro_scat)
3309 3842548546 : if (present(sw_nonhygro_ascat)) call physprop_get(id, sw_nonhygro_ascat=sw_nonhygro_ascat)
3310 3842548546 : if (present(lw_ext)) call physprop_get(id, lw_abs=lw_ext)
3311 :
3312 3842548546 : if (present(refindex_aer_sw)) call physprop_get(id, refindex_aer_sw=refindex_aer_sw)
3313 3842548546 : if (present(refindex_aer_lw)) call physprop_get(id, refindex_aer_lw=refindex_aer_lw)
3314 :
3315 3842548546 : if (present(r_lw_abs)) call physprop_get(id, r_lw_abs=r_lw_abs)
3316 3842548546 : if (present(r_sw_ext)) call physprop_get(id, r_sw_ext=r_sw_ext)
3317 3842548546 : if (present(r_sw_scat)) call physprop_get(id, r_sw_scat=r_sw_scat)
3318 3842548546 : if (present(r_sw_ascat)) call physprop_get(id, r_sw_ascat=r_sw_ascat)
3319 3842548546 : if (present(mu)) call physprop_get(id, mu=mu)
3320 :
3321 3842548546 : if (present(aername)) call physprop_get(id, aername=aername)
3322 3842548546 : if (present(density_aer)) call physprop_get(id, density_aer=density_aer)
3323 3842548546 : if (present(hygro_aer)) call physprop_get(id, hygro_aer=hygro_aer)
3324 3842548546 : if (present(dryrad_aer)) call physprop_get(id, dryrad_aer=dryrad_aer)
3325 3842548546 : if (present(dispersion_aer)) call physprop_get(id, dispersion_aer=dispersion_aer)
3326 3842548546 : if (present(num_to_mass_aer)) call physprop_get(id, num_to_mass_aer=num_to_mass_aer)
3327 :
3328 3842548546 : if (present(spectype)) spectype = modes%comps(m_idx)%type(spec_idx)
3329 :
3330 3842548546 : end subroutine rad_cnst_get_mam_props_by_idx
3331 :
3332 : !================================================================================================
3333 :
3334 0 : subroutine rad_cnst_get_bin_props_by_idx(list_idx, &
3335 0 : bin_idx, spec_idx, opticstype, &
3336 : sw_hygro_ext, sw_hygro_ssa, sw_hygro_asm, lw_hygro_ext, &
3337 : sw_nonhygro_ext, sw_nonhygro_ssa, sw_nonhygro_asm, &
3338 : sw_nonhygro_scat, sw_nonhygro_ascat, lw_ext, &
3339 : refindex_aer_sw, refindex_aer_lw, &
3340 : r_sw_ext, r_sw_scat, r_sw_ascat, r_lw_abs, mu, &
3341 0 : aername, density_aer, hygro_aer, dryrad_aer, dispersion_aer, &
3342 0 : num_to_mass_aer, spectype, specmorph)
3343 :
3344 : ! Return requested properties for the aerosol from the specified
3345 : ! climate or diagnostic list.
3346 :
3347 3842548546 : use phys_prop, only: physprop_get
3348 :
3349 : ! Arguments
3350 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
3351 : integer, intent(in) :: bin_idx ! mode index
3352 : integer, intent(in) :: spec_idx ! index of specie in the mode
3353 : character(len=ot_length), optional, intent(out) :: opticstype
3354 : real(r8), optional, pointer :: sw_hygro_ext(:,:)
3355 : real(r8), optional, pointer :: sw_hygro_ssa(:,:)
3356 : real(r8), optional, pointer :: sw_hygro_asm(:,:)
3357 : real(r8), optional, pointer :: lw_hygro_ext(:,:)
3358 : real(r8), optional, pointer :: sw_nonhygro_ext(:)
3359 : real(r8), optional, pointer :: sw_nonhygro_ssa(:)
3360 : real(r8), optional, pointer :: sw_nonhygro_asm(:)
3361 : real(r8), optional, pointer :: sw_nonhygro_scat(:)
3362 : real(r8), optional, pointer :: sw_nonhygro_ascat(:)
3363 : real(r8), optional, pointer :: lw_ext(:)
3364 : complex(r8), optional, pointer :: refindex_aer_sw(:)
3365 : complex(r8), optional, pointer :: refindex_aer_lw(:)
3366 :
3367 : real(r8), optional, pointer :: r_sw_ext(:,:)
3368 : real(r8), optional, pointer :: r_sw_scat(:,:)
3369 : real(r8), optional, pointer :: r_sw_ascat(:,:)
3370 : real(r8), optional, pointer :: r_lw_abs(:,:)
3371 : real(r8), optional, pointer :: mu(:)
3372 :
3373 : character(len=20), optional, intent(out) :: aername
3374 : real(r8), optional, intent(out) :: density_aer
3375 : real(r8), optional, intent(out) :: hygro_aer
3376 : real(r8), optional, intent(out) :: dryrad_aer
3377 : real(r8), optional, intent(out) :: dispersion_aer
3378 : real(r8), optional, intent(out) :: num_to_mass_aer
3379 : character(len=32), optional, intent(out) :: spectype
3380 : character(len=32), optional, intent(out) :: specmorph
3381 :
3382 : ! Local variables
3383 : integer :: m_idx, id
3384 : type(binlist_t), pointer :: slist
3385 : character(len=*), parameter :: subname = 'rad_cnst_get_bin_props_by_idx'
3386 : !------------------------------------------------------------------------------------
3387 :
3388 0 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
3389 0 : slist => sa_list(list_idx)
3390 : else
3391 0 : write(iulog,*) subname//': list_idx = ', list_idx
3392 0 : call endrun(subname//': list_idx out of range')
3393 : endif
3394 :
3395 : ! Check for valid mode index
3396 0 : if (bin_idx < 1 .or. bin_idx > slist%nbins) then
3397 0 : write(iulog,*) subname//': bin_idx= ', bin_idx, ' nbins= ', slist%nbins
3398 0 : call endrun(subname//': bin list index out of range')
3399 : end if
3400 :
3401 : ! Get the index for the corresponding mode in the mode definition object
3402 0 : m_idx = slist%idx(bin_idx)
3403 :
3404 : ! Check for valid specie index
3405 0 : if (spec_idx < 1 .or. spec_idx > bins%comps(m_idx)%nspec) then
3406 0 : write(iulog,*) subname//': spec_idx= ', spec_idx, ' nspec= ', bins%comps(m_idx)%nspec
3407 0 : call endrun(subname//': specie list index out of range')
3408 : end if
3409 :
3410 0 : id = bins%comps(m_idx)%idx_props(spec_idx)
3411 :
3412 0 : if (present(opticstype)) call physprop_get(id, opticstype=opticstype)
3413 :
3414 0 : if (present(sw_hygro_ext)) call physprop_get(id, sw_hygro_ext=sw_hygro_ext)
3415 0 : if (present(sw_hygro_ssa)) call physprop_get(id, sw_hygro_ssa=sw_hygro_ssa)
3416 0 : if (present(sw_hygro_asm)) call physprop_get(id, sw_hygro_asm=sw_hygro_asm)
3417 0 : if (present(lw_hygro_ext)) call physprop_get(id, lw_hygro_abs=lw_hygro_ext)
3418 :
3419 0 : if (present(sw_nonhygro_ext)) call physprop_get(id, sw_nonhygro_ext=sw_nonhygro_ext)
3420 0 : if (present(sw_nonhygro_ssa)) call physprop_get(id, sw_nonhygro_ssa=sw_nonhygro_ssa)
3421 0 : if (present(sw_nonhygro_asm)) call physprop_get(id, sw_nonhygro_asm=sw_nonhygro_asm)
3422 0 : if (present(sw_nonhygro_scat)) call physprop_get(id, sw_nonhygro_scat=sw_nonhygro_scat)
3423 0 : if (present(sw_nonhygro_ascat)) call physprop_get(id, sw_nonhygro_ascat=sw_nonhygro_ascat)
3424 0 : if (present(lw_ext)) call physprop_get(id, lw_abs=lw_ext)
3425 :
3426 0 : if (present(refindex_aer_sw)) call physprop_get(id, refindex_aer_sw=refindex_aer_sw)
3427 0 : if (present(refindex_aer_lw)) call physprop_get(id, refindex_aer_lw=refindex_aer_lw)
3428 :
3429 0 : if (present(r_lw_abs)) call physprop_get(id, r_lw_abs=r_lw_abs)
3430 0 : if (present(r_sw_ext)) call physprop_get(id, r_sw_ext=r_sw_ext)
3431 0 : if (present(r_sw_scat)) call physprop_get(id, r_sw_scat=r_sw_scat)
3432 0 : if (present(r_sw_ascat)) call physprop_get(id, r_sw_ascat=r_sw_ascat)
3433 0 : if (present(mu)) call physprop_get(id, mu=mu)
3434 :
3435 0 : if (present(aername)) call physprop_get(id, aername=aername)
3436 0 : if (present(density_aer)) call physprop_get(id, density_aer=density_aer)
3437 0 : if (present(hygro_aer)) call physprop_get(id, hygro_aer=hygro_aer)
3438 0 : if (present(dryrad_aer)) call physprop_get(id, dryrad_aer=dryrad_aer)
3439 0 : if (present(dispersion_aer)) call physprop_get(id, dispersion_aer=dispersion_aer)
3440 0 : if (present(num_to_mass_aer)) call physprop_get(id, num_to_mass_aer=num_to_mass_aer)
3441 :
3442 0 : if (present(spectype)) spectype = bins%comps(m_idx)%type(spec_idx)
3443 0 : if (present(specmorph)) specmorph = bins%comps(m_idx)%morph(spec_idx)
3444 :
3445 0 : end subroutine rad_cnst_get_bin_props_by_idx
3446 :
3447 : !================================================================================================
3448 :
3449 0 : subroutine rad_cnst_get_mode_props(list_idx, mode_idx, opticstype, &
3450 : extpsw, abspsw, asmpsw, absplw, refrtabsw, &
3451 : refitabsw, refrtablw, refitablw, ncoef, prefr, &
3452 : prefi, sigmag, dgnum, dgnumlo, dgnumhi, &
3453 : rhcrystal, rhdeliques)
3454 :
3455 : ! Return requested properties for the mode from the specified
3456 : ! climate or diagnostic list.
3457 :
3458 0 : use phys_prop, only: physprop_get
3459 :
3460 : ! Arguments
3461 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
3462 : integer, intent(in) :: mode_idx ! mode index
3463 :
3464 : character(len=ot_length), optional, intent(out) :: opticstype
3465 : real(r8), optional, pointer :: extpsw(:,:,:,:)
3466 : real(r8), optional, pointer :: abspsw(:,:,:,:)
3467 : real(r8), optional, pointer :: asmpsw(:,:,:,:)
3468 : real(r8), optional, pointer :: absplw(:,:,:,:)
3469 : real(r8), optional, pointer :: refrtabsw(:,:)
3470 : real(r8), optional, pointer :: refitabsw(:,:)
3471 : real(r8), optional, pointer :: refrtablw(:,:)
3472 : real(r8), optional, pointer :: refitablw(:,:)
3473 : integer, optional, intent(out) :: ncoef
3474 : integer, optional, intent(out) :: prefr
3475 : integer, optional, intent(out) :: prefi
3476 : real(r8), optional, intent(out) :: sigmag
3477 : real(r8), optional, intent(out) :: dgnum
3478 : real(r8), optional, intent(out) :: dgnumlo
3479 : real(r8), optional, intent(out) :: dgnumhi
3480 : real(r8), optional, intent(out) :: rhcrystal
3481 : real(r8), optional, intent(out) :: rhdeliques
3482 :
3483 : ! Local variables
3484 : integer :: id
3485 : type(modelist_t), pointer :: mlist
3486 : character(len=*), parameter :: subname = 'rad_cnst_get_mode_props'
3487 : !------------------------------------------------------------------------------------
3488 :
3489 8047501 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
3490 8047501 : mlist => ma_list(list_idx)
3491 : else
3492 0 : write(iulog,*) subname//': list_idx = ', list_idx
3493 0 : call endrun(subname//': list_idx out of range')
3494 : endif
3495 :
3496 : ! Check for valid mode index
3497 8047501 : if (mode_idx < 1 .or. mode_idx > mlist%nmodes) then
3498 0 : write(iulog,*) subname//': mode_idx= ', mode_idx, ' nmodes= ', mlist%nmodes
3499 0 : call endrun(subname//': mode list index out of range')
3500 : end if
3501 :
3502 : ! Get the physprop index for the requested mode
3503 8047501 : id = mlist%idx_props(mode_idx)
3504 :
3505 8047501 : if (present(opticstype)) call physprop_get(id, opticstype=opticstype)
3506 8047501 : if (present(extpsw)) call physprop_get(id, extpsw=extpsw)
3507 8047501 : if (present(abspsw)) call physprop_get(id, abspsw=abspsw)
3508 8047501 : if (present(asmpsw)) call physprop_get(id, asmpsw=asmpsw)
3509 8047501 : if (present(absplw)) call physprop_get(id, absplw=absplw)
3510 :
3511 8047501 : if (present(refrtabsw)) call physprop_get(id, refrtabsw=refrtabsw)
3512 8047501 : if (present(refitabsw)) call physprop_get(id, refitabsw=refitabsw)
3513 8047501 : if (present(refrtablw)) call physprop_get(id, refrtablw=refrtablw)
3514 8047501 : if (present(refitablw)) call physprop_get(id, refitablw=refitablw)
3515 :
3516 8047501 : if (present(ncoef)) call physprop_get(id, ncoef=ncoef)
3517 8047501 : if (present(prefr)) call physprop_get(id, prefr=prefr)
3518 8047501 : if (present(prefi)) call physprop_get(id, prefi=prefi)
3519 8047501 : if (present(sigmag)) call physprop_get(id, sigmag=sigmag)
3520 8047501 : if (present(dgnum)) call physprop_get(id, dgnum=dgnum)
3521 8047501 : if (present(dgnumlo)) call physprop_get(id, dgnumlo=dgnumlo)
3522 8047501 : if (present(dgnumhi)) call physprop_get(id, dgnumhi=dgnumhi)
3523 8047501 : if (present(rhcrystal)) call physprop_get(id, rhcrystal=rhcrystal)
3524 8047501 : if (present(rhdeliques)) call physprop_get(id, rhdeliques=rhdeliques)
3525 :
3526 8047501 : end subroutine rad_cnst_get_mode_props
3527 :
3528 : !================================================================================================
3529 :
3530 0 : subroutine rad_cnst_get_bin_props(list_idx, bin_idx, opticstype, &
3531 : extpsw, abspsw, asmpsw, absplw, corefrac, nfrac, &
3532 : wgtpct, nwtp, bcdust, nbcdust, kap, nkap, relh, nrelh, &
3533 : sw_hygro_ext_wtp, sw_hygro_ssa_wtp, sw_hygro_asm_wtp, lw_hygro_ext_wtp, &
3534 : sw_hygro_coreshell_ext, sw_hygro_coreshell_ssa, sw_hygro_coreshell_asm, lw_hygro_coreshell_ext, dryrad )
3535 :
3536 : ! Return requested properties for the bin from the specified
3537 : ! climate or diagnostic list.
3538 :
3539 8047501 : use phys_prop, only: physprop_get
3540 :
3541 : ! Arguments
3542 : integer, intent(in) :: list_idx ! index of the climate or a diagnostic list
3543 : integer, intent(in) :: bin_idx ! mode index
3544 :
3545 : character(len=ot_length), optional, intent(out) :: opticstype
3546 :
3547 : real(r8), optional, pointer :: extpsw(:,:)
3548 : real(r8), optional, pointer :: abspsw(:,:)
3549 : real(r8), optional, pointer :: asmpsw(:,:)
3550 : real(r8), optional, pointer :: absplw(:,:)
3551 : real(r8), optional, pointer :: corefrac(:)
3552 : integer, optional, intent(out) :: nfrac
3553 :
3554 : real(r8), optional, pointer :: sw_hygro_ext_wtp(:,:)
3555 : real(r8), optional, pointer :: sw_hygro_ssa_wtp(:,:)
3556 : real(r8), optional, pointer :: sw_hygro_asm_wtp(:,:)
3557 : real(r8), optional, pointer :: lw_hygro_ext_wtp(:,:)
3558 : real(r8), optional, pointer :: sw_hygro_coreshell_ext(:,:,:,:,:) ! Pengfei Yu Mar.30
3559 : real(r8), optional, pointer :: sw_hygro_coreshell_ssa(:,:,:,:,:)
3560 : real(r8), optional, pointer :: sw_hygro_coreshell_asm(:,:,:,:,:)
3561 : real(r8), optional, pointer :: lw_hygro_coreshell_ext(:,:,:,:,:)
3562 : real(r8), optional, pointer :: wgtpct(:)
3563 : real(r8), optional, pointer :: bcdust(:)
3564 : real(r8), optional, pointer :: kap(:)
3565 : real(r8), optional, pointer :: relh(:)
3566 : integer, optional, intent(out) :: nwtp
3567 : integer, optional, intent(out) :: nbcdust
3568 : integer, optional, intent(out) :: nkap
3569 : integer, optional, intent(out) :: nrelh
3570 : real(r8), optional, intent(out) :: dryrad
3571 :
3572 : ! Local variables
3573 : integer :: id
3574 : type(binlist_t), pointer :: slist
3575 : character(len=*), parameter :: subname = 'rad_cnst_get_bin_props'
3576 : !------------------------------------------------------------------------------------
3577 :
3578 0 : if (list_idx >= 0 .and. list_idx <= N_DIAG) then
3579 0 : slist => sa_list(list_idx)
3580 : else
3581 0 : write(iulog,*) subname//': list_idx = ', list_idx
3582 0 : call endrun(subname//': list_idx out of range')
3583 : endif
3584 :
3585 : ! Check for valid mode index
3586 0 : if (bin_idx < 1 .or. bin_idx > slist%nbins) then
3587 0 : write(iulog,*) subname//': bin_idx= ', bin_idx, ' nbins= ', slist%nbins
3588 0 : call endrun(subname//': bin list index out of range')
3589 : end if
3590 :
3591 : ! Get the physprop index for the requested bin
3592 0 : id = slist%idx_props(bin_idx)
3593 :
3594 0 : if (present(opticstype)) call physprop_get(id, opticstype=opticstype)
3595 0 : if (present(extpsw)) call physprop_get(id, extpsw2=extpsw)
3596 0 : if (present(abspsw)) call physprop_get(id, abspsw2=abspsw)
3597 0 : if (present(asmpsw)) call physprop_get(id, asmpsw2=asmpsw)
3598 0 : if (present(absplw)) call physprop_get(id, absplw2=absplw)
3599 0 : if (present(corefrac)) call physprop_get(id, corefrac=corefrac)
3600 0 : if (present(nfrac)) call physprop_get(id, nfrac=nfrac)
3601 :
3602 0 : if (present(sw_hygro_ext_wtp)) call physprop_get(id, sw_hygro_ext_wtp=sw_hygro_ext_wtp)
3603 0 : if (present(sw_hygro_ssa_wtp)) call physprop_get(id, sw_hygro_ssa_wtp=sw_hygro_ssa_wtp)
3604 0 : if (present(sw_hygro_asm_wtp)) call physprop_get(id, sw_hygro_asm_wtp=sw_hygro_asm_wtp)
3605 0 : if (present(lw_hygro_ext_wtp)) call physprop_get(id, lw_hygro_abs_wtp=lw_hygro_ext_wtp)
3606 0 : if (present(sw_hygro_coreshell_ext)) call physprop_get(id, sw_hygro_coreshell_ext=sw_hygro_coreshell_ext)
3607 0 : if (present(sw_hygro_coreshell_ssa)) call physprop_get(id, sw_hygro_coreshell_ssa=sw_hygro_coreshell_ssa)
3608 0 : if (present(sw_hygro_coreshell_asm)) call physprop_get(id, sw_hygro_coreshell_asm=sw_hygro_coreshell_asm)
3609 0 : if (present(lw_hygro_coreshell_ext)) call physprop_get(id, lw_hygro_coreshell_abs=lw_hygro_coreshell_ext)
3610 0 : if (present(wgtpct)) call physprop_get(id, wgtpct=wgtpct)
3611 0 : if (present(bcdust)) call physprop_get(id, bcdust=bcdust)
3612 0 : if (present(kap)) call physprop_get(id, kap=kap)
3613 0 : if (present(relh)) call physprop_get(id, relh=relh)
3614 0 : if (present(nwtp)) call physprop_get(id, nwtp=nwtp)
3615 0 : if (present(nbcdust)) call physprop_get(id, nbcdust=nbcdust)
3616 0 : if (present(nkap)) call physprop_get(id, nkap=nkap)
3617 0 : if (present(nrelh)) call physprop_get(id, nrelh=nrelh)
3618 0 : if (present(dryrad)) call physprop_get(id, dryrad_aer=dryrad)
3619 :
3620 0 : end subroutine rad_cnst_get_bin_props
3621 :
3622 : !================================================================================================
3623 :
3624 2 : subroutine print_modes(modes)
3625 :
3626 : type(modes_t), intent(inout) :: modes
3627 :
3628 : integer :: i, m
3629 : !---------------------------------------------------------------------------------------------
3630 :
3631 2 : write(iulog,*)' Mode Definitions'
3632 :
3633 12 : do m = 1, modes%nmodes
3634 :
3635 10 : write(iulog,*) nl//' name=',trim(modes%names(m)),' type=',trim(modes%types(m))
3636 10 : write(iulog,*) ' src_a=',trim(modes%comps(m)%source_num_a),' num_a=',trim(modes%comps(m)%camname_num_a), &
3637 20 : ' src_c=',trim(modes%comps(m)%source_num_c),' num_c=',trim(modes%comps(m)%camname_num_c)
3638 :
3639 104 : do i = 1, modes%comps(m)%nspec
3640 :
3641 92 : write(iulog,*) ' src_a=',trim(modes%comps(m)%source_mmr_a(i)), ' mmr_a=',trim(modes%comps(m)%camname_mmr_a(i)), &
3642 92 : ' src_c=',trim(modes%comps(m)%source_mmr_c(i)), ' mmr_c=',trim(modes%comps(m)%camname_mmr_c(i)), &
3643 184 : ' type=',trim(modes%comps(m)%type(i))
3644 102 : write(iulog,*) ' prop file=', trim(modes%comps(m)%props(i))
3645 : end do
3646 :
3647 : end do
3648 :
3649 0 : end subroutine print_modes
3650 :
3651 : !================================================================================================
3652 :
3653 2 : subroutine print_bins(bins)
3654 :
3655 : type(bins_t), intent(inout) :: bins
3656 :
3657 : integer :: i, m
3658 : !---------------------------------------------------------------------------------------------
3659 :
3660 2 : write(iulog,*)' Bin Definitions'
3661 :
3662 2 : do m = 1, bins%nbins
3663 :
3664 0 : write(iulog,*) nl//' name=',trim(bins%names(m))
3665 :
3666 2 : do i = 1, bins%comps(m)%nspec
3667 :
3668 0 : write(iulog,*) ' src_a=',trim(bins%comps(m)%source_mmr_a(i)), ' mmr_a=',trim(bins%comps(m)%camname_mmr_a(i)), &
3669 0 : ' type=',trim(bins%comps(m)%type(i))
3670 0 : write(iulog,*) ' prop file=', trim(bins%comps(m)%props(i))
3671 : end do
3672 :
3673 : end do
3674 :
3675 2 : end subroutine print_bins
3676 :
3677 : !================================================================================================
3678 :
3679 2 : subroutine print_lists(gas_list, aer_list, ma_list, sa_list)
3680 :
3681 : ! Print summary of gas, bulk and modal aerosol lists. This is just the information
3682 : ! read from the namelist.
3683 :
3684 : use radconstants, only: gascnst=>gaslist
3685 :
3686 : type(aerlist_t), intent(in) :: aer_list
3687 : type(gaslist_t), intent(in) :: gas_list
3688 : type(modelist_t), intent(in) :: ma_list
3689 : type(binlist_t), intent(in) :: sa_list
3690 :
3691 : integer :: i, id
3692 :
3693 2 : if (len_trim(gas_list%list_id) == 0) then
3694 2 : write(iulog,*) nl//' gas list for climate calculations'
3695 : else
3696 0 : write(iulog,*) nl//' gas list for diag'//gas_list%list_id//' calculations'
3697 : end if
3698 :
3699 18 : do i = 1, nradgas
3700 18 : if (gas_list%gas(i)%source .eq. 'N') then
3701 4 : write(iulog,*) ' '//gas_list%gas(i)%source//':'//gascnst(i)//' has pbuf name:'//&
3702 8 : trim(gas_list%gas(i)%camname)
3703 12 : else if (gas_list%gas(i)%source .eq. 'A') then
3704 12 : write(iulog,*) ' '//gas_list%gas(i)%source//':'//gascnst(i)//' has constituents name:'//&
3705 24 : trim(gas_list%gas(i)%camname)
3706 : endif
3707 : enddo
3708 :
3709 2 : if (len_trim(aer_list%list_id) == 0) then
3710 2 : write(iulog,*) nl//' bulk aerosol list for climate calculations'
3711 : else
3712 0 : write(iulog,*) nl//' bulk aerosol list for diag'//aer_list%list_id//' calculations'
3713 : end if
3714 :
3715 2 : do i = 1, aer_list%numaerosols
3716 0 : write(iulog,*) ' '//trim(aer_list%aer(i)%source)//':'//trim(aer_list%aer(i)%camname)//&
3717 2 : ' optics and phys props in :'//trim(aer_list%aer(i)%physprop_file)
3718 : enddo
3719 :
3720 2 : if (len_trim(ma_list%list_id) == 0) then
3721 2 : write(iulog,*) nl//' modal aerosol list for climate calculations'
3722 : else
3723 0 : write(iulog,*) nl//' modal aerosol list for diag'//ma_list%list_id//' calculations'
3724 : end if
3725 :
3726 12 : do i = 1, ma_list%nmodes
3727 10 : id = ma_list%idx(i)
3728 12 : write(iulog,*) ' '//trim(modes%names(id))
3729 : enddo
3730 :
3731 2 : if (len_trim(sa_list%list_id) == 0) then
3732 2 : write(iulog,*) nl//' bin aerosol list for climate calculations'
3733 : else
3734 0 : write(iulog,*) nl//' bin aerosol list for diag'//sa_list%list_id//' calculations'
3735 : end if
3736 :
3737 2 : do i = 1, sa_list%nbins
3738 0 : id = sa_list%idx(i)
3739 2 : write(iulog,*) ' '//trim(bins%names(id))
3740 : enddo
3741 :
3742 2 : end subroutine print_lists
3743 :
3744 : !================================================================================================
3745 :
3746 0 : end module rad_constituents
|