PartMC  2.6.1
fractal.F90
Go to the documentation of this file.
1 ! Copyright (C) 2011-2012, 2016 Jian Tian, 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_fractal module.
7 
8 !> The fractal_t structure and associated subroutines.
9 !!
10 !! This module includes all the conversions of different radii and
11 !! diameters to volume (and vice versa), such as geometric radius/diameter,
12 !! mobility equivalent radius/diameter, etc. Here volume means the
13 !! particle mass-equivalent volume (referred to "vol" in code).
14 !! The mass-equivalent volume is the sum of the per-species volumes, which are
15 !! in turn the per-species masses divided by the per-species
16 !! densities in aero_data. Geometric radius
17 !! (referred to "rad" in code) is defined as the radius of the closest
18 !! convex envelop. This quantity provides the information about the
19 !! collisional cross section which is required to calculate coagulation rates.
20 !! Mobility equivalent radius (referred to "mobility_rad" in code)
21 !! will be the same as geometric radius for spherical particles, but
22 !! different for fractal particles. This is due to hydrodynamic interactions
23 !! between the primary particles, which result in a decrease of the frictional
24 !! forces acting upon the particles accompanied by an increase of the
25 !! translational diffusion coefficient. Mobility equivalent radius is often
26 !! used as output from experimental data such as SMPS measurements. We also
27 !! use "mobility_rad_in_continuum" for the mobility equivalent radius in
28 !! continuum regime.
29 !!
30 !! All equations used in this file are obtained from
31 !! K. -H. Naumann (2003) COSIMA - a computer program simulating
32 !! the dynamics of fractal aerosols, <i>Journal of Aerosol Science</i>,
33 !! 34(10), 1371-1397. The equations are written in detail in the file
34 !! \c doc/fractal/fractal.tex.
36 
37  use pmc_spec_file
38  use pmc_constants
39  use pmc_netcdf
40  use pmc_mpi
41 
42  !> Constant \f$A\f$ in slip correction equation in Eq. 22 of Naumann [2003].
43  real(kind=dp), parameter :: fractal_a_slip = 1.142d0
44  !> Constant \f$Q\f$ in slip correction equation in Eq. 22 of Naumann [2003].
45  real(kind=dp), parameter :: fractal_q_slip = 0.588d0
46  !> Constant \f$b\f$ in slip correction equation in Eq. 22 of Naumann [2003].
47  real(kind=dp), parameter :: fractal_b_slip = 0.999d0
48  !> Scaling factor \f$z\f$ in calculating accessible particle surface area
49  !> in Eq. 26 of Naumann [2003].
50  real(kind=dp), parameter :: fractal_scale_factor_s_acc = 1d0
51  !> Scaling exponent \f$\gamma\f$ in calculating accessible particle surface
52  !> area in Eq. 26 of Naumann [2003].
53  real(kind=dp), parameter :: fractal_scale_exponent_s_acc = 0.86d0
54 
55  !> Fractal data.
56  !!
57  !! The data in this structure is constant, as it represents physical
58  !! quantities that cannot change over time.
59  type fractal_t
60  !> Volume fractal dimension \f$d_{\rm f}\f$ (1).
61  real(kind=dp) :: frac_dim
62  !> Radius of primary particles \f$R_{\rm 0}\f$ (m).
63  real(kind=dp) :: prime_radius
64  !> Volume filling factor \f$f\f$ (1).
65  real(kind=dp) :: vol_fill_factor
66  end type fractal_t
67 
68 contains
69 
70 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
71 
72  !> Set fractal parameters for spherical particles.
73  subroutine fractal_set_spherical(fractal)
74 
75  !> Fractal parameters.
76  type(fractal_t), intent(out) :: fractal
77 
78  fractal%frac_dim = 3d0
79  fractal%prime_radius = 1d-8
80  fractal%vol_fill_factor = 1d0
81 
82  end subroutine fractal_set_spherical
83 
84 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
85 
86  !> Convert mass-equivalent volume \f$V\f$ (m^3) to number of
87  !> monomers \f$N\f$ in a fractal particle cluster.
88  !!
89  !! Based on Eq. 5 in Naumann [2003].
90  real(kind=dp) elemental function fractal_vol_to_num_of_monomers(fractal, v)
91 
92  !> Fractal parameters.
93  type(fractal_t), intent(in) :: fractal
94  !> Particle mass-equivalent volume (m^3).
95  real(kind=dp), intent(in) :: v
96 
98  / fractal%prime_radius)**3
99 
100  end function fractal_vol_to_num_of_monomers
101 
102 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
103 
104  !> Convert mass-equivalent volume \f$V\f$ (m^3) to geometric radius
105  !> \f$R_{\rm geo}\f$ (m).
106  real(kind=dp) elemental function fractal_vol2rad(fractal, v)
107 
108  !> Fractal parameters.
109  type(fractal_t), intent(in) :: fractal
110  !> Particle mass-equivalent volume (m^3).
111  real(kind=dp), intent(in) :: v
112 
113  if (fractal_is_spherical(fractal)) then
115  else
116  fractal_vol2rad = fractal%prime_radius &
118  * fractal%vol_fill_factor)**(1d0 / fractal%frac_dim)
119  end if
120 
121  end function fractal_vol2rad
122 
123 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
124 
125  !> Convert mass-equivalent volume \f$V\f$ (m^3) to geometric diameter
126  !> \f$D_{\rm geo}\f$ (m).
127  real(kind=dp) elemental function fractal_vol2diam(fractal, v)
128 
129  !> Fractal parameters.
130  type(fractal_t), intent(in) :: fractal
131  !> Particle mass-equivalent volume (m^3).
132  real(kind=dp), intent(in) :: v
133 
135 
136  end function fractal_vol2diam
137 
138 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
139 
140  !> Convert geometric radius \f$R_{\rm geo}\f$ (m) to mass-equivalent volume
141  !> \f$V\f$ (m^3).
142  real(kind=dp) elemental function fractal_rad2vol(fractal, r)
143 
144  !> Fractal parameters.
145  type(fractal_t), intent(in) :: fractal
146  !> Geometric radius (m).
147  real(kind=dp), intent(in) :: r
148 
149  if (fractal_is_spherical(fractal)) then
151  else
152  fractal_rad2vol = sphere_rad2vol(fractal%prime_radius) &
153  * (r / fractal%prime_radius)**fractal%frac_dim &
154  / fractal%vol_fill_factor
155  end if
156 
157  end function fractal_rad2vol
158 
159 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
160 
161  !> Convert geometric diameter \f$D_{\rm geo}\f$ (m) to
162  !> mass-equivalent volume \f$V\f$ (m^3).
163  real(kind=dp) elemental function fractal_diam2vol(fractal, d)
164 
165  !> Fractal parameters.
166  type(fractal_t), intent(in) :: fractal
167  !> Geometric diameter (m).
168  real(kind=dp), intent(in) :: d
169 
171 
172  end function fractal_diam2vol
173 
174 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
175 
176  !> Compute surface fractal dimension \f$d_{\rm s}\f$.
177  real(kind=dp) function fractal_surface_frac_dim(fractal)
178 
179  !> Fractal parameters.
180  type(fractal_t), intent(in) :: fractal
181 
182  fractal_surface_frac_dim = 0d0 ! prevent uninitialized warnings
183  if (fractal%frac_dim <= 2d0) then
185  elseif ((fractal%frac_dim > 2d0) .and. (fractal%frac_dim <= 3d0)) then
186  fractal_surface_frac_dim = 6d0 / fractal%frac_dim
187  else
188  call die_msg(110248362, 'volume fractal dimension larger than 3')
189  end if
190 
191  end function fractal_surface_frac_dim
192 
193 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
194 
195  !> Convert mass-equivalent volume \f$V\f$ (m^3) to accessible
196  !> particle surface area \f$S_{\rm acc}\f$ (m^2).
197  !!
198  !! Based on Eq. 26 in Naumann [2003].
199  real(kind=dp) function fractal_vol_to_accessible_surface(fractal, v)
200 
201  !> Fractal parameters.
202  type(fractal_t), intent(in) :: fractal
203  !> Particle mass-equivalent volume (m^3)
204  real(kind=dp), intent(in) :: v
205 
206  real(kind=dp) :: ds, n
207 
210 
212  * fractal%prime_radius**2 * n**(ds / 3d0) * ((ds - 2d0) &
214  **(1d0 - fractal_scale_exponent_s_acc) - ds + 3d0)
215 
217 
218 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
219 
220  !> Kirkwood-Riseman ratio \f$h_{\rm KR}\f$.
221  !!
222  !! Based on Eq. 21 in Naumann [2003].
223  real(kind=dp) function fractal_kirkwood_riseman(fractal)
224 
225  !> Fractal parameters.
226  type(fractal_t), intent(in) :: fractal
227 
228  fractal_kirkwood_riseman = -0.06483d0 * fractal%frac_dim**2 &
229  + 0.6353d0 * fractal%frac_dim - 0.4898d0
230 
231  end function fractal_kirkwood_riseman
232 
233 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
234 
235  !> Convert mass-equivalent volume \f$V\f$ (m^3) to continuum regime
236  !> mobility equivalent radius \f$R_{\rm me,c}\f$ (m).
237  !!
238  !! Based on Eq. 21 in Naumann [2003].
239  real(kind=dp) function fractal_vol_to_mobility_rad_in_continuum(fractal, v)
240 
241  !> Fractal parameters.
242  type(fractal_t), intent(in) :: fractal
243  !> Particle mass-equivalent volume (m^3).
244  real(kind=dp), intent(in) :: v
245 
248 
250 
251 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
252 
253  !> Convert mass-equivalent volume \f$V\f$ (m^3) to particle effective
254  !> radius \f$R_{\rm eff}\f$ (m).
255  !!
256  !! Based on Eq. 28 in Naumann [2003].
257  real(kind=dp) function fractal_vol_to_effective_rad(fractal, v)
258 
259  !> Fractal parameters.
260  type(fractal_t), intent(in) :: fractal
261  !> Particle mass-equivalent volume (m^3).
262  real(kind=dp), intent(in) :: v
263 
267 
268  end function fractal_vol_to_effective_rad
269 
270 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
271 
272  !> Slip correction function \f$C(R_eff)\f$ from continuum to
273  !> free molecular regime.
274  !!
275  !! Based on Eq. 22 in Naumann [2003].
276  real(kind=dp) function fractal_slip_correct(R_eff, temp, pressure)
277 
278  !> Effective radius (m).
279  real(kind=dp), intent(in) :: r_eff
280  !> Temperature (K).
281  real(kind=dp), intent(in) :: temp
282  !> Pressure (Pa).
283  real(kind=dp), intent(in) :: pressure
284 
285  real(kind=dp) :: fp
286 
287  fp = air_mean_free_path(temp, pressure)
288  fractal_slip_correct = 1d0 + fractal_a_slip * fp / r_eff &
289  + fractal_q_slip * fp / r_eff * exp(-fractal_b_slip * r_eff / fp)
290 
291  end function fractal_slip_correct
292 
293 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
294 
295  !> Test whether a particle is spherical.
296  elemental logical function fractal_is_spherical(fractal)
297 
298  !> Fractal parameters.
299  type(fractal_t), intent(in) :: fractal
300 
301  if (fractal%frac_dim == 3d0 .and. fractal%vol_fill_factor == 1d0) then
302  fractal_is_spherical = .true.
303  else
304  fractal_is_spherical = .false.
305  end if
306 
307  end function fractal_is_spherical
308 
309 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
310 
311  !> Convert mass-equivalent volume \f$V\f$ (m^3) to mobility equivalent
312  !> radius \f$R_{\rm me}\f$ (m).
313  !!
314  !! Based on Eq. 5, 21 and 30 in Naumann [2003].
315  real(kind=dp) function fractal_vol_to_mobility_rad(fractal, v, &
316  temp, pressure)
317 
318  !> Fractal parameters.
319  type(fractal_t), intent(in) :: fractal
320  !> Particle mass-equivalent volume (m^3).
321  real(kind=dp), intent(in) :: v
322  !> Temperature (K).
323  real(kind=dp), intent(in) :: temp
324  !> Pressure (Pa).
325  real(kind=dp), intent(in) :: pressure
326 
327  real(kind=dp), parameter :: newton_rel_tol = 1d-14
328  integer, parameter :: newton_max_steps = 10
329 
330  real(kind=dp) :: x
331  real(kind=dp) :: rmec, reff, c_reff, fp, f, df
332  real(kind=dp) :: a1, a2, a3, a4, a5
333  integer ::newton_step
334 
335  if (fractal_is_spherical(fractal)) then
337  return
338  end if
339 
342  c_reff = fractal_slip_correct(reff, temp, pressure)
343  fp = air_mean_free_path(temp, pressure)
344  a1 = c_reff
345  a2 = -rmec
346  a3 = -rmec * fractal_q_slip * fp
347  a4 = -fractal_b_slip / fp
348  a5 = -rmec * fractal_a_slip * fp
349 
350  x = rmec
351  do newton_step = 1,newton_max_steps
352  f = a1 * x**2 + a2 * x + a3 * exp(a4 * x) + a5
353  df = 2d0 * a1 * x + a2 + a3 * a4 * exp(a4 * x)
354  x = x - f / df
355  if (abs(f / df) / (abs(x + f / df) + abs(x)) &
356  < newton_rel_tol) exit
357  end do
358  call assert_msg(728724732, newton_step < newton_max_steps, &
359  "fractal Newton loop failed to converge")
361 
362  end function fractal_vol_to_mobility_rad
363 
364 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
365 
366  !> Convert mobility equivalent radius \f$R_{\rm me}\f$ (m) to that in the
367  !> continuum regime \f$R_{\rm me,c}\f$ (m).
368  !!
369  !! Based on Eq. 30 in Naumann [2003].
371  fractal, mobility_rad, temp, pressure)
372 
373  !> Fractal parameters.
374  type(fractal_t), intent(in) :: fractal
375  !> Mobility equivalent radius (m).
376  real(kind=dp), intent(in) :: mobility_rad
377  !> Temperature (K).
378  real(kind=dp), intent(in) :: temp
379  !> Pressure (Pa).
380  real(kind=dp), intent(in) :: pressure
381 
382  real(kind=dp), parameter :: newton_rel_tol = 1d-14
383  integer, parameter :: newton_max_steps = 10
384 
385  real(kind=dp) :: x
386  real(kind=dp) :: c_rme, fp, phi, ds, psi, c1, c2, f, df
387  real(kind=dp) :: a1, a2, a3, a4, a5, a6, a7, a8
388  integer :: newton_step
389 
390  c_rme = fractal_slip_correct(mobility_rad, temp, pressure)
391  fp = air_mean_free_path(temp, pressure)
393  phi = fractal%prime_radius**2 / (fractal%vol_fill_factor &
395  * fractal%prime_radius**fractal%frac_dim)**(ds / 3d0)
396  psi = 1d0 / (fractal%vol_fill_factor &
398  * fractal%prime_radius**fractal%frac_dim)&
400  c1 = fractal%frac_dim * ds / 3d0 + (fractal_scale_exponent_s_acc - 1d0) &
401  * fractal%frac_dim - 1d0
402  c2 = fractal%frac_dim * ds / 3d0 - 1d0
403  a1 = c_rme / mobility_rad * phi * psi * (ds - 2d0)
404  a2 = c_rme / mobility_rad * phi * (3d0 - ds)
405  a3 = -phi * psi * (ds - 2d0)
406  a4 = phi * (ds - 3d0)
407  a5 = -fractal_q_slip * fp
408  a6 = -fractal_b_slip / fp * phi * psi * (ds - 2d0)
409  a7 = -fractal_b_slip / fp * phi * (3d0 - ds)
410  a8 = -fractal_a_slip * fp
411 
412  x = mobility_rad
413  do newton_step = 1,newton_max_steps
414  f = a1 * x**(c1 + 1d0) + a2 * x**(c2 + 1d0) + a3 * x**c1 &
415  + a4 * x**c2 + a5 * exp(a6 * x**c1 + a7 * x**c2) + a8
416  df = a1 * (c1 + 1d0) * x**c1 + a2 * (c2 + 1d0) * x**c2 &
417  + a3 * c1 * x**(c1 - 1d0) + a4 * c2 * x**(c2 - 1d0) &
418  + a5 * (a6 * c1 * x**(c1 - 1d0) + a7 * c2 * x**(c2 - 1d0)) &
419  * exp(a6 * x**c1 + a7 * x**c2)
420  x = x - f / df
421  if (abs(f / df) / (abs(x + f / df) + abs(x)) &
422  < newton_rel_tol) exit
423  end do
424  call assert_msg(875871349, newton_step < newton_max_steps, &
425  "fractal Newton loop failed to converge")
427 
429 
430 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
431 
432  !> Convert mobility equivalent radius \f$R_{\rm me}\f$ (m) to
433  !> geometric radius \f$R_{\rm geo}\f$ (m^3).
434  real(kind=dp) function fractal_mobility_rad_to_geometric_rad(fractal, &
435  mobility_rad, temp, pressure)
436 
437  !> Fractal parameters.
438  type(fractal_t), intent(in) :: fractal
439  !> Mobility equivalent radius (m).
440  real(kind=dp), intent(in) :: mobility_rad
441  !> Temperature (K).
442  real(kind=dp), intent(in) :: temp
443  !> Pressure (Pa).
444  real(kind=dp), intent(in) :: pressure
445 
446  real(kind=dp) :: rmec
447 
448  if (fractal_is_spherical(fractal)) then
450  return
451  end if
452 
454  mobility_rad, temp, pressure)
457 
459 
460 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
461 
462  !> Convert mobility equivalent radius \f$R_{\rm me}\f$ (m) to
463  !> mass-equivalent volume \f$V\f$ (m^3).
464  !!
465  !! Based on Eq. 5, 21 and 30 in Naumann [2003].
466  real(kind=dp) function fractal_mobility_rad_to_vol(fractal, mobility_rad, &
467  temp, pressure)
468 
469  !> Fractal parameters.
470  type(fractal_t), intent(in) :: fractal
471  !> Mobility equivalent radius (m).
472  real(kind=dp), intent(in) :: mobility_rad
473  !> Temperature (K).
474  real(kind=dp), intent(in) :: temp
475  !> Pressure (Pa).
476  real(kind=dp), intent(in) :: pressure
477 
478  real(kind=dp) :: rgeo
479 
480  rgeo = fractal_mobility_rad_to_geometric_rad(fractal, mobility_rad, temp, &
481  pressure)
483 
484  end function fractal_mobility_rad_to_vol
485 
486 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
487 
488  !> Determines the number of bytes required to pack the given value.
489  integer function pmc_mpi_pack_size_fractal(val)
490 
491  !> Value to pack.
492  type(fractal_t), intent(in) :: val
493 
495  pmc_mpi_pack_size_real(val%frac_dim) &
496  + pmc_mpi_pack_size_real(val%prime_radius) &
497  + pmc_mpi_pack_size_real(val%vol_fill_factor)
498 
499  end function pmc_mpi_pack_size_fractal
500 
501 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
502 
503  !> Packs the given value into the buffer, advancing position.
504  subroutine pmc_mpi_pack_fractal(buffer, position, val)
505 
506  !> Memory buffer.
507  character, intent(inout) :: buffer(:)
508  !> Current buffer position.
509  integer, intent(inout) :: position
510  !> Value to pack.
511  type(fractal_t), intent(in) :: val
512 
513  integer :: prev_position
514 
515  prev_position = position
516  call pmc_mpi_pack_real(buffer, position, val%frac_dim)
517  call pmc_mpi_pack_real(buffer, position, val%prime_radius)
518  call pmc_mpi_pack_real(buffer, position, val%vol_fill_factor)
519  call assert(287864891, &
520  position - prev_position <= pmc_mpi_pack_size_fractal(val))
521 
522  end subroutine pmc_mpi_pack_fractal
523 
524 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
525 
526  !> Unpacks the given value from the buffer, advancing position.
527  subroutine pmc_mpi_unpack_fractal(buffer, position, val)
528 
529  !> Memory buffer.
530  character, intent(inout) :: buffer(:)
531  !> Current buffer position.
532  integer, intent(inout) :: position
533  !> Value to pack.
534  type(fractal_t), intent(inout) :: val
535 
536  integer :: prev_position
537 
538  prev_position = position
539  call pmc_mpi_unpack_real(buffer, position, val%frac_dim)
540  call pmc_mpi_unpack_real(buffer, position, val%prime_radius)
541  call pmc_mpi_unpack_real(buffer, position, val%vol_fill_factor)
542  call assert(294756245, &
543  position - prev_position <= pmc_mpi_pack_size_fractal(val))
544 
545  end subroutine pmc_mpi_unpack_fractal
546 
547 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
548 
549  !> Read fractal specification from a spec file.
550  subroutine spec_file_read_fractal(file, fractal)
551 
552  !> Spec file.
553  type(spec_file_t), intent(inout) :: file
554  !> Fractal parameters.
555  type(fractal_t), intent(inout) :: fractal
556 
557  logical :: do_fractal
558 
559  !> \page input_format_fractal Input File Format: Fractal Data
560  !!
561  !! The fractal parameters are all held constant for the simulation,
562  !! and they are the same for all the particles.
563  !!
564  !! The fractal data file is specified by the parameters:
565  !! - \b frac_dim \f$d_{\rm f}\f$ (real, dimensionless): the fractal
566  !! dimension (3 for spherical and less than 3 for agglomerate)
567  !! - \b prime_radius \f$R_0\f$ (real, unit m): radius of primary
568  !! particles
569  !! - \b vol_fill_factor \f$f\f$ (real, dimensionless): the volume
570  !! filling factor which accounts for the fact that even
571  !! in a most closely packed structure the spherical monomers can
572  !! occupy only 74% of the available volume (1 for compact structure)
573  !!
574  !! See also:
575  !! - \ref spec_file_format --- the input file text format
576  !! - \ref output_format_fractal --- the corresponding output format
577 
578  call spec_file_read_logical(file, 'do_fractal', &
579  do_fractal)
580  if (do_fractal) then
581  call spec_file_read_real(file, 'frac_dim', &
582  fractal%frac_dim)
583  call spec_file_read_real(file, 'prime_radius', &
584  fractal%prime_radius)
585  call spec_file_read_real(file, 'vol_fill_factor', &
586  fractal%vol_fill_factor)
587  call assert_msg(801987241, fractal%frac_dim <= 3d0, &
588  'fractal dimension greater than 3')
589  else
590  call fractal_set_spherical(fractal)
591  end if
592 
593  end subroutine spec_file_read_fractal
594 
595 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
596 
597  !> Write full state.
598  subroutine fractal_output_netcdf(fractal, ncid)
599 
600  !> \page output_format_fractal Output File Format: Fractal Data
601  !!
602  !! The fractal data NetCDF variables are:
603  !! - \b fractal_dimension \f$d_{\rm f}\f$ (dimensionless):
604  !! particle volume fractal dimension
605  !! - \b fractal_prime_radius \f$R_0\f$ (unit m):
606  !! radius of primary particles
607  !! - \b fractal_vol_fill_factor \f$f\f$ (dimensionless):
608  !! volume filling factor
609  !!
610  !! See also:
611  !! - \ref input_format_fractal --- the corresponding input format
612 
613  !> Fractal parameters to write.
614  type(fractal_t), intent(in) :: fractal
615  !> NetCDF file ID, in data mode.
616  integer, intent(in) :: ncid
617 
618  call pmc_nc_write_real(ncid, fractal%frac_dim, "fractal_dimension", &
619  unit="1", description="particle volume fractal dimension")
620  call pmc_nc_write_real(ncid, fractal%prime_radius, &
621  "fractal_prime_radius", unit="m", &
622  description="radius of primary particles")
623  call pmc_nc_write_real(ncid, fractal%vol_fill_factor, &
624  "fractal_vol_fill_factor", unit="1", &
625  description="volume filling factor")
626 
627  end subroutine fractal_output_netcdf
628 
629 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
630 
631  !> Read full state.
632  subroutine fractal_input_netcdf(fractal, ncid)
633 
634  !> Fractal parameters to read.
635  type(fractal_t), intent(inout) :: fractal
636  !> NetCDF file ID, in data mode.
637  integer, intent(in) :: ncid
638 
639  call pmc_nc_read_real(ncid, fractal%frac_dim, "fractal_dimension")
640  call pmc_nc_read_real(ncid, fractal%prime_radius, "fractal_prime_radius")
641  call pmc_nc_read_real(ncid, fractal%vol_fill_factor, &
642  "fractal_vol_fill_factor")
643 
644  end subroutine fractal_input_netcdf
645 
646 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
647 
648 end module pmc_fractal
pmc_fractal::fractal_surface_frac_dim
real(kind=dp) function fractal_surface_frac_dim(fractal)
Compute surface fractal dimension .
Definition: fractal.F90:178
pmc_fractal::fractal_vol2rad
real(kind=dp) elemental function fractal_vol2rad(fractal, v)
Convert mass-equivalent volume (m^3) to geometric radius (m).
Definition: fractal.F90:107
pmc_mpi
Wrapper functions for MPI.
Definition: mpi.F90:13
pmc_mpi::pmc_mpi_pack_size_real
integer function pmc_mpi_pack_size_real(val)
Determines the number of bytes required to pack the given value.
Definition: mpi.F90:365
pmc_fractal::pmc_mpi_pack_size_fractal
integer function pmc_mpi_pack_size_fractal(val)
Determines the number of bytes required to pack the given value.
Definition: fractal.F90:490
pmc_util::sphere_rad2vol
real(kind=dp) elemental function sphere_rad2vol(r)
Convert geometric radius (m) to mass-equivalent volume (m^3) for spherical particles.
Definition: util.F90:265
pmc_fractal::fractal_a_slip
real(kind=dp), parameter fractal_a_slip
Constant in slip correction equation in Eq. 22 of Naumann [2003].
Definition: fractal.F90:43
pmc_util::die_msg
subroutine die_msg(code, error_msg)
Error immediately.
Definition: util.F90:134
pmc_fractal::fractal_mobility_rad_to_mobility_rad_in_continuum
real(kind=dp) function fractal_mobility_rad_to_mobility_rad_in_continuum(fractal, mobility_rad, temp, pressure)
Convert mobility equivalent radius (m) to that in the continuum regime (m).
Definition: fractal.F90:372
pmc_netcdf
Wrapper functions for NetCDF. These all take a NetCDF ncid in data mode and return with it again in d...
Definition: netcdf.F90:11
pmc_constants::dp
integer, parameter dp
Kind of a double precision real number.
Definition: constants.F90:12
pmc_spec_file
Reading formatted text input.
Definition: spec_file.F90:43
pmc_fractal::pmc_mpi_unpack_fractal
subroutine pmc_mpi_unpack_fractal(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: fractal.F90:528
pmc_spec_file::spec_file_read_logical
subroutine spec_file_read_logical(file, name, var)
Read a logical from a spec file that must have a given name.
Definition: spec_file.F90:584
pmc_fractal::fractal_slip_correct
real(kind=dp) function fractal_slip_correct(R_eff, temp, pressure)
Slip correction function from continuum to free molecular regime.
Definition: fractal.F90:277
pmc_mpi::pmc_mpi_pack_real
subroutine pmc_mpi_pack_real(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: mpi.F90:586
pmc_util::assert
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
Definition: util.F90:103
pmc_fractal::fractal_input_netcdf
subroutine fractal_input_netcdf(fractal, ncid)
Read full state.
Definition: fractal.F90:633
pmc_fractal::fractal_b_slip
real(kind=dp), parameter fractal_b_slip
Constant in slip correction equation in Eq. 22 of Naumann [2003].
Definition: fractal.F90:47
pmc_fractal::fractal_diam2vol
real(kind=dp) elemental function fractal_diam2vol(fractal, d)
Convert geometric diameter (m) to mass-equivalent volume (m^3).
Definition: fractal.F90:164
pmc_spec_file::spec_file_t
An input file with extra data for printing messages.
Definition: spec_file.F90:59
pmc_fractal::fractal_mobility_rad_to_vol
real(kind=dp) function fractal_mobility_rad_to_vol(fractal, mobility_rad, temp, pressure)
Convert mobility equivalent radius (m) to mass-equivalent volume (m^3).
Definition: fractal.F90:468
pmc_util::sphere_vol2rad
real(kind=dp) elemental function sphere_vol2rad(v)
Convert mass-equivalent volume (m^3) to geometric radius (m) for spherical particles.
Definition: util.F90:240
pmc_fractal::fractal_scale_exponent_s_acc
real(kind=dp), parameter fractal_scale_exponent_s_acc
Scaling exponent in calculating accessible particle surface area in Eq. 26 of Naumann [2003].
Definition: fractal.F90:53
pmc_fractal::fractal_vol_to_accessible_surface
real(kind=dp) function fractal_vol_to_accessible_surface(fractal, v)
Convert mass-equivalent volume (m^3) to accessible particle surface area (m^2).
Definition: fractal.F90:200
pmc_spec_file::spec_file_read_real
subroutine spec_file_read_real(file, name, var)
Read a real number from a spec file that must have the given name.
Definition: spec_file.F90:563
pmc_util::assert_msg
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
Definition: util.F90:77
pmc_util::diam2rad
real(kind=dp) elemental function diam2rad(d)
Convert diameter (m) to radius (m).
Definition: util.F90:277
pmc_fractal::fractal_vol2diam
real(kind=dp) elemental function fractal_vol2diam(fractal, v)
Convert mass-equivalent volume (m^3) to geometric diameter (m).
Definition: fractal.F90:128
pmc_netcdf::pmc_nc_write_real
subroutine pmc_nc_write_real(ncid, var, name, unit, long_name, standard_name, description)
Write a single real to a NetCDF file.
Definition: netcdf.F90:426
pmc_fractal::fractal_vol_to_mobility_rad_in_continuum
real(kind=dp) function fractal_vol_to_mobility_rad_in_continuum(fractal, v)
Convert mass-equivalent volume (m^3) to continuum regime mobility equivalent radius (m).
Definition: fractal.F90:240
ncid
integer, intent(in) ncid
Definition: fractal.F90:616
pmc_constants::const
type(const_t), save const
Fixed variable for accessing the constant's values.
Definition: constants.F90:73
pmc_fractal::fractal_is_spherical
elemental logical function fractal_is_spherical(fractal)
Test whether a particle is spherical.
Definition: fractal.F90:297
pmc_fractal::fractal_mobility_rad_to_geometric_rad
real(kind=dp) function fractal_mobility_rad_to_geometric_rad(fractal, mobility_rad, temp, pressure)
Convert mobility equivalent radius (m) to geometric radius (m^3).
Definition: fractal.F90:436
fractal
type(fractal_t), intent(in) fractal
Definition: fractal.F90:614
pmc_fractal::fractal_vol_to_mobility_rad
real(kind=dp) function fractal_vol_to_mobility_rad(fractal, v, temp, pressure)
Convert mass-equivalent volume (m^3) to mobility equivalent radius (m).
Definition: fractal.F90:317
pmc_constants
Physical constants.
Definition: constants.F90:9
pmc_fractal::fractal_vol_to_num_of_monomers
real(kind=dp) elemental function fractal_vol_to_num_of_monomers(fractal, v)
Convert mass-equivalent volume (m^3) to number of monomers in a fractal particle cluster.
Definition: fractal.F90:91
pmc_fractal
The fractal_t structure and associated subroutines.
Definition: fractal.F90:35
pmc_fractal::fractal_q_slip
real(kind=dp), parameter fractal_q_slip
Constant in slip correction equation in Eq. 22 of Naumann [2003].
Definition: fractal.F90:45
pmc_util::air_mean_free_path
real(kind=dp) function air_mean_free_path(temp, pressure)
Calculate air molecular mean free path (m).
Definition: util.F90:289
pmc_fractal::fractal_t
Fractal data.
Definition: fractal.F90:59
pmc_fractal::fractal_vol_to_effective_rad
real(kind=dp) function fractal_vol_to_effective_rad(fractal, v)
Convert mass-equivalent volume (m^3) to particle effective radius (m).
Definition: fractal.F90:258
pmc_fractal::fractal_scale_factor_s_acc
real(kind=dp), parameter fractal_scale_factor_s_acc
Scaling factor in calculating accessible particle surface area in Eq. 26 of Naumann [2003].
Definition: fractal.F90:50
pmc_fractal::fractal_rad2vol
real(kind=dp) elemental function fractal_rad2vol(fractal, r)
Convert geometric radius (m) to mass-equivalent volume (m^3).
Definition: fractal.F90:143
pmc_netcdf::pmc_nc_read_real
subroutine pmc_nc_read_real(ncid, var, name, must_be_present)
Read a single real from a NetCDF file.
Definition: netcdf.F90:149
pmc_fractal::fractal_set_spherical
subroutine fractal_set_spherical(fractal)
Set fractal parameters for spherical particles.
Definition: fractal.F90:74
pmc_fractal::pmc_mpi_pack_fractal
subroutine pmc_mpi_pack_fractal(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: fractal.F90:505
pmc_mpi::pmc_mpi_unpack_real
subroutine pmc_mpi_unpack_real(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: mpi.F90:843
pmc_fractal::fractal_kirkwood_riseman
real(kind=dp) function fractal_kirkwood_riseman(fractal)
Kirkwood-Riseman ratio .
Definition: fractal.F90:224