PartMC  2.9.0
aero_dist.F90
Go to the documentation of this file.
1 ! Copyright (C) 2005-2012 Nicole Riemer and 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_aero_dist module.
7 
8 !> The aero_dist_t structure and associated subroutines.
9 !!
10 !! The initial size distributions are computed as number densities, so
11 !! they can be used for both sectional and particle-resolved
12 !! simulations. The routine dist_to_n() converts a number concentration
13 !! distribution to an actual number of particles ready for a
14 !! particle-resolved simulation.
15 !!
16 !! Initial distributions should be normalized so that <tt>sum(n_den) =
17 !! 1/log_width</tt>.
19 
20  use pmc_bin_grid
21  use pmc_util
22  use pmc_constants
23  use pmc_spec_file
24  use pmc_aero_data
25  use pmc_aero_mode
26  use pmc_mpi
27  use pmc_rand
28 #ifdef PMC_USE_MPI
29  use mpi
30 #endif
31 
32  !> A complete aerosol distribution, consisting of several modes.
34  !> Internally mixed modes.
35  type(aero_mode_t), allocatable :: mode(:)
36  end type aero_dist_t
37 
38 contains
39 
40 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
41 
42  !> Return the number of modes.
43  elemental integer function aero_dist_n_mode(aero_dist)
44 
45  !> Aero data structure.
46  type(aero_dist_t), intent(in) :: aero_dist
47 
48  if (allocated(aero_dist%mode)) then
49  aero_dist_n_mode = size(aero_dist%mode)
50  else
52  end if
53 
54  end function aero_dist_n_mode
55 
56 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
57 
58  !> Returns the total number concentration of a distribution. (#/m^3)
59  real(kind=dp) function aero_dist_total_num_conc(aero_dist)
60 
61  !> Aerosol distribution.
62  type(aero_dist_t), intent(in) :: aero_dist
63 
64  integer :: i_mode
65 
67  do i_mode = 1,aero_dist_n_mode(aero_dist)
69  + aero_mode_total_num_conc(aero_dist%mode(i_mode))
70  end do
71 
72  end function aero_dist_total_num_conc
73 
74 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
75 
76  !> Returns the total number of particles of a distribution.
77  real(kind=dp) function aero_dist_number(aero_dist, aero_weight)
78 
79  !> Aerosol distribution.
80  type(aero_dist_t), intent(in) :: aero_dist
81  !> Aerosol weight.
82  type(aero_weight_t), intent(in) :: aero_weight
83 
84  integer :: i_mode
85 
86  aero_dist_number = 0d0
87  do i_mode = 1,aero_dist_n_mode(aero_dist)
89  + aero_mode_number(aero_dist%mode(i_mode), aero_weight)
90  end do
91 
92  end function aero_dist_number
93 
94 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
95 
96  !> Return the binned number concentration for an aero_dist.
97  subroutine aero_dist_num_conc(aero_dist, bin_grid, aero_data, &
98  num_conc)
99 
100  !> Aero dist for which to compute number concentration.
101  type(aero_dist_t), intent(in) :: aero_dist
102  !> Bin grid.
103  type(bin_grid_t), intent(in) :: bin_grid
104  !> Aerosol data.
105  type(aero_data_t), intent(in) :: aero_data
106  !> Number concentration (#(ln(r))d(ln(r))).
107  real(kind=dp), intent(out) :: num_conc(bin_grid_size(bin_grid))
108 
109  integer :: i_mode
110  real(kind=dp) :: mode_num_conc(size(num_conc, 1))
111 
112  num_conc = 0d0
113  do i_mode = 1,aero_dist_n_mode(aero_dist)
114  call aero_mode_num_conc(aero_dist%mode(i_mode), bin_grid, &
115  aero_data, mode_num_conc)
116  num_conc = num_conc + mode_num_conc
117  end do
118 
119  end subroutine aero_dist_num_conc
120 
121 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
122 
123  !> Return the binned per-species volume concentration for an
124  !> aero_dist.
125  subroutine aero_dist_vol_conc(aero_dist, bin_grid, aero_data, &
126  vol_conc)
127 
128  !> Aero dist for which to compute volume concentration.
129  type(aero_dist_t), intent(in) :: aero_dist
130  !> Bin grid.
131  type(bin_grid_t), intent(in) :: bin_grid
132  !> Aerosol data.
133  type(aero_data_t), intent(in) :: aero_data
134  !> Volume concentration (V(ln(r))d(ln(r))).
135  real(kind=dp), intent(out) :: vol_conc(bin_grid_size(bin_grid), &
136  aero_data_n_spec(aero_data))
137 
138  integer :: i_mode
139  real(kind=dp) :: mode_vol_conc(size(vol_conc, 1), size(vol_conc, 2))
140 
141  vol_conc = 0d0
142  do i_mode = 1,aero_dist_n_mode(aero_dist)
143  call aero_mode_vol_conc(aero_dist%mode(i_mode), bin_grid, &
144  aero_data, mode_vol_conc)
145  vol_conc = vol_conc + mode_vol_conc
146  end do
147 
148  end subroutine aero_dist_vol_conc
149 
150 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
151 
152  !> Whether any of the modes are of the given type.
153  elemental logical function aero_dist_contains_aero_mode_type(aero_dist, &
154  aero_mode_type)
155 
156  !> Aerosol distribution.
157  type(aero_dist_t), intent(in) :: aero_dist
158  !> Aerosol mode type to test for.
159  integer, intent(in) :: aero_mode_type
160 
161  integer :: i_mode
162 
164  do i_mode = 1,aero_dist_n_mode(aero_dist)
166  .or. (aero_dist%mode(i_mode)%type == aero_mode_type)
167  end do
168 
170 
171 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
172 
173  !> Determine the current aero_dist and rate by interpolating at the
174  !> current time with the lists of aero_dists and rates.
175  subroutine aero_dist_interp_1d(aero_dist_list, time_list, &
176  rate_list, time, aero_dist, rate)
177 
178  !> Gas states.
179  type(aero_dist_t), intent(in) :: aero_dist_list(:)
180  !> Times (s).
181  real(kind=dp), intent(in) :: time_list(size(aero_dist_list))
182  !> Rates (s^{-1}).
183  real(kind=dp), intent(in) :: rate_list(size(aero_dist_list))
184  !> Current time (s).
185  real(kind=dp), intent(in) :: time
186  !> Current gas state.
187  type(aero_dist_t), intent(inout) :: aero_dist
188  !> Current rate (s^{-1}).
189  real(kind=dp), intent(out) :: rate
190 
191  integer :: n, p, n_bin, n_spec, i, i_new
192  real(kind=dp) :: y, alpha
193 
194  n = size(aero_dist_list)
195  p = find_1d(n, time_list, time)
196  if (p == 0) then
197  ! before the start, just use the first state and rate
198  aero_dist = aero_dist_list(1)
199  rate = rate_list(1)
200  elseif (p == n) then
201  ! after the end, just use the last state and rate
202  aero_dist = aero_dist_list(n)
203  rate = rate_list(n)
204  else
205  ! in the middle, use the previous dist
206  aero_dist = aero_dist_list(p)
207  rate = rate_list(p)
208  end if
209 
210  end subroutine aero_dist_interp_1d
211 
212 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
213 
214  !> Read continuous aerosol distribution composed of several modes.
215  subroutine spec_file_read_aero_dist(file, aero_data, &
216  read_aero_weight_classes, aero_dist)
217 
218  !> Spec file to read data from.
219  type(spec_file_t), intent(inout) :: file
220  !> Aero_data data.
221  type(aero_data_t), intent(inout) :: aero_data
222  !> Whether the weight classes for each source are specified in inputs.
223  logical, intent(in) :: read_aero_weight_classes
224  !> Aerosol dist.
225  type(aero_dist_t), intent(inout) :: aero_dist
226 
227  type(aero_mode_t) :: aero_mode
228  type(aero_mode_t), allocatable :: new_modes(:)
229  integer :: n, i
230  logical :: eof
231 
232  ! note that the <p> is needed below to force correct paragraph
233  ! breaking by doxygen
234 
235  !> \page input_format_aero_dist Input File Format: Aerosol Distribution
236  !!
237  !! <p>An aerosol distribution file consists of zero or more modes,
238  !! each in the format described by \subpage input_format_aero_mode
239  !!
240  !! See also:
241  !! - \ref spec_file_format --- the input file text format
242  !! - \ref input_format_aero_mode --- the format for each mode
243  !! of an aerosol distribution
244 
245  allocate(aero_dist%mode(0))
246  call spec_file_read_aero_mode(file, aero_data, read_aero_weight_classes, &
247  aero_mode, eof)
248  do while (.not. eof)
249  n = size(aero_dist%mode)
250  allocate(new_modes(n + 1))
251  do i = 1,n
252  new_modes(i) = aero_dist%mode(i)
253  end do
254  new_modes(n + 1) = aero_mode
255  ! Next line is commented out due to a reported memory leak with valgrind
256  ! using both gcc 4.6.3 and 4.9.2.
257  !call move_alloc(new_modes, aero_dist%mode)
258  ! Next two lines are here to avoid issues with reallocation of lhs by
259  ! assignment.
260  deallocate(aero_dist%mode)
261  allocate(aero_dist%mode(n+1))
262  aero_dist%mode = new_modes
263  deallocate(new_modes)
264  ! Next line appears to work in gcc 4.9.2 but led to problems with older
265  ! versions of gcc (4.6.3). This will be ideal in the future as it avoids
266  ! the copying of the aero_dist%mode array each loop.
267  !aero_dist%mode = [aero_dist%mode, aero_mode]
268  call spec_file_read_aero_mode(file, aero_data, &
269  read_aero_weight_classes, aero_mode, eof)
270  end do
271 
272  end subroutine spec_file_read_aero_dist
273 
274 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
275 
276  !> Write distribution parameters for each mode in the aerosol distribution.
277  subroutine aero_dist_output_netcdf(aero_dist, ncid)
278 
279  !> Aerosol distribution to write.
280  type(aero_dist_t), intent(in) :: aero_dist
281  !> NetCDF file ID, in data mode.
282  integer, intent(in) :: ncid
283 
284  integer :: i_mode, n_mode
285  real(kind=dp), allocatable :: char_rads(:), log10_std_dev_rads(:), &
286  num_concs(:)
287 
288  n_mode = aero_dist_n_mode(aero_dist)
289 
290  allocate(char_rads(n_mode), log10_std_dev_rads(n_mode), num_concs(n_mode))
291 
292  do i_mode = 1,n_mode
293  char_rads(i_mode) = aero_dist%mode(i_mode)%char_radius
294  log10_std_dev_rads(i_mode) = aero_dist%mode(i_mode)%log10_std_dev_radius
295  num_concs(i_mode) = aero_dist%mode(i_mode)%num_conc
296  end do
297 
298  call pmc_nc_write_real_1d(ncid, char_rads, "char_rads_modes", &
299  dim_name="num_modes", &
300  long_name="characteristic radius of each mode", &
301  unit="m")
302  call pmc_nc_write_real_1d(ncid, log10_std_dev_rads, "std_dev_rads_modes", &
303  dim_name="num_modes", &
304  long_name="log of geom. std dev of each mode", &
305  unit="1")
306  call pmc_nc_write_real_1d(ncid, num_concs, "num_conc_modes", &
307  dim_name="num_modes", &
308  long_name="number concentration of each mode", &
309  unit="m^-3")
310  call pmc_nc_write_integer(ncid, aero_dist_n_mode(aero_dist), "n_mode", &
311  description="total number of modes")
312 
313  deallocate(char_rads, log10_std_dev_rads, num_concs)
314 
315  end subroutine aero_dist_output_netcdf
316 
317 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
318 
319  !> Read distribution parameters for each mode in the aerosol distribution.
320  subroutine aero_dist_input_netcdf(aero_dist, ncid)
321 
322  !> Aerosol distribution to read.
323  type(aero_dist_t), intent(inout) :: aero_dist
324  !> NetCDF file ID, in data mode
325  integer, intent(in) :: ncid
326 
327  integer :: i_mode, n_mode
328  type(aero_mode_t), allocatable :: modes(:)
329  real(kind=dp), allocatable :: char_rads(:), log10_std_dev_rads(:), &
330  num_concs(:)
331 
332  call pmc_nc_read_integer(ncid, n_mode, "n_mode")
333 
334  if (allocated(modes)) deallocate(modes)
335  allocate(modes(n_mode))
336 
337  allocate(char_rads(n_mode), log10_std_dev_rads(n_mode), num_concs(n_mode))
338 
339  call pmc_nc_read_real_1d(ncid, char_rads, "char_rads_modes")
340  call pmc_nc_read_real_1d(ncid, log10_std_dev_rads, "std_dev_rads_modes")
341  call pmc_nc_read_real_1d(ncid, num_concs, "num_conc_modes")
342 
343  do i_mode = 1, n_mode
344  modes(i_mode)%char_radius = char_rads(i_mode)
345  modes(i_mode)%log10_std_dev_radius = log10_std_dev_rads(i_mode)
346  modes(i_mode)%num_conc = num_concs(i_mode)
347  end do
348 
349  aero_dist%mode = modes
350 
351  deallocate(char_rads, log10_std_dev_rads, num_concs)
352 
353  end subroutine aero_dist_input_netcdf
354 
355 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
356 
357  !> Read an array of aero_dists with associated times and rates from
358  !> the given file.
359  subroutine spec_file_read_aero_dists_times_rates(file, aero_data, &
360  read_aero_weight_classes, times, rates, aero_dists)
361 
362  !> Spec file to read data from.
363  type(spec_file_t), intent(inout) :: file
364  !> Aero data.
365  type(aero_data_t), intent(inout) :: aero_data
366  !> Whether the weight classes for each source are specified in inputs.
367  logical, intent(in) :: read_aero_weight_classes
368  !> Times (s).
369  real(kind=dp), allocatable :: times(:)
370  !> Rates (s^{-1}).
371  real(kind=dp), allocatable :: rates(:)
372  !> Aero dists.
373  type(aero_dist_t), allocatable :: aero_dists(:)
374 
375  type(spec_line_t) :: aero_dist_line
376  type(spec_file_t) :: aero_dist_file
377  integer :: n_time, i_time
378  character(len=SPEC_LINE_MAX_VAR_LEN), allocatable :: names(:)
379  real(kind=dp), allocatable :: data(:,:)
380 
381  !> \page input_format_aero_dist_profile Input File Format: Aerosol Distribution Profile
382  !!
383  !! An aerosol distribution profile input file must consist of
384  !! three lines:
385  !! - the first line must begin with \c time and should be followed
386  !! by \f$N\f$ space-separated real scalars, giving the times (in
387  !! s after the start of the simulation) of the aerosol
388  !! distrbution set points --- the times must be in increasing
389  !! order
390  !! - the second line must begin with \c rate and should be
391  !! followed by \f$N\f$ space-separated real scalars, giving the
392  !! values at the corresponding times
393  !! - the third line must begin with \c dist and should be followed
394  !! by \f$N\f$ space-separated filenames, each specifying an
395  !! aerosol distribution in the format \ref input_format_aero_dist
396  !! at the corresponding time
397  !!
398  !! The units of the \c rate line depend on the type of aerosol
399  !! distribution profile:
400  !! - Emissions aerosol profiles have rates with units m/s ---
401  !! the aerosol distribution number concentrations are multiplied
402  !! by the rate to give an emission rate with unit #/(m^2 s)
403  !! which is then divided by the current mixing layer height
404  !! to give a per-volume emission rate.
405  !! - Background aerosol profiles have rates with units \f$\rm
406  !! s^{-1}\f$, which is the dilution rate between the background
407  !! and the simulated air parcel. That is, if the simulated
408  !! number concentration is \f$N\f$ and the background number
409  !! concentration is \f$N_{\rm back}\f$, then dilution is modeled
410  !! as \f$\dot{N} = r N_{\rm back} - r N\f$, where \f$r\f$ is the
411  !! rate.
412  !!
413  !! Between the specified times the aerosol profile is interpolated
414  !! step-wise and kept constant at its last value. That is, if the
415  !! times are \f$t_i\f$, the rates are \f$r_i\f$, and the aerosol
416  !! distributions are \f$a_i\f$ (all with \f$i = 1,\ldots,n\f$),
417  !! then between times \f$t_i\f$ and \f$t_{i+1}\f$ the aerosol
418  !! state is constant at \f$r_i a_i\f$. Before time \f$t_1\f$ the
419  !! aerosol state is \f$r_1 a_1\f$, while after time \f$t_n\f$ it
420  !! is \f$r_n a_n\f$.
421  !!
422  !! Example: an emissions aerosol profile could be:
423  !! <pre>
424  !! time 0 600 1800 # time (in s) after sim start
425  !! rate 1 0.5 1 # scaling factor in m/s
426  !! dist dist1.dat dist2.dat dist3.dat # aerosol distribution files
427  !! </pre>
428  !! Here the emissions between 0&nbsp;min and 10&nbsp;min are given
429  !! by <tt>dist1.dat</tt> (with the number concentration
430  !! interpreted as having units 1/(m^2 s)), the emissions between
431  !! 10&nbsp;min and 30&nbsp;min are given by <tt>dist2.dat</tt>
432  !! (scaled by 0.5), while the emissions after 30&nbsp;min are
433  !! given by <tt>dist3.dat</tt>.
434  !!
435  !! See also:
436  !! - \ref spec_file_format --- the input file text format
437  !! - \ref input_format_aero_data --- the aerosol species list
438  !! and material data
439  !! - \ref input_format_aero_dist --- the format of the
440  !! instantaneous aerosol distribution files
441 
442  ! read the data from the file
443  call spec_file_read_real_named_array(file, 2, names, data)
444  call spec_file_read_line_no_eof(file, aero_dist_line)
445  call spec_file_check_line_name(file, aero_dist_line, "dist")
446  call spec_file_check_line_length(file, aero_dist_line, size(data, 2))
447 
448  ! check the data size
449  if (size(names) /= 2) then
450  call die_msg(530745700, &
451  trim(file%name) // ' must contain exactly two data lines')
452  end if
453  if (trim(names(1)) /= 'time') then
454  call die_msg(570205795, 'row 1 in ' // trim(file%name) &
455  // ' must start with: time not: ' // trim(names(1)))
456  end if
457  if (trim(names(2)) /= 'rate') then
458  call die_msg(221270915, 'row 2 in ' // trim(file%name) &
459  // ' must start with: rate not: ' // trim(names(1)))
460  end if
461  n_time = size(data, 2)
462  if (n_time < 1) then
463  call die_msg(457229710, 'each line in ' // trim(file%name) &
464  // ' must contain at least one data value')
465  end if
466 
467  ! copy over the data
468  times = data(1,:)
469  rates = data(2,:)
470  if (allocated(aero_dists)) deallocate(aero_dists)
471  allocate(aero_dists(n_time))
472  do i_time = 1,n_time
473  call spec_file_open(aero_dist_line%data(i_time), aero_dist_file)
474  call spec_file_read_aero_dist(aero_dist_file, aero_data, &
475  read_aero_weight_classes, aero_dists(i_time))
476  call spec_file_close(aero_dist_file)
477  end do
478 
479  end subroutine spec_file_read_aero_dists_times_rates
480 
481 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
482 
483  !> Determines the number of bytes required to pack the given value.
484  integer function pmc_mpi_pack_size_aero_dist(val)
485 
486  !> Value to pack.
487  type(aero_dist_t), intent(in) :: val
488 
489  integer :: i, total_size
490 
491  if (allocated(val%mode)) then
493  do i = 1,size(val%mode)
494  total_size = total_size + pmc_mpi_pack_size_aero_mode(val%mode(i))
495  end do
496  else
497  total_size = pmc_mpi_pack_size_integer(-1)
498  end if
499  pmc_mpi_pack_size_aero_dist = total_size
500 
501  end function pmc_mpi_pack_size_aero_dist
502 
503 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
504 
505  !> Packs the given value into the buffer, advancing position.
506  subroutine pmc_mpi_pack_aero_dist(buffer, position, val)
507 
508  !> Memory buffer.
509  character, intent(inout) :: buffer(:)
510  !> Current buffer position.
511  integer, intent(inout) :: position
512  !> Value to pack.
513  type(aero_dist_t), intent(in) :: val
514 
515 #ifdef PMC_USE_MPI
516  integer :: prev_position, i
517 
518  prev_position = position
519  if (allocated(val%mode)) then
520  call pmc_mpi_pack_integer(buffer, position, aero_dist_n_mode(val))
521  do i = 1,size(val%mode)
522  call pmc_mpi_pack_aero_mode(buffer, position, val%mode(i))
523  end do
524  else
525  call pmc_mpi_pack_integer(buffer, position, -1)
526  end if
527  call assert(440557910, &
528  position - prev_position <= pmc_mpi_pack_size_aero_dist(val))
529 #endif
530 
531  end subroutine pmc_mpi_pack_aero_dist
532 
533 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
534 
535  !> Unpacks the given value from the buffer, advancing position.
536  subroutine pmc_mpi_unpack_aero_dist(buffer, position, val)
537 
538  !> Memory buffer.
539  character, intent(inout) :: buffer(:)
540  !> Current buffer position.
541  integer, intent(inout) :: position
542  !> Value to pack.
543  type(aero_dist_t), intent(inout) :: val
544 
545 #ifdef PMC_USE_MPI
546  integer :: prev_position, i, n
547 
548  prev_position = position
549  call pmc_mpi_unpack_integer(buffer, position, n)
550  if (allocated(val%mode)) deallocate(val%mode)
551  if (n >= 0) then
552  allocate(val%mode(n))
553  do i = 1,n
554  call pmc_mpi_unpack_aero_mode(buffer, position, val%mode(i))
555  end do
556  end if
557  call assert(742535268, &
558  position - prev_position <= pmc_mpi_pack_size_aero_dist(val))
559 #endif
560 
561  end subroutine pmc_mpi_unpack_aero_dist
562 
563 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
564 
565 end module pmc_aero_dist
pmc_aero_dist::aero_dist_n_mode
elemental integer function aero_dist_n_mode(aero_dist)
Return the number of modes.
Definition: aero_dist.F90:44
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:250
pmc_mpi
Wrapper functions for MPI.
Definition: mpi.F90:13
pmc_spec_file::spec_file_close
subroutine spec_file_close(file)
Close a spec file.
Definition: spec_file.F90:135
pmc_aero_dist::pmc_mpi_pack_aero_dist
subroutine pmc_mpi_pack_aero_dist(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: aero_dist.F90:507
pmc_util::die_msg
subroutine die_msg(code, error_msg)
Error immediately.
Definition: util.F90:135
pmc_constants::dp
integer, parameter dp
Kind of a double precision real number.
Definition: constants.F90:12
pmc_aero_dist::aero_dist_interp_1d
subroutine aero_dist_interp_1d(aero_dist_list, time_list, rate_list, time, aero_dist, rate)
Determine the current aero_dist and rate by interpolating at the current time with the lists of aero_...
Definition: aero_dist.F90:177
pmc_aero_mode::pmc_mpi_pack_size_aero_mode
integer function pmc_mpi_pack_size_aero_mode(val)
Determines the number of bytes required to pack the given value.
Definition: aero_mode.F90:1129
pmc_spec_file
Reading formatted text input.
Definition: spec_file.F90:43
pmc_bin_grid::bin_grid_size
elemental integer function bin_grid_size(bin_grid)
Return the number of bins in the grid, or -1 if the bin grid is not allocated.
Definition: bin_grid.F90:51
pmc_util::assert
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
Definition: util.F90:104
pmc_aero_dist::aero_dist_total_num_conc
real(kind=dp) function aero_dist_total_num_conc(aero_dist)
Returns the total number concentration of a distribution. (#/m^3)
Definition: aero_dist.F90:60
pmc_aero_mode::aero_mode_num_conc
subroutine aero_mode_num_conc(aero_mode, bin_grid, aero_data, num_conc)
Return the binned number concentration for an aero_mode.
Definition: aero_mode.F90:380
pmc_aero_mode::aero_mode_total_num_conc
real(kind=dp) function aero_mode_total_num_conc(aero_mode)
Returns the total number concentration of a mode. (#/m^3)
Definition: aero_mode.F90:110
pmc_spec_file::spec_file_t
An input file with extra data for printing messages.
Definition: spec_file.F90:59
pmc_aero_dist::aero_dist_number
real(kind=dp) function aero_dist_number(aero_dist, aero_weight)
Returns the total number of particles of a distribution.
Definition: aero_dist.F90:78
pmc_aero_dist::aero_dist_vol_conc
subroutine aero_dist_vol_conc(aero_dist, bin_grid, aero_data, vol_conc)
Return the binned per-species volume concentration for an aero_dist.
Definition: aero_dist.F90:127
pmc_aero_dist::pmc_mpi_unpack_aero_dist
subroutine pmc_mpi_unpack_aero_dist(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: aero_dist.F90:537
pmc_aero_dist
The aero_dist_t structure and associated subroutines.
Definition: aero_dist.F90:18
pmc_spec_file::spec_file_check_line_length
subroutine spec_file_check_line_length(file, line, length)
Check that the length of the line data is as given.
Definition: spec_file.F90:432
pmc_aero_dist::aero_dist_output_netcdf
subroutine aero_dist_output_netcdf(aero_dist, ncid)
Write distribution parameters for each mode in the aerosol distribution.
Definition: aero_dist.F90:278
pmc_aero_mode::aero_mode_t
An aerosol size distribution mode.
Definition: aero_mode.F90:54
ncid
integer, intent(in) ncid
Definition: fractal.F90:616
pmc_aero_mode::pmc_mpi_unpack_aero_mode
subroutine pmc_mpi_unpack_aero_mode(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: aero_mode.F90:1185
pmc_spec_file::spec_file_open
subroutine spec_file_open(filename, file)
Open a spec file for reading.
Definition: spec_file.F90:112
pmc_spec_file::spec_file_read_line_no_eof
subroutine spec_file_read_line_no_eof(file, line)
Read a spec_line from the spec_file. This will always succeed or error out, so should only be called ...
Definition: spec_file.F90:298
pmc_rand
Random number generators.
Definition: rand.F90:9
pmc_spec_file::spec_file_read_real_named_array
subroutine spec_file_read_real_named_array(file, max_lines, names, vals)
Read an array of named lines with real data. All lines must have the same number of data elements.
Definition: spec_file.F90:669
pmc_aero_data::aero_data_t
Aerosol material properties and associated data.
Definition: aero_data.F90:55
pmc_mpi::pmc_mpi_unpack_integer
subroutine pmc_mpi_unpack_integer(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: mpi.F90:1139
pmc_constants
Physical constants.
Definition: constants.F90:9
pmc_aero_dist::aero_dist_t
A complete aerosol distribution, consisting of several modes.
Definition: aero_dist.F90:33
pmc_aero_mode::pmc_mpi_pack_aero_mode
subroutine pmc_mpi_pack_aero_mode(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: aero_mode.F90:1152
pmc_util
Common utility subroutines.
Definition: util.F90:9
pmc_aero_mode::aero_mode_number
real(kind=dp) function aero_mode_number(aero_mode, aero_weight)
Return the total number of computational particles for an aero_mode.
Definition: aero_mode.F90:497
pmc_aero_mode
The aero_mode_t structure and associated subroutines.
Definition: aero_mode.F90:9
pmc_aero_dist::pmc_mpi_pack_size_aero_dist
integer function pmc_mpi_pack_size_aero_dist(val)
Determines the number of bytes required to pack the given value.
Definition: aero_dist.F90:485
pmc_mpi::pmc_mpi_pack_size_integer
integer function pmc_mpi_pack_size_integer(val)
Determines the number of bytes required to pack the given value.
Definition: mpi.F90:345
pmc_bin_grid
The bin_grid_t structure and associated subroutines.
Definition: bin_grid.F90:9
pmc_mpi::pmc_mpi_pack_integer
subroutine pmc_mpi_pack_integer(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: mpi.F90:711
pmc_aero_data
The aero_data_t structure and associated subroutines.
Definition: aero_data.F90:9
pmc_spec_file::spec_file_check_line_name
subroutine spec_file_check_line_name(file, line, name)
Check that the name of the line data is as given.
Definition: spec_file.F90:390
pmc_bin_grid::bin_grid_t
1D grid, either logarithmic or linear.
Definition: bin_grid.F90:33
pmc_aero_dist::aero_dist_num_conc
subroutine aero_dist_num_conc(aero_dist, bin_grid, aero_data, num_conc)
Return the binned number concentration for an aero_dist.
Definition: aero_dist.F90:99
pmc_aero_dist::aero_dist_contains_aero_mode_type
elemental logical function aero_dist_contains_aero_mode_type(aero_dist, aero_mode_type)
Whether any of the modes are of the given type.
Definition: aero_dist.F90:155
pmc_util::find_1d
integer function find_1d(n, x_vals, x)
Find the position of a real number in an arbitrary 1D array.
Definition: util.F90:593
pmc_aero_dist::aero_dist_input_netcdf
subroutine aero_dist_input_netcdf(aero_dist, ncid)
Read distribution parameters for each mode in the aerosol distribution.
Definition: aero_dist.F90:321
pmc_aero_mode::aero_mode_vol_conc
subroutine aero_mode_vol_conc(aero_mode, bin_grid, aero_data, vol_conc)
Return the binned per-species volume concentration for an aero_mode.
Definition: aero_mode.F90:415