PartMC  2.8.0
mosaic.F90
Go to the documentation of this file.
1 ! Copyright (C) 2007-2012, 2016 Matthew West
2 ! Licensed under the GNU General Public License version 2 or (at your
3 ! option) any later version. See the file COPYING for details.
4 
5 !> \file
6 !> The pmc_mosaic module.
7 
8 !> Interface to the MOSAIC aerosol and gas phase chemistry code.
9 module pmc_mosaic
10 
11  use pmc_aero_data
12  use pmc_aero_state
13  use pmc_constants
14  use pmc_env_state
15  use pmc_gas_data
16  use pmc_gas_state
17  use pmc_output
18  use pmc_util
19 
20 contains
21 
22 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23 
24  !> Whether MOSAIC support is compiled in.
25  logical function mosaic_support()
26 
27 #ifdef PMC_USE_MOSAIC
28  mosaic_support = .true.
29 #else
30  mosaic_support = .false.
31 #endif
32 
33  end function mosaic_support
34 
35 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
36 
37  !> Initialize all MOSAIC data-structures.
38  subroutine mosaic_init(env_state, aero_data, del_t, do_optical)
39 
40 #ifdef PMC_USE_MOSAIC
41  use module_data_mosaic_aero, only: alpha_astem, rtol_eqb_astem, &
42  ptol_mol_astem, mgas_aer_xfer, mdynamic_solver
43 
44  use module_data_mosaic_main, only: tbeg_sec, dt_sec, rlon, rlat, &
45  zalt_m, rh, te, pr_atm, cair_mlc, cair_molm3, ppb, avogad, &
46  mmode, mgas, maer, mcld, maeroptic, mshellcore, &
47  msolar, mphoto, lun_aeroptic, naerbin
48 #endif
49 
50  !> Environment state.
51  type(env_state_t), intent(inout) :: env_state
52  !> Aerosol data.
53  type(aero_data_t), intent(in) :: aero_data
54  !> Timestep for coagulation.
55  real(kind=dp), intent(in) :: del_t
56  !> Whether to compute optical properties.
57  logical, intent(in) :: do_optical
58 
59 #ifdef PMC_USE_MOSAIC
60  ! MOSAIC function interfaces
61  interface
62  subroutine loadperoxyparameters()
63  end subroutine loadperoxyparameters
64  subroutine init_data_modules()
65  end subroutine init_data_modules
66  subroutine allocatememory()
67  end subroutine allocatememory
68  end interface
69 
70  call init_data_modules ! initialize indices and vars
71 
72  ! allocate one aerosol bin
73  naerbin = 1
74  call allocatememory()
75 
76  ! parameters
77  mmode = 1 ! 1 = time integration, 2 = parametric analysis
78  mgas = 1 ! 1 = gas chem on, 0 = gas chem off
79  maer = 1 ! 1 = aer chem on, 0 = aer chem off
80  mcld = 0 ! 1 = cld chem on, 0 = cld chem off
81  if (do_optical) then
82  maeroptic = 1 ! 1 = aer_optical on, 0 = aer_optical off
83  else
84  maeroptic = 0
85  end if
86  mshellcore = 1 ! 0 = no shellcore, 1 = core is BC only
87  ! 2 = core is BC and DUST
88  msolar = 1 ! 1 = diurnally varying phot, 2 = fixed phot
89  mphoto = 2 ! 1 = Rick's param, 2 = Yang's param
90  mgas_aer_xfer = 1 ! 1 = gas-aerosol partitioning, 0 = no partition
91  mdynamic_solver = 1 ! 1 = astem, 2 = lsodes
92  alpha_astem = 0.5d0 ! solver parameter. range: 0.01 - 1.0
93  rtol_eqb_astem = 0.01d0 ! relative eqb tolerance. range: 0.01 - 0.03
94  ptol_mol_astem = 0.01d0 ! percent mol tolerance. range: 0.01 - 1.0
95 
96  ! time variables
97  dt_sec = del_t ! time-step (s)
98  tbeg_sec = env_state%start_day*24*3600 + & ! time since the beg of
99  nint(env_state%start_time) ! year 00:00, UTC (s)
100 
101  ! geographic location
102  rlon = deg2rad(env_state%longitude) ! longitude
103  rlat = deg2rad(env_state%latitude) ! latitude
104  zalt_m = env_state%altitude ! altitude (m)
105 
106  ! environmental parameters: map PartMC -> MOSAIC
107  rh = env_state%rel_humid * 100.d0 ! relative humidity (%)
108  te = env_state%temp ! temperature (K)
109  pr_atm = env_state%pressure / const%air_std_press ! pressure (atm)
110  cair_mlc = avogad*pr_atm/(82.056d0*te) ! air conc [molec/cc]
111  cair_molm3 = 1d6*pr_atm/(82.056d0*te) ! air conc [mol/m^3]
112  ppb = 1d9
113 
114  call loadperoxyparameters ! Aperox and Bperox only once
115 
116  ! get unit for aerosol optical output
117  if (lun_aeroptic <= 0 ) lun_aeroptic = get_unit()
118 
119  ! ensure H2O is a valid species
120  call assert_msg(111041803, aero_data%i_water > 0, &
121  "MOSAIC requires H2O as an aerosol species")
122 
123 #endif
124 
125  end subroutine mosaic_init
126 
127 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
128 
129  !> Clean-up after running MOSAIC, deallocating memory.
130  subroutine mosaic_cleanup()
131 
132 #ifdef PMC_USE_MOSAIC
133  ! MOSAIC function interfaces
134  interface
135  subroutine deallocatememory()
136  end subroutine deallocatememory
137  end interface
138 
139  call deallocatememory()
140 #endif
141 
142  end subroutine mosaic_cleanup
143 
144 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
145 
146  !> Map all data PartMC -> MOSAIC.
147  subroutine mosaic_from_partmc(env_state, aero_data, &
148  aero_state, gas_data, gas_state)
149 
150 #ifdef PMC_USE_MOSAIC
151  use module_data_mosaic_aero, only: nbin_a, aer, num_a, jhyst_leg, &
152 #ifdef pmc_use_wrf
153  particle_error, &
154 #endif
155  jtotal, water_a
156 
157  use module_data_mosaic_main, only: tbeg_sec, tcur_sec, tmid_sec, &
158  dt_sec, dt_min, dt_aeroptic_min, rh, te, pr_atm, cnn, cair_mlc, &
159  cair_molm3, ppb, avogad, msolar, naerbin
160 #endif
161 
162  !> Environment state.
163  type(env_state_t), intent(in) :: env_state
164  !> Aerosol data.
165  type(aero_data_t), intent(in) :: aero_data
166  !> Aerosol state.
167  type(aero_state_t), intent(in) :: aero_state
168  !> Gas data.
169  type(gas_data_t), intent(in) :: gas_data
170  !> Gas state.
171  type(gas_state_t), intent(in) :: gas_state
172 
173 #ifdef PMC_USE_MOSAIC
174  ! local variables
175  real(kind=dp) :: time_utc ! 24-hr UTC clock time (hr).
176  real(kind=dp) :: tmar21_sec ! Time at noon, march 21, UTC (s).
177  real(kind=dp) :: conv_fac(aero_data_n_spec(aero_data)), dum_var
178  integer :: i_part, i_spec, i_spec_mosaic
179  real(kind=dp) :: num_conc
180 
181  ! MOSAIC function interfaces
182  interface
183  subroutine allocatememory()
184  end subroutine allocatememory
185  subroutine deallocatememory()
186  end subroutine deallocatememory
187  end interface
188 
189  ! update time variables
190  tmar21_sec = real((79*24 + 12)*3600, kind=dp) ! noon, mar 21, UTC
191  tcur_sec = real(tbeg_sec, kind=dp) + env_state%elapsed_time
192  ! current (old) time since the beg of year 00:00, UTC (s)
193 
194  time_utc = env_state%start_time/3600d0 ! 24-hr UTC clock time (hr)
195  time_utc = time_utc + dt_sec/3600d0
196 
197  do while (time_utc >= 24d0)
198  time_utc = time_utc - 24d0
199  end do
200 
201  tmid_sec = tcur_sec + 0.5d0*dt_sec
202  if(tmid_sec .ge. tmar21_sec)then
203  tmid_sec = tmid_sec - tmar21_sec ! seconds since noon, march 21
204  else
205  tmid_sec = tmid_sec &
206  + dble(((365-79)*24 - 12)*3600) ! seconds since noon, march 21
207  endif
208 
209  ! transport timestep (min)
210  dt_min = dt_sec/60d0
211  ! aerosol optics timestep (min)
212  dt_aeroptic_min = 0d0
213 
214  ! compute aerosol conversion factors
215  do i_spec = 1,aero_data_n_spec(aero_data)
216  ! converts m^3(species) to nmol(species)/m^3(air)
217  conv_fac(i_spec) = 1.d9 * aero_data%density(i_spec) &
218  / aero_data%molec_weight(i_spec)
219  enddo
220 
221  ! environmental parameters: map PartMC -> MOSAIC
222  rh = env_state%rel_humid * 100.d0 ! relative humidity (%)
223  te = env_state%temp ! temperature (K)
224  pr_atm = env_state%pressure / const%air_std_press ! pressure (atm)
225  cair_mlc = avogad*pr_atm/(82.056d0*te) ! air conc [molec/cc]
226  cair_molm3 = 1d6*pr_atm/(82.056d0*te) ! air conc [mol/m^3]
227  ppb = 1d9
228 
229  ! aerosol data: map PartMC -> MOSAIC
230  nbin_a = aero_state_total_particles(aero_state)
231  if (nbin_a > naerbin) then
232  call deallocatememory()
233  naerbin = nbin_a
234  call allocatememory()
235  end if
236  aer = 0d0 ! initialize to zero
237  ! work backwards for consistency with mosaic_to_partmc(), which
238  ! has specific ordering requirements
239  do i_part = aero_state_n_part(aero_state),1,-1
240  num_conc = aero_weight_array_num_conc(aero_state%awa, &
241  aero_state%apa%particle(i_part), aero_data)
242  do i_spec = 1,aero_data_n_spec(aero_data)
243  i_spec_mosaic = aero_data%mosaic_index(i_spec)
244  if (i_spec_mosaic > 0) then
245  ! convert m^3(species) to nmol(species)/m^3(air)
246  aer(i_spec_mosaic, 3, i_part) & ! nmol/m^3(air)
247  = aero_state%apa%particle(i_part)%vol(i_spec) &
248  * conv_fac(i_spec) * num_conc
249  end if
250  end do
251  ! handle water specially
252  ! convert m^3(water) to kg(water)/m^3(air)
253  water_a(i_part) = &
254  aero_state%apa%particle(i_part)%vol(aero_data%i_water) &
255  * aero_data%density(aero_data%i_water) * num_conc
256  num_a(i_part) = 1d-6 * num_conc ! num conc (#/cc(air))
257  jhyst_leg(i_part) = aero_state%apa%particle(i_part)%water_hyst_leg
258  end do
259 
260  ! gas chemistry: map PartMC -> MOSAIC
261  cnn = 0d0
262  do i_spec = 1,gas_data_n_spec(gas_data)
263  i_spec_mosaic = gas_data%mosaic_index(i_spec)
264  if (i_spec_mosaic > 0) then
265  ! convert ppbv to molec/cc
266  cnn(i_spec_mosaic) = gas_state%mix_rat(i_spec) * cair_mlc / ppb
267  end if
268  end do
269 #ifdef PMC_USE_WRF
270  particle_error = .false.
271 #endif
272 #endif
273 
274  end subroutine mosaic_from_partmc
275 
276 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
277 
278  !> Map all data MOSAIC -> PartMC.
279  subroutine mosaic_to_partmc(env_state, aero_data, aero_state, gas_data, &
280  gas_state, uuid)
281 
282 #ifdef PMC_USE_MOSAIC
283  use module_data_mosaic_aero, only: nbin_a, aer, num_a, jhyst_leg, &
284 #ifdef pmc_use_wrf
285  particle_error, &
286 #endif
287  jtotal, water_a
288 
289  use module_data_mosaic_main, only: tbeg_sec, tcur_sec, tmid_sec, &
290  dt_sec, dt_min, dt_aeroptic_min, rh, te, pr_atm, cnn, cair_mlc, &
291  cair_molm3, ppb, avogad, msolar, cos_sza
292 #endif
293 
294  !> Environment state.
295  type(env_state_t), intent(inout) :: env_state
296  !> Aerosol data.
297  type(aero_data_t), intent(in) :: aero_data
298  !> Aerosol state.
299  type(aero_state_t), intent(inout) :: aero_state
300  !> Gas data.
301  type(gas_data_t), intent(in) :: gas_data
302  !> Gas state.
303  type(gas_state_t), intent(inout) :: gas_state
304  !> UUID for this simulation.
305  character(len=PMC_UUID_LEN), intent(in) :: uuid
306 
307 #ifdef PMC_USE_MOSAIC
308  ! local variables
309  real(kind=dp) :: conv_fac(aero_data_n_spec(aero_data)), dum_var, num_conc
310  integer :: i_part, i_spec, i_spec_mosaic
311  real(kind=dp), allocatable :: reweight_num_conc(:)
312 
313 #ifdef PMC_USE_WRF
314  if (any(particle_error) .eqv. .true.) then
315  call output_state('before_error', output_type_dist, aero_data, &
316  aero_state, gas_data, gas_state, env_state, &
317  int(env_state%elapsed_time / dt_sec), tcur_sec, dt_sec, 1, &
318  .false., .false., uuid)
319  end if
320 #endif
321 
322  ! compute aerosol conversion factors
323  do i_spec = 1,aero_data_n_spec(aero_data)
324  ! converts m^3(species) to nmol(species)/m^3(air)
325  conv_fac(i_spec) = 1d9 * aero_data%density(i_spec) &
326  / aero_data%molec_weight(i_spec)
327  enddo
328 
329  ! environmental parameters: map MOSAIC -> PartMC
330  env_state%rel_humid = rh / 100d0
331  env_state%temp = te
332  env_state%pressure = pr_atm * const%air_std_press
333  if (msolar == 1) then
334  env_state%solar_zenith_angle = acos(cos_sza)
335  end if
336  cair_mlc = avogad*pr_atm/(82.056d0*te) ! air conc [molec/cc]
337  cair_molm3 = 1d6*pr_atm/(82.056d0*te) ! air conc [mol/m^3]
338  ppb = 1d9
339 
340  ! gas chemistry: map MOSAIC -> PartMC
341  do i_spec = 1,gas_data_n_spec(gas_data)
342  i_spec_mosaic = gas_data%mosaic_index(i_spec)
343  if (i_spec_mosaic > 0) then
344  ! convert molec/cc to ppbv
345  gas_state%mix_rat(i_spec) = cnn(i_spec_mosaic) / cair_mlc * ppb
346  end if
347  end do
348 
349  ! We're modifying particle diameters, so the bin sort is now invalid
350  aero_state%valid_sort = .false.
351 
352  ! aerosol data: map MOSAIC -> PartMC
353  allocate(reweight_num_conc(aero_state_n_part(aero_state)))
354  call aero_state_num_conc_for_reweight(aero_state, aero_data, &
355  reweight_num_conc)
356  do i_part = 1,aero_state_n_part(aero_state),1
357  num_conc = aero_weight_array_num_conc(aero_state%awa, &
358  aero_state%apa%particle(i_part), aero_data)
359  do i_spec = 1,aero_data_n_spec(aero_data)
360  i_spec_mosaic = aero_data%mosaic_index(i_spec)
361  if (i_spec_mosaic > 0) then
362  aero_state%apa%particle(i_part)%vol(i_spec) = &
363  ! convert nmol(species)/m^3(air) to m^3(species)
364  aer(i_spec_mosaic, 3, i_part) / (conv_fac(i_spec) * num_conc)
365  end if
366  end do
367  aero_state%apa%particle(i_part)%water_hyst_leg = jhyst_leg(i_part)
368  ! handle water specially
369  ! convert kg(water)/m^3(air) to m^3(water)
370  aero_state%apa%particle(i_part)%vol(aero_data%i_water) = &
371  water_a(i_part) / aero_data%density(aero_data%i_water) / num_conc
372  end do
373 
374 #ifdef PMC_USE_WRF
375  if (any(particle_error) .eqv. .true.) then
376  call output_state('after_error', output_type_dist, aero_data, &
377  aero_state, gas_data, gas_state, env_state, &
378  int(env_state%elapsed_time / dt_sec), tcur_sec, dt_sec, 1,&
379  .false., .false., uuid)
380  do i_part = aero_state_n_part(aero_state),1,-1
381  if (particle_error(i_part)) then
382  ! Move last element to the current spot if it is removed.
383  if (i_part < aero_state_n_part(aero_state)) then
384  reweight_num_conc(i_part) = reweight_num_conc( &
385  aero_state_n_part(aero_state))
386  end if
387  call aero_state_remove_particle_no_info(aero_state, i_part)
388  end if
389  end do
390  ! Shrink the reweight_num_conc array to the number of particles
391  reweight_num_conc = reweight_num_conc(1:aero_state_n_part(aero_state))
392  end if
393 #endif
394 
395  ! adjust particles to account for weight changes
396  call aero_state_reweight(aero_state, aero_data, reweight_num_conc)
397 
398 #endif
399 
400  end subroutine mosaic_to_partmc
401 
402 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
403 
404  !> Do one timestep with MOSAIC.
405  !!
406  !! We currently also compute aerosol optical properties within this
407  !! subroutine. In principle this could be done at data analysis
408  !! time, rather than inside the timestepper. It's not clear if this
409  !! really matters, however. Because of this mosaic_aero_optical() is
410  !! currently disabled.
411  subroutine mosaic_timestep(env_state, aero_data, aero_state, gas_data, &
412  gas_state, do_optical, uuid)
413 
414 #ifdef PMC_USE_MOSAIC
415  use module_data_mosaic_main, only: msolar
416 #endif
417 
418  !> Environment state.
419  type(env_state_t), intent(inout) :: env_state
420  !> Aerosol data.
421  type(aero_data_t), intent(in) :: aero_data
422  !> Aerosol state.
423  type(aero_state_t), intent(inout) :: aero_state
424  !> Gas data.
425  type(gas_data_t), intent(in) :: gas_data
426  !> Gas state.
427  type(gas_state_t), intent(inout) :: gas_state
428  !> Whether to compute optical properties.
429  logical, intent(in) :: do_optical
430  !> UUID for this simulation.
431  character(len=PMC_UUID_LEN), intent(in) :: uuid
432 
433 #ifdef PMC_USE_MOSAIC
434  ! MOSAIC function interfaces
435  interface
436  subroutine solarzenithangle()
437  end subroutine solarzenithangle
438  subroutine integratechemistry()
439  end subroutine integratechemistry
440 #ifdef PMC_USE_MOSAIC_MULTI_OPT
441  subroutine aerosol_optical(i_wavelength)
442  integer, optional :: i_wavelength
443  end subroutine aerosol_optical
444 #else
445  subroutine aerosol_optical()
446  end subroutine aerosol_optical
447 #endif
448  end interface
449 
450  ! map PartMC -> MOSAIC
451  call mosaic_from_partmc(env_state, aero_data, aero_state, gas_data, &
452  gas_state)
453 
454  if (msolar == 1) then
455  call solarzenithangle
456  end if
457 
458  call integratechemistry
459 
460  ! map MOSAIC -> PartMC
461  if (do_optical) then
462  ! must do optical properties first, as mosaic_to_partmc() may
463  ! change the number of particles
464  call aerosol_optical
465  call mosaic_aero_optical(env_state, aero_data, &
466  aero_state, gas_data, gas_state)
467  end if
468 
469  call mosaic_to_partmc(env_state, aero_data, aero_state, gas_data, &
470  gas_state, uuid)
471 #endif
472 
473  end subroutine mosaic_timestep
474 
475 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
476 
477  !> Compute the optical properties of each aerosol particle.
478  !> FIXME: currently disabled.
479  !!
480  !! At the moment we are computing the aerosol optical properties
481  !! every timestep from withing mosaic_timestep. This decision should
482  !! be re-evaluated at some point in the future.
483  subroutine mosaic_aero_optical(env_state, aero_data, &
484  aero_state, gas_data, gas_state)
485 
486 #ifdef PMC_USE_MOSAIC
487  use module_data_mosaic_aero, only: ri_shell_a, ri_core_a, &
488  ext_cross, scat_cross, asym_particle, dp_core_a
489 #endif
490 
491  !> Environment state.
492  type(env_state_t), intent(in) :: env_state
493  !> Aerosol data.
494  type(aero_data_t), intent(in) :: aero_data
495  !> Aerosol state.
496  type(aero_state_t), intent(inout) :: aero_state
497  !> Gas data.
498  type(gas_data_t), intent(in) :: gas_data
499  !> Gas state.
500  type(gas_state_t), intent(in) :: gas_state
501 
502 #ifdef PMC_USE_MOSAIC
503  ! MOSAIC function interfaces
504  interface
505 #ifdef PMC_USE_MOSAIC_MULTI_OPT
506  subroutine aerosol_optical(i_wavelength)
507  integer, optional :: i_wavelength
508  end subroutine aerosol_optical
509 #else
510  subroutine aerosol_optical()
511  end subroutine aerosol_optical
512 #endif
513  end interface
514 
515  integer :: i_part
516 
517  ! map PartMC -> MOSAIC
518 ! call mosaic_from_partmc(env_state, aero_data, aero_state, &
519 ! gas_data, gas_state)
520 
521 ! call aerosol_optical
522 
523  ! map MOSAIC -> PartMC
524  ! work backwards for consistency with mosaic_to_partmc(), which
525  ! has specific ordering requirements
526  do i_part = aero_state_n_part(aero_state),1,-1
527 #ifdef PMC_USE_MOSAIC_MULTI_OPT
528  aero_state%apa%particle(i_part)%absorb_cross_sect = &
529  (ext_cross(i_part,:) - scat_cross(i_part,:)) / 1d4 ! (m^2)
530  aero_state%apa%particle(i_part)%scatter_cross_sect = &
531  scat_cross(i_part,:) / 1d4 ! (m^2)
532  aero_state%apa%particle(i_part)%asymmetry = &
533  asym_particle(i_part,:) ! (1)
534  aero_state%apa%particle(i_part)%refract_shell = &
535  cmplx(ri_shell_a(i_part,:), kind=dc) ! (1)
536  aero_state%apa%particle(i_part)%refract_core =&
537  cmplx(ri_core_a(i_part,:), kind=dc) ! (1)
538  aero_state%apa%particle(i_part)%core_vol = &
539  aero_data_diam2vol(aero_data, dp_core_a(i_part)) / 1d6 ! (m^3)
540 #else
541  aero_state%apa%particle(i_part)%absorb_cross_sect = (ext_cross(i_part) &
542  - scat_cross(i_part)) / 1d4 ! (m^2)
543  aero_state%apa%particle(i_part)%scatter_cross_sect = &
544  scat_cross(i_part) / 1d4 ! (m^2)
545  aero_state%apa%particle(i_part)%asymmetry = asym_particle(i_part) ! (1)
546  aero_state%apa%particle(i_part)%refract_shell = &
547  cmplx(ri_shell_a(i_part), kind=dc) ! (1)
548  aero_state%apa%particle(i_part)%refract_core =&
549  cmplx(ri_core_a(i_part), kind=dc) ! (1)
550  aero_state%apa%particle(i_part)%core_vol = &
551  aero_data_diam2vol(aero_data, dp_core_a(i_part)) / 1d6 ! (m^3)
552 #endif
553  end do
554 #endif
555 
556  end subroutine mosaic_aero_optical
557 
558 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
559 
560  !> Compute the optical properties of each aerosol particle for initial
561  !> timestep.
562  subroutine mosaic_aero_optical_init(env_state, aero_data, &
563  aero_state, gas_data, gas_state)
564 
565 #ifdef PMC_USE_MOSAIC
566  use module_data_mosaic_aero, only: ri_shell_a, ri_core_a, &
567  ext_cross, scat_cross, asym_particle, dp_core_a
568 #endif
569 
570  !> Environment state.
571  type(env_state_t), intent(in) :: env_state
572  !> Aerosol data.
573  type(aero_data_t), intent(in) :: aero_data
574  !> Aerosol state.
575  type(aero_state_t), intent(inout) :: aero_state
576  !> Gas data.
577  type(gas_data_t), intent(in) :: gas_data
578  !> Gas state.
579  type(gas_state_t), intent(in) :: gas_state
580 
581 #ifdef PMC_USE_MOSAIC
582  ! MOSAIC function interfaces
583  interface
584  subroutine load_mosaic_parameters()
585  end subroutine load_mosaic_parameters
586 #ifdef PMC_USE_MOSAIC_MULTI_OPT
587  subroutine aerosol_optical(i_wavelength)
588  integer, optional :: i_wavelength
589  end subroutine aerosol_optical
590 #else
591  subroutine aerosol_optical()
592  end subroutine aerosol_optical
593 #endif
594  end interface
595 
596  call load_mosaic_parameters
597 
598  ! map PartMC -> MOSAIC
599  call mosaic_from_partmc(env_state, aero_data, aero_state, &
600  gas_data, gas_state)
601 
602  call aerosol_optical
603 
604  call mosaic_aero_optical(env_state, aero_data, &
605  aero_state, gas_data, gas_state)
606 #endif
607 
608  end subroutine mosaic_aero_optical_init
609 
610 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
611 
612  !> Compute the optical properties of each aerosol particle for a single
613  !> wavelength selected by index when MOSAIC has multiple wavelengths enabled.
614  subroutine mosaic_aero_optical_single_wavelength(env_state, aero_data, &
615  aero_state, gas_data, gas_state, i_wavelength)
616 
617 #ifdef PMC_USE_MOSAIC
618  use module_data_mosaic_main, only: rh, pr_atm, te
619  use module_data_mosaic_aero, only: ri_shell_a, ri_core_a, &
620  ext_cross, scat_cross, asym_particle, dp_core_a, &
621  p_atm, rh_pc, ah2o, t_k
622 #endif
623 
624  !> Environment state.
625  type(env_state_t), intent(in) :: env_state
626  !> Aerosol data.
627  type(aero_data_t), intent(in) :: aero_data
628  !> Aerosol state.
629  type(aero_state_t), intent(inout) :: aero_state
630  !> Gas data.
631  type(gas_data_t), intent(in) :: gas_data
632  !> Gas state.
633  type(gas_state_t), intent(in) :: gas_state
634  !> Wavelength index to compute properties.
635  integer, intent(in) :: i_wavelength
636 
637 #ifdef PMC_USE_MOSAIC
638  ! MOSAIC function interfaces
639  interface
640 #ifdef PMC_USE_MOSAIC_MULTI_OPT
641  subroutine aerosol_optical(i_wavelength)
642  integer, optional :: i_wavelength
643  end subroutine aerosol_optical
644 #else
645  subroutine aerosol_optical()
646  end subroutine aerosol_optical
647 #endif
648  subroutine load_mosaic_parameters()
649  end subroutine load_mosaic_parameters
650  end interface
651 
652  integer :: i_part
653 
654  call load_mosaic_parameters
655 
656  ! map PartMC -> MOSAIC
657  call mosaic_from_partmc(env_state, aero_data, aero_state, &
658  gas_data, gas_state)
659 
660  rh_pc = rh ! RH(%)
661  ah2o = 0.01*rh_pc ! aH2O (aerosol water activity)
662  p_atm = pr_atm ! P(atm)
663  t_k = te ! T(K)
664 #ifdef PMC_USE_MOSAIC_MULTI_OPT
665  call aerosol_optical(i_wavelength)
666 #endif
667  call mosaic_aero_optical(env_state, aero_data, &
668  aero_state, gas_data, gas_state)
669 #endif
670 
672 
673 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
674 
675  !> Fetch the wavelengths that optical cross-sections are calculated at in
676  !> MOSAIC. If not using multiple wavelengths, the wavelength is the default
677  !> value of 550 nm.
678  subroutine mosaic_optical_wavelengths(aero_data)
679 
680 #ifdef PMC_USE_MOSAIC
681 #ifdef PMC_USE_MOSAIC_MULTI_OPT
682  use module_data_mosaic_aero, only: wavelength
683 #endif
684 #endif
685  type(aero_data_t), intent(inout) :: aero_data
686  integer :: i
687 
688  if(allocated(aero_data%wavelengths)) deallocate(aero_data%wavelengths)
689  allocate(aero_data%wavelengths(n_swbands))
690  aero_data%wavelengths = 0.0d0
691 #ifdef PMC_USE_MOSAIC_MULTI_OPT
692  do i = 1,n_swbands
693  aero_data%wavelengths(i) = wavelength(i) * 1d-9
694  end do
695 #else
696  aero_data%wavelengths = 550.0d0 * 1d-9
697 #endif
698 
699  end subroutine mosaic_optical_wavelengths
700 
701 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
702 
703 end module pmc_mosaic
pmc_aero_data::aero_data_n_spec
elemental integer function aero_data_n_spec(aero_data)
Return the number of aerosol species, or -1 if uninitialized.
Definition: aero_data.F90:246
pmc_gas_data::gas_data_t
Constant gas data.
Definition: gas_data.F90:35
pmc_aero_state::aero_state_n_part
elemental integer function aero_state_n_part(aero_state)
Return the current number of particles.
Definition: aero_state.F90:94
pmc_mosaic::mosaic_init
subroutine mosaic_init(env_state, aero_data, del_t, do_optical)
Initialize all MOSAIC data-structures.
Definition: mosaic.F90:39
pmc_util::get_unit
integer function get_unit()
Returns an available unit number. This should be freed by free_unit().
Definition: util.F90:149
pmc_aero_state::aero_state_num_conc_for_reweight
subroutine aero_state_num_conc_for_reweight(aero_state, aero_data, reweight_num_conc)
Save the correct number concentrations for later use by aero_state_reweight().
Definition: aero_state.F90:566
pmc_gas_data
The gas_data_t structure and associated subroutines.
Definition: gas_data.F90:9
pmc_constants::dp
integer, parameter dp
Kind of a double precision real number.
Definition: constants.F90:12
pmc_output::output_state
subroutine output_state(prefix, output_type, aero_data, aero_state, gas_data, gas_state, env_state, index, time, del_t, i_repeat, record_removals, record_optical, uuid)
Write the current state.
Definition: output.F90:112
pmc_env_state::env_state_t
Current environment state.
Definition: env_state.F90:29
pmc_aero_state
The aero_state_t structure and assocated subroutines.
Definition: aero_state.F90:9
pmc_mosaic
Interface to the MOSAIC aerosol and gas phase chemistry code.
Definition: mosaic.F90:9
pmc_aero_data::n_swbands
integer, parameter n_swbands
Definition: aero_data.F90:34
pmc_mosaic::mosaic_to_partmc
subroutine mosaic_to_partmc(env_state, aero_data, aero_state, gas_data, gas_state, uuid)
Map all data MOSAIC -> PartMC.
Definition: mosaic.F90:281
pmc_gas_state
The gas_state_t structure and associated subroutines.
Definition: gas_state.F90:9
pmc_util::assert_msg
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
Definition: util.F90:78
pmc_util::deg2rad
real(kind=dp) function deg2rad(deg)
Convert degrees to radians.
Definition: util.F90:1548
pmc_aero_state::aero_state_total_particles
integer function aero_state_total_particles(aero_state, i_group, i_class)
Returns the total number of particles in an aerosol distribution.
Definition: aero_state.F90:288
pmc_constants::const
type(const_t), save const
Fixed variable for accessing the constant's values.
Definition: constants.F90:75
pmc_aero_state::aero_state_reweight
subroutine aero_state_reweight(aero_state, aero_data, reweight_num_conc)
Reweight all particles after their constituent volumes have been altered.
Definition: aero_state.F90:598
pmc_mosaic::mosaic_aero_optical_single_wavelength
subroutine mosaic_aero_optical_single_wavelength(env_state, aero_data, aero_state, gas_data, gas_state, i_wavelength)
Compute the optical properties of each aerosol particle for a single wavelength selected by index whe...
Definition: mosaic.F90:616
pmc_mosaic::mosaic_cleanup
subroutine mosaic_cleanup()
Clean-up after running MOSAIC, deallocating memory.
Definition: mosaic.F90:131
pmc_mosaic::mosaic_optical_wavelengths
subroutine mosaic_optical_wavelengths(aero_data)
Fetch the wavelengths that optical cross-sections are calculated at in MOSAIC. If not using multiple ...
Definition: mosaic.F90:679
pmc_env_state
The env_state_t structure and associated subroutines.
Definition: env_state.F90:9
pmc_gas_state::gas_state_t
Current state of the gas mixing ratios in the system.
Definition: gas_state.F90:33
pmc_aero_state::aero_state_remove_particle_no_info
subroutine aero_state_remove_particle_no_info(aero_state, i_part)
Remove the given particle without recording it.
Definition: aero_state.F90:390
pmc_aero_data::aero_data_t
Aerosol material properties and associated data.
Definition: aero_data.F90:55
pmc_output
Write data in NetCDF format.
Definition: output.F90:68
pmc_constants
Physical constants.
Definition: constants.F90:9
pmc_util
Common utility subroutines.
Definition: util.F90:9
pmc_gas_data::gas_data_n_spec
elemental integer function gas_data_n_spec(gas_data)
Return the number of gas species.
Definition: gas_data.F90:109
pmc_constants::dc
integer, parameter dc
Kind of a double precision complex number.
Definition: constants.F90:14
pmc_mosaic::mosaic_aero_optical_init
subroutine mosaic_aero_optical_init(env_state, aero_data, aero_state, gas_data, gas_state)
Compute the optical properties of each aerosol particle for initial timestep.
Definition: mosaic.F90:564
pmc_mosaic::mosaic_timestep
subroutine mosaic_timestep(env_state, aero_data, aero_state, gas_data, gas_state, do_optical, uuid)
Do one timestep with MOSAIC.
Definition: mosaic.F90:413
pmc_aero_data
The aero_data_t structure and associated subroutines.
Definition: aero_data.F90:9
pmc_mosaic::mosaic_aero_optical
subroutine mosaic_aero_optical(env_state, aero_data, aero_state, gas_data, gas_state)
Compute the optical properties of each aerosol particle. FIXME: currently disabled.
Definition: mosaic.F90:485
pmc_aero_state::aero_state_t
The current collection of aerosol particles.
Definition: aero_state.F90:69
pmc_aero_data::aero_data_diam2vol
real(kind=dp) elemental function aero_data_diam2vol(aero_data, d)
Convert geometric diameter (m) to mass-equivalent volume (m^3).
Definition: aero_data.F90:147
pmc_mosaic::mosaic_support
logical function mosaic_support()
Whether MOSAIC support is compiled in.
Definition: mosaic.F90:26
pmc_mosaic::mosaic_from_partmc
subroutine mosaic_from_partmc(env_state, aero_data, aero_state, gas_data, gas_state)
Map all data PartMC -> MOSAIC.
Definition: mosaic.F90:149
pmc_output::output_type_dist
integer, parameter output_type_dist
Type code for distributed output (one file per process, written by each process).
Definition: output.F90:94