PartMC  2.8.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  !> Read an array of aero_dists with associated times and rates from
277  !> the given file.
278  subroutine spec_file_read_aero_dists_times_rates(file, aero_data, &
279  read_aero_weight_classes, times, rates, aero_dists)
280 
281  !> Spec file to read data from.
282  type(spec_file_t), intent(inout) :: file
283  !> Aero data.
284  type(aero_data_t), intent(inout) :: aero_data
285  !> Whether the weight classes for each source are specified in inputs.
286  logical, intent(in) :: read_aero_weight_classes
287  !> Times (s).
288  real(kind=dp), allocatable :: times(:)
289  !> Rates (s^{-1}).
290  real(kind=dp), allocatable :: rates(:)
291  !> Aero dists.
292  type(aero_dist_t), allocatable :: aero_dists(:)
293 
294  type(spec_line_t) :: aero_dist_line
295  type(spec_file_t) :: aero_dist_file
296  integer :: n_time, i_time
297  character(len=SPEC_LINE_MAX_VAR_LEN), allocatable :: names(:)
298  real(kind=dp), allocatable :: data(:,:)
299 
300  !> \page input_format_aero_dist_profile Input File Format: Aerosol Distribution Profile
301  !!
302  !! An aerosol distribution profile input file must consist of
303  !! three lines:
304  !! - the first line must begin with \c time and should be followed
305  !! by \f$N\f$ space-separated real scalars, giving the times (in
306  !! s after the start of the simulation) of the aerosol
307  !! distrbution set points --- the times must be in increasing
308  !! order
309  !! - the second line must begin with \c rate and should be
310  !! followed by \f$N\f$ space-separated real scalars, giving the
311  !! values at the corresponding times
312  !! - the third line must begin with \c dist and should be followed
313  !! by \f$N\f$ space-separated filenames, each specifying an
314  !! aerosol distribution in the format \ref input_format_aero_dist
315  !! at the corresponding time
316  !!
317  !! The units of the \c rate line depend on the type of aerosol
318  !! distribution profile:
319  !! - Emissions aerosol profiles have rates with units m/s ---
320  !! the aerosol distribution number concentrations are multiplied
321  !! by the rate to give an emission rate with unit #/(m^2 s)
322  !! which is then divided by the current mixing layer height
323  !! to give a per-volume emission rate.
324  !! - Background aerosol profiles have rates with units \f$\rm
325  !! s^{-1}\f$, which is the dilution rate between the background
326  !! and the simulated air parcel. That is, if the simulated
327  !! number concentration is \f$N\f$ and the background number
328  !! concentration is \f$N_{\rm back}\f$, then dilution is modeled
329  !! as \f$\dot{N} = r N_{\rm back} - r N\f$, where \f$r\f$ is the
330  !! rate.
331  !!
332  !! Between the specified times the aerosol profile is interpolated
333  !! step-wise and kept constant at its last value. That is, if the
334  !! times are \f$t_i\f$, the rates are \f$r_i\f$, and the aerosol
335  !! distributions are \f$a_i\f$ (all with \f$i = 1,\ldots,n\f$),
336  !! then between times \f$t_i\f$ and \f$t_{i+1}\f$ the aerosol
337  !! state is constant at \f$r_i a_i\f$. Before time \f$t_1\f$ the
338  !! aerosol state is \f$r_1 a_1\f$, while after time \f$t_n\f$ it
339  !! is \f$r_n a_n\f$.
340  !!
341  !! Example: an emissions aerosol profile could be:
342  !! <pre>
343  !! time 0 600 1800 # time (in s) after sim start
344  !! rate 1 0.5 1 # scaling factor in m/s
345  !! dist dist1.dat dist2.dat dist3.dat # aerosol distribution files
346  !! </pre>
347  !! Here the emissions between 0&nbsp;min and 10&nbsp;min are given
348  !! by <tt>dist1.dat</tt> (with the number concentration
349  !! interpreted as having units 1/(m^2 s)), the emissions between
350  !! 10&nbsp;min and 30&nbsp;min are given by <tt>dist2.dat</tt>
351  !! (scaled by 0.5), while the emissions after 30&nbsp;min are
352  !! given by <tt>dist3.dat</tt>.
353  !!
354  !! See also:
355  !! - \ref spec_file_format --- the input file text format
356  !! - \ref input_format_aero_data --- the aerosol species list
357  !! and material data
358  !! - \ref input_format_aero_dist --- the format of the
359  !! instantaneous aerosol distribution files
360 
361  ! read the data from the file
362  call spec_file_read_real_named_array(file, 2, names, data)
363  call spec_file_read_line_no_eof(file, aero_dist_line)
364  call spec_file_check_line_name(file, aero_dist_line, "dist")
365  call spec_file_check_line_length(file, aero_dist_line, size(data, 2))
366 
367  ! check the data size
368  if (size(names) /= 2) then
369  call die_msg(530745700, &
370  trim(file%name) // ' must contain exactly two data lines')
371  end if
372  if (trim(names(1)) /= 'time') then
373  call die_msg(570205795, 'row 1 in ' // trim(file%name) &
374  // ' must start with: time not: ' // trim(names(1)))
375  end if
376  if (trim(names(2)) /= 'rate') then
377  call die_msg(221270915, 'row 2 in ' // trim(file%name) &
378  // ' must start with: rate not: ' // trim(names(1)))
379  end if
380  n_time = size(data, 2)
381  if (n_time < 1) then
382  call die_msg(457229710, 'each line in ' // trim(file%name) &
383  // ' must contain at least one data value')
384  end if
385 
386  ! copy over the data
387  times = data(1,:)
388  rates = data(2,:)
389  if (allocated(aero_dists)) deallocate(aero_dists)
390  allocate(aero_dists(n_time))
391  do i_time = 1,n_time
392  call spec_file_open(aero_dist_line%data(i_time), aero_dist_file)
393  call spec_file_read_aero_dist(aero_dist_file, aero_data, &
394  read_aero_weight_classes, aero_dists(i_time))
395  call spec_file_close(aero_dist_file)
396  end do
397 
398  end subroutine spec_file_read_aero_dists_times_rates
399 
400 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
401 
402  !> Determines the number of bytes required to pack the given value.
403  integer function pmc_mpi_pack_size_aero_dist(val)
404 
405  !> Value to pack.
406  type(aero_dist_t), intent(in) :: val
407 
408  integer :: i, total_size
409 
410  if (allocated(val%mode)) then
412  do i = 1,size(val%mode)
413  total_size = total_size + pmc_mpi_pack_size_aero_mode(val%mode(i))
414  end do
415  else
416  total_size = pmc_mpi_pack_size_integer(-1)
417  end if
418  pmc_mpi_pack_size_aero_dist = total_size
419 
420  end function pmc_mpi_pack_size_aero_dist
421 
422 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
423 
424  !> Packs the given value into the buffer, advancing position.
425  subroutine pmc_mpi_pack_aero_dist(buffer, position, val)
426 
427  !> Memory buffer.
428  character, intent(inout) :: buffer(:)
429  !> Current buffer position.
430  integer, intent(inout) :: position
431  !> Value to pack.
432  type(aero_dist_t), intent(in) :: val
433 
434 #ifdef PMC_USE_MPI
435  integer :: prev_position, i
436 
437  prev_position = position
438  if (allocated(val%mode)) then
439  call pmc_mpi_pack_integer(buffer, position, aero_dist_n_mode(val))
440  do i = 1,size(val%mode)
441  call pmc_mpi_pack_aero_mode(buffer, position, val%mode(i))
442  end do
443  else
444  call pmc_mpi_pack_integer(buffer, position, -1)
445  end if
446  call assert(440557910, &
447  position - prev_position <= pmc_mpi_pack_size_aero_dist(val))
448 #endif
449 
450  end subroutine pmc_mpi_pack_aero_dist
451 
452 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
453 
454  !> Unpacks the given value from the buffer, advancing position.
455  subroutine pmc_mpi_unpack_aero_dist(buffer, position, val)
456 
457  !> Memory buffer.
458  character, intent(inout) :: buffer(:)
459  !> Current buffer position.
460  integer, intent(inout) :: position
461  !> Value to pack.
462  type(aero_dist_t), intent(inout) :: val
463 
464 #ifdef PMC_USE_MPI
465  integer :: prev_position, i, n
466 
467  prev_position = position
468  call pmc_mpi_unpack_integer(buffer, position, n)
469  if (allocated(val%mode)) deallocate(val%mode)
470  if (n >= 0) then
471  allocate(val%mode(n))
472  do i = 1,n
473  call pmc_mpi_unpack_aero_mode(buffer, position, val%mode(i))
474  end do
475  end if
476  call assert(742535268, &
477  position - prev_position <= pmc_mpi_pack_size_aero_dist(val))
478 #endif
479 
480  end subroutine pmc_mpi_unpack_aero_dist
481 
482 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
483 
484 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:246
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:426
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:456
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_mode::aero_mode_t
An aerosol size distribution mode.
Definition: aero_mode.F90:54
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:650
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:404
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_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