Line data Source code
1 : !-------------------------------------------------------------------
2 : ! manages reading and interpolation of offline tracer fields
3 : ! Created by: Francis Vitt -- 2 May 2006
4 : !-------------------------------------------------------------------
5 : module tracer_cnst
6 :
7 : use shr_kind_mod, only : r8 => shr_kind_r8
8 : use cam_abortutils, only : endrun
9 : use spmd_utils, only : masterproc
10 : use tracer_data, only : trfld,trfile,MAXTRCRS
11 : use cam_logfile, only : iulog
12 :
13 : implicit none
14 :
15 : private ! all unless made public
16 : save
17 :
18 : public :: tracer_cnst_init
19 : public :: num_tracer_cnst
20 : public :: tracer_cnst_flds
21 : public :: tracer_cnst_adv
22 : public :: get_cnst_data
23 : public :: get_cnst_data_ptr
24 : public :: write_tracer_cnst_restart
25 : public :: read_tracer_cnst_restart
26 : public :: tracer_cnst_defaultopts
27 : public :: tracer_cnst_setopts
28 : public :: init_tracer_cnst_restart
29 :
30 : type(trfld), pointer :: fields(:) => null()
31 : type(trfile) :: file
32 :
33 : integer :: num_tracer_cnst
34 : character(len=16), pointer :: tracer_cnst_flds(:) => null()
35 : real(r8), allocatable, target, dimension(:,:,:,:) :: data_q ! constituent mass mixing ratios
36 :
37 : character(len=64) :: specifier(MAXTRCRS) = ''
38 : character(len=256) :: filename = 'tracer_cnst_file'
39 : character(len=256) :: filelist = ''
40 : character(len=256) :: datapath = ''
41 : character(len=32) :: data_type = 'SERIAL'
42 : logical :: rmv_file = .false.
43 : integer :: cycle_yr = 0
44 : integer :: fixed_ymd = 0
45 : integer :: fixed_tod = 0
46 :
47 : contains
48 :
49 : !-------------------------------------------------------------------
50 : !-------------------------------------------------------------------
51 2304 : subroutine tracer_cnst_init()
52 :
53 : use mo_chem_utls,only : get_inv_ndx
54 : use tracer_data, only : trcdata_init
55 : use cam_history, only : addfld
56 : use error_messages, only: handle_err
57 : use ppgrid, only: pcols, pver, begchunk, endchunk
58 : use physics_buffer, only : physics_buffer_desc
59 :
60 : implicit none
61 :
62 : integer :: i ,ndx, istat
63 :
64 1536 : allocate(file%in_pbuf(size(specifier)))
65 155136 : file%in_pbuf(:) = .false.
66 : call trcdata_init( specifier, filename, filelist, datapath, fields, file, &
67 1536 : rmv_file, cycle_yr, fixed_ymd, fixed_tod, data_type)
68 :
69 1536 : num_tracer_cnst = 0
70 1536 : if (associated(fields)) num_tracer_cnst = size( fields )
71 :
72 1536 : if( num_tracer_cnst < 1 ) then
73 0 : if ( masterproc ) then
74 0 : write(iulog,*) 'There are no offline invariant species'
75 0 : write(iulog,*) ' '
76 : endif
77 : return
78 : end if
79 :
80 4608 : allocate( tracer_cnst_flds(num_tracer_cnst), stat=istat)
81 1536 : call handle_err(istat, 'tracer_cnst_init: ERROR allocating tracer_cnst_flds')
82 :
83 :
84 9216 : do i = 1, num_tracer_cnst
85 :
86 7680 : ndx = get_inv_ndx( fields(i)%fldnam )
87 :
88 7680 : if (ndx < 1) then
89 0 : write(iulog,*) fields(i)%fldnam//' is not an invariant'
90 0 : call endrun('tracer_cnst_init')
91 : endif
92 :
93 7680 : tracer_cnst_flds(i) = fields(i)%fldnam
94 :
95 0 : call addfld(trim(fields(i)%fldnam), (/ 'lev' /), &
96 16896 : 'I','mol/mol', 'prescribed tracer constituent' )
97 : enddo
98 :
99 6144 : allocate(data_q(pcols,pver,num_tracer_cnst,begchunk:endchunk), stat=istat)
100 1536 : call handle_err(istat, 'tracer_cnst_init: ERROR allocating data_q')
101 :
102 1536 : end subroutine tracer_cnst_init
103 :
104 : !-------------------------------------------------------------------
105 : !-------------------------------------------------------------------
106 1536 : subroutine tracer_cnst_setopts( &
107 : tracer_cnst_file_in, &
108 : tracer_cnst_filelist_in, &
109 : tracer_cnst_datapath_in, &
110 : tracer_cnst_type_in, &
111 1536 : tracer_cnst_specifier_in, &
112 : tracer_cnst_rmfile_in, &
113 : tracer_cnst_cycle_yr_in, &
114 : tracer_cnst_fixed_ymd_in, &
115 : tracer_cnst_fixed_tod_in &
116 : )
117 :
118 : implicit none
119 :
120 : character(len=*), intent(in), optional :: tracer_cnst_file_in
121 : character(len=*), intent(in), optional :: tracer_cnst_filelist_in
122 : character(len=*), intent(in), optional :: tracer_cnst_datapath_in
123 : character(len=*), intent(in), optional :: tracer_cnst_type_in
124 : character(len=*), intent(in), optional :: tracer_cnst_specifier_in(:)
125 : logical, intent(in), optional :: tracer_cnst_rmfile_in
126 : integer, intent(in), optional :: tracer_cnst_cycle_yr_in
127 : integer, intent(in), optional :: tracer_cnst_fixed_ymd_in
128 : integer, intent(in), optional :: tracer_cnst_fixed_tod_in
129 :
130 1536 : if ( present(tracer_cnst_file_in) ) then
131 1536 : filename = tracer_cnst_file_in
132 : endif
133 1536 : if ( present(tracer_cnst_filelist_in) ) then
134 1536 : filelist = tracer_cnst_filelist_in
135 : endif
136 1536 : if ( present(tracer_cnst_datapath_in) ) then
137 1536 : datapath = tracer_cnst_datapath_in
138 : endif
139 1536 : if ( present(tracer_cnst_type_in) ) then
140 1536 : data_type = tracer_cnst_type_in
141 : endif
142 1536 : if ( present(tracer_cnst_specifier_in) ) then
143 156672 : specifier = tracer_cnst_specifier_in
144 : endif
145 1536 : if ( present(tracer_cnst_rmfile_in) ) then
146 1536 : rmv_file = tracer_cnst_rmfile_in
147 : endif
148 1536 : if ( present(tracer_cnst_cycle_yr_in) ) then
149 1536 : cycle_yr = tracer_cnst_cycle_yr_in
150 : endif
151 1536 : if ( present(tracer_cnst_fixed_ymd_in) ) then
152 1536 : fixed_ymd = tracer_cnst_fixed_ymd_in
153 : endif
154 1536 : if ( present(tracer_cnst_fixed_tod_in) ) then
155 1536 : fixed_tod = tracer_cnst_fixed_tod_in
156 : endif
157 :
158 3072 : endsubroutine tracer_cnst_setopts
159 :
160 : !-------------------------------------------------------------------
161 : !-------------------------------------------------------------------
162 1536 : subroutine tracer_cnst_defaultopts( &
163 : tracer_cnst_file_out, &
164 : tracer_cnst_filelist_out, &
165 : tracer_cnst_datapath_out, &
166 : tracer_cnst_type_out, &
167 1536 : tracer_cnst_specifier_out,&
168 : tracer_cnst_rmfile_out, &
169 : tracer_cnst_cycle_yr_out, &
170 : tracer_cnst_fixed_ymd_out,&
171 : tracer_cnst_fixed_tod_out &
172 : )
173 :
174 : implicit none
175 :
176 : character(len=*), intent(out), optional :: tracer_cnst_file_out
177 : character(len=*), intent(out), optional :: tracer_cnst_filelist_out
178 : character(len=*), intent(out), optional :: tracer_cnst_datapath_out
179 : character(len=*), intent(out), optional :: tracer_cnst_type_out
180 : character(len=*), intent(out), optional :: tracer_cnst_specifier_out(:)
181 : logical, intent(out), optional :: tracer_cnst_rmfile_out
182 : integer, intent(out), optional :: tracer_cnst_cycle_yr_out
183 : integer, intent(out), optional :: tracer_cnst_fixed_ymd_out
184 : integer, intent(out), optional :: tracer_cnst_fixed_tod_out
185 :
186 1536 : if ( present(tracer_cnst_file_out) ) then
187 1536 : tracer_cnst_file_out = filename
188 : endif
189 1536 : if ( present(tracer_cnst_filelist_out) ) then
190 1536 : tracer_cnst_filelist_out = filelist
191 : endif
192 1536 : if ( present(tracer_cnst_datapath_out) ) then
193 1536 : tracer_cnst_datapath_out = datapath
194 : endif
195 1536 : if ( present(tracer_cnst_type_out) ) then
196 1536 : tracer_cnst_type_out = data_type
197 : endif
198 1536 : if ( present(tracer_cnst_specifier_out) ) then
199 156672 : tracer_cnst_specifier_out = specifier
200 : endif
201 1536 : if ( present(tracer_cnst_rmfile_out) ) then
202 1536 : tracer_cnst_rmfile_out = rmv_file
203 : endif
204 1536 : if ( present(tracer_cnst_cycle_yr_out) ) then
205 1536 : tracer_cnst_cycle_yr_out = cycle_yr
206 : endif
207 1536 : if ( present(tracer_cnst_fixed_ymd_out) ) then
208 1536 : tracer_cnst_fixed_ymd_out = fixed_ymd
209 : endif
210 1536 : if ( present(tracer_cnst_fixed_tod_out) ) then
211 1536 : tracer_cnst_fixed_tod_out = fixed_tod
212 : endif
213 :
214 1536 : endsubroutine tracer_cnst_defaultopts
215 :
216 : !-------------------------------------------------------------------
217 : !-------------------------------------------------------------------
218 741888 : subroutine tracer_cnst_adv( pbuf2d, state )
219 :
220 : use physics_buffer, only : physics_buffer_desc
221 : use tracer_data, only : advance_trcdata
222 : use physics_types,only : physics_state
223 : use ppgrid, only : begchunk, endchunk
224 : use ppgrid, only : pcols, pver
225 : use string_utils, only : to_lower, GLC
226 : use chem_mods, only : fix_mass
227 : use mo_chem_utls, only : get_inv_ndx
228 : use cam_history, only : outfld
229 : use physconst, only: mwdry ! molecular weight dry air ~ kg/kmole
230 : use physconst, only: boltz
231 :
232 : implicit none
233 :
234 : type(physics_state), intent(in):: state(begchunk:endchunk)
235 : type(physics_buffer_desc), pointer :: pbuf2d(:,:)
236 :
237 : integer :: i,ind,c,ncol
238 : real(r8) :: to_vmr(pcols,pver)
239 :
240 370944 : if( num_tracer_cnst < 1 ) return
241 :
242 370944 : call advance_trcdata( fields, file, state, pbuf2d )
243 :
244 : ! copy prescribed tracer fields into state variable with the correct units
245 :
246 2225664 : do i = 1,num_tracer_cnst
247 1854720 : ind = get_inv_ndx( tracer_cnst_flds(i) )
248 9702504 : do c = begchunk,endchunk
249 7476840 : ncol = state(c)%ncol
250 :
251 14953680 : select case ( to_lower(trim(fields(i)%units(:GLC(fields(i)%units)))) )
252 : case ("molec/cm3","/cm3","molecules/cm3","cm^-3","cm**-3")
253 0 : to_vmr(:ncol,:) = (1.e6_r8*boltz*state(c)%t(:ncol,:))/(state(c)%pmiddry(:ncol,:))
254 : case ('kg/kg','mmr')
255 0 : to_vmr(:ncol,:) = mwdry/fix_mass(ind)
256 : case ('mol/mol','mole/mole','vmr')
257 11618139960 : to_vmr(:ncol,:) = 1._r8
258 : case default
259 0 : write(iulog,*) 'tracer_cnst_adv: units = ',trim(fields(i)%units) ,' are not recognized'
260 14953680 : call endrun('tracer_cnst_adv: units are not recognized')
261 : end select
262 :
263 11618139960 : fields(i)%data(:ncol,:,c) = to_vmr(:ncol,:) * fields(i)%data(:ncol,:,c) ! vmr
264 9331560 : call outfld( trim(tracer_cnst_flds(i)), fields(i)%data(:ncol,:,c), ncol, state(c)%lchnk )
265 :
266 : enddo
267 : enddo
268 :
269 370944 : end subroutine tracer_cnst_adv
270 :
271 : !-------------------------------------------------------------------
272 : !-------------------------------------------------------------------
273 7445880 : subroutine get_cnst_data( field_name, data, ncol, lchnk, pbuf )
274 :
275 370944 : use tracer_data, only : get_fld_data
276 : use physics_buffer, only : physics_buffer_desc
277 :
278 : implicit none
279 :
280 : character(len=*), intent(in) :: field_name
281 : real(r8), intent(out) :: data(:,:)
282 : integer, intent(in) :: lchnk
283 : integer, intent(in) :: ncol
284 : type(physics_buffer_desc), pointer :: pbuf(:)
285 :
286 7445880 : if( num_tracer_cnst < 1 ) return
287 :
288 7445880 : call get_fld_data( fields, field_name, data, ncol, lchnk, pbuf )
289 :
290 7445880 : end subroutine get_cnst_data
291 :
292 : !-------------------------------------------------------------------
293 : !-------------------------------------------------------------------
294 1495368 : subroutine get_cnst_data_ptr(name, state, q, pbuf)
295 :
296 7445880 : use tracer_data, only : get_fld_data, get_fld_ndx
297 : use physconst, only : mwdry ! molecular weight dry air ~ kg/kmole
298 : use chem_mods, only : fix_mass
299 : use mo_chem_utls, only : get_inv_ndx
300 : use physics_types, only : physics_state
301 : use ppgrid, only : pcols, pver
302 : use physics_buffer, only : physics_buffer_desc
303 :
304 : implicit none
305 :
306 : character(len=*), intent(in) :: name
307 : type(physics_state), intent(in) :: state
308 : real(r8), pointer, dimension(:,:) :: q ! constituent mass mixing ratio
309 : type(physics_buffer_desc), pointer :: pbuf(:)
310 :
311 : integer :: lchnk
312 : integer :: ncol
313 : integer :: inv_id, idx
314 : character(len=80) :: error_str
315 :
316 1495368 : lchnk = state%lchnk
317 1495368 : ncol = state%ncol
318 :
319 : ! make sure the requested constituent can be provided
320 1495368 : inv_id = get_inv_ndx(name)
321 1495368 : if (.not. inv_id > 0) then
322 0 : if (masterproc) then
323 0 : write(iulog,*) 'get_cnst_data_ptr: '//name//' is not a prescribed tracer constituent'
324 : endif
325 : return
326 : endif
327 :
328 :
329 1495368 : call get_fld_ndx( fields, name, idx )
330 1495368 : if (idx<1) then
331 0 : write(error_str,*) 'get_cnst_data_ptr: ',trim(name),' not found ... idx : ',idx
332 0 : if (masterproc) then
333 0 : write(iulog,*) error_str
334 : end if
335 0 : call endrun(error_str)
336 : end if
337 1495368 : call get_fld_data( fields, name, data_q(:,:,idx,lchnk), ncol, lchnk, pbuf )
338 :
339 2323627992 : data_q(:ncol,:,idx,lchnk) = data_q(:ncol,:,idx,lchnk)*fix_mass(inv_id)/mwdry ! vmr->mmr
340 1495368 : q => data_q(:,:,idx,lchnk)
341 :
342 1495368 : end subroutine get_cnst_data_ptr
343 :
344 : !-------------------------------------------------------------------
345 :
346 1536 : subroutine init_tracer_cnst_restart( piofile )
347 1495368 : use pio, only : file_desc_t
348 : use tracer_data, only : init_trc_restart
349 : implicit none
350 : type(file_desc_t),intent(inout) :: pioFile ! pio File pointer
351 :
352 1536 : call init_trc_restart( 'tracer_cnst', piofile, file )
353 :
354 1536 : end subroutine init_tracer_cnst_restart
355 : !-------------------------------------------------------------------
356 1536 : subroutine write_tracer_cnst_restart( piofile )
357 1536 : use tracer_data, only : write_trc_restart
358 : use pio, only : file_desc_t
359 : implicit none
360 :
361 : type(file_desc_t) :: piofile
362 :
363 1536 : call write_trc_restart( piofile, file )
364 :
365 1536 : end subroutine write_tracer_cnst_restart
366 :
367 : !-------------------------------------------------------------------
368 768 : subroutine read_tracer_cnst_restart( pioFile )
369 1536 : use tracer_data, only : read_trc_restart
370 : use pio, only : file_desc_t
371 : implicit none
372 :
373 : type(file_desc_t) :: piofile
374 :
375 768 : call read_trc_restart( 'tracer_cnst', piofile, file )
376 :
377 768 : end subroutine read_tracer_cnst_restart
378 :
379 : end module tracer_cnst
|