49 allocate(aero_weight_array%weight(0, 0))
62 integer,
intent(in) :: n_group
64 integer,
intent(in) :: n_class
66 allocate(aero_weight_array%weight(n_group, n_class))
79 integer,
intent(in) :: n_class
82 aero_weight_array%weight%type = aero_weight_type_none
83 aero_weight_array%weight%magnitude = 1d0
84 aero_weight_array%weight%exponent = 0d0
97 integer,
intent(in) :: n_class
99 real(kind=dp),
intent(in) :: exponent
102 aero_weight_array%weight%type = aero_weight_type_power
103 aero_weight_array%weight%magnitude = 1d0
104 aero_weight_array%weight%exponent = exponent
116 integer,
intent(in) :: n_class
119 aero_weight_array%weight(1, :)%type = aero_weight_type_none
120 aero_weight_array%weight(1, :)%magnitude = 1d0
121 aero_weight_array%weight(1, :)%exponent = 0d0
122 aero_weight_array%weight(2, :)%type = aero_weight_type_power
123 aero_weight_array%weight(2, :)%magnitude = 1d0
124 aero_weight_array%weight(2, :)%exponent = -3d0
137 deallocate(aero_weight_array%weight)
169 aero_weight_array_to)
176 if (any(shape(aero_weight_array_to%weight) &
177 /= shape(aero_weight_array_from%weight)))
then
178 deallocate(aero_weight_array_to%weight)
180 size(aero_weight_array_from%weight, 1), &
181 size(aero_weight_array_from%weight, 2))
184 aero_weight_array_to%weight)
221 real(kind=dp),
intent(in) :: factor
232 aero_weight_array_delta)
240 aero_weight_array_delta%weight)
250 aero_weight_array_to, sample_prop, overwrite_to)
257 real(kind=dp),
intent(in) :: sample_prop
259 logical,
intent(in),
optional :: overwrite_to
262 aero_weight_array_to%weight, sample_prop, overwrite_to)
278 aero_weight_array%weight(aero_particle%weight_group, &
279 aero_particle%weight_class), aero_particle)
287 aero_weight_array, i_class, radius)
292 integer,
intent(in) :: i_class
294 real(kind=dp),
intent(in) :: radius
297 real(kind=dp) :: num_conc(size(aero_weight_array%weight, 1))
299 do i_group = 1,
size(aero_weight_array%weight, 1)
301 aero_weight_array%weight(i_group, i_class), radius)
320 aero_weight_array, aero_particle%weight_class, &
333 integer :: i_group, i_class
336 do i_group = 1,
size(aero_weight_array%weight, 1)
337 do i_class = 1,
size(aero_weight_array%weight, 2)
339 aero_weight_array%weight(i_group, i_class))
343 if (all(abs(sum(aero_weight_array%weight%exponent, 1)) &
344 < 1d-20 * sum(abs(aero_weight_array%weight%exponent), 1)))
then
357 monotone_increasing, monotone_decreasing)
362 logical,
intent(out) :: monotone_increasing
364 logical,
intent(out) :: monotone_decreasing
366 integer :: i_group, i_class
367 logical :: mono_increasing_array(size(aero_weight_array%weight, 1), &
368 size(aero_weight_array%weight, 2))
369 logical :: mono_decreasing_array(size(aero_weight_array%weight, 1), &
370 size(aero_weight_array%weight, 2))
372 do i_group = 1,
size(aero_weight_array%weight, 1)
373 do i_class = 1,
size(aero_weight_array%weight, 2)
375 aero_weight_array%weight(i_group, i_class), &
376 mono_increasing_array(i_group, i_class), &
377 mono_decreasing_array(i_group, i_class))
381 monotone_increasing = all(mono_increasing_array)
382 monotone_decreasing = all(mono_decreasing_array)
391 radius_1, radius_2, num_conc_min, num_conc_max)
396 integer,
intent(in) :: i_class
398 real(kind=dp),
intent(in) :: radius_1
400 real(kind=dp),
intent(in) :: radius_2
402 real(kind=dp),
intent(out) :: num_conc_min
404 real(kind=dp),
intent(out) :: num_conc_max
406 real(kind=dp) :: num_conc_1, num_conc_2
407 logical :: monotone_increasing, monotone_decreasing
410 monotone_increasing, monotone_decreasing)
411 call
assert(857727714, monotone_increasing .or. monotone_decreasing)
417 num_conc_min = min(num_conc_1, num_conc_2)
418 num_conc_max = max(num_conc_1, num_conc_2)
432 integer,
intent(in) :: i_class
434 real(kind=dp),
intent(in) :: radius
436 real(kind=dp) :: comp_vols(size(aero_weight_array%weight, 1))
439 do i_group = 1,
size(aero_weight_array%weight, 1)
441 aero_weight_array%weight(i_group, i_class), radius)
457 integer :: i_group, i_class
459 do i_group = 1,
size(aero_weight_array%weight, 1)
460 do i_class = 1,
size(aero_weight_array%weight, 2)
461 call spec_file_read_aero_weight(file, &
462 aero_weight_array%weight(i_group, i_class))
476 integer :: i_group, i_class
482 do i_group = 1,
size(val%weight, 1)
483 do i_class = 1,
size(val%weight, 2)
498 character,
intent(inout) :: buffer(:)
500 integer,
intent(inout) :: position
505 integer :: prev_position, i_group, i_class
507 prev_position = position
510 do i_group = 1,
size(val%weight, 1)
511 do i_class = 1,
size(val%weight, 2)
513 val%weight(i_group, i_class))
528 character,
intent(inout) :: buffer(:)
530 integer,
intent(inout) :: position
535 integer :: prev_position, n_group, n_class, i_group, i_class
538 prev_position = position
542 do i_group = 1,
size(val%weight, 1)
543 do i_class = 1,
size(val%weight, 2)
545 val%weight(i_group, i_class))
560 ncid, dimid_aero_weight_group)
565 integer,
intent(in) :: ncid
567 integer,
intent(out) :: dimid_aero_weight_group
569 integer :: status, i_group, n_group
570 integer :: varid_aero_weight_group
571 integer :: aero_weight_group_centers(size(aero_weight_array%weight, 1))
574 status = nf90_inq_dimid(ncid,
"aero_weight_group", dimid_aero_weight_group)
575 if (status == nf90_noerr)
return
581 n_group =
size(aero_weight_array%weight, 1)
583 call
pmc_nc_check(nf90_def_dim(ncid,
"aero_weight_group", n_group, &
584 dimid_aero_weight_group))
585 call
pmc_nc_check(nf90_def_var(ncid,
"aero_weight_group", nf90_int, &
586 dimid_aero_weight_group, varid_aero_weight_group))
587 call
pmc_nc_check(nf90_put_att(ncid, varid_aero_weight_group, &
588 "description",
"dummy dimension variable (no useful value)"))
592 do i_group = 1,n_group
593 aero_weight_group_centers(i_group) = i_group
595 call
pmc_nc_check(nf90_put_var(ncid, varid_aero_weight_group, &
596 aero_weight_group_centers))
606 ncid, dimid_aero_weight_class)
611 integer,
intent(in) :: ncid
613 integer,
intent(out) :: dimid_aero_weight_class
615 integer :: status, i_class, n_class
616 integer :: varid_aero_weight_class
617 integer :: aero_weight_class_centers(size(aero_weight_array%weight, 2))
620 status = nf90_inq_dimid(ncid,
"aero_weight_class", dimid_aero_weight_class)
621 if (status == nf90_noerr)
return
627 n_class =
size(aero_weight_array%weight, 2)
629 call
pmc_nc_check(nf90_def_dim(ncid,
"aero_weight_class", n_class, &
630 dimid_aero_weight_class))
631 call
pmc_nc_check(nf90_def_var(ncid,
"aero_weight_class", nf90_int, &
632 dimid_aero_weight_class, varid_aero_weight_class))
633 call
pmc_nc_check(nf90_put_att(ncid, varid_aero_weight_class, &
634 "description",
"dummy dimension variable (no useful value)"))
638 do i_class = 1,n_class
639 aero_weight_class_centers(i_class) = i_class
641 call
pmc_nc_check(nf90_put_var(ncid, varid_aero_weight_class, &
642 aero_weight_class_centers))
649 subroutine aero_weight_array_output_netcdf(aero_weight_array, ncid)
654 integer,
intent(in) :: ncid
656 integer :: dimid_aero_weight_group, dimid_aero_weight_class
679 dimid_aero_weight_group)
681 dimid_aero_weight_class)
685 (/ dimid_aero_weight_group, dimid_aero_weight_class /), &
686 description=
"type of each aerosol weighting function: 0 = invalid, " &
687 //
"1 = none (w(D) = 1), 2 = power (w(D) = (D/D_0)^alpha), " &
688 //
"3 = MFA (mass flow) (w(D) = (D/D_0)^(-3))")
690 "weight_magnitude", &
691 (/ dimid_aero_weight_group, dimid_aero_weight_class /), &
693 description=
"magnitude for each weighting function")
696 (/ dimid_aero_weight_group, dimid_aero_weight_class /), unit=
"1", &
697 description=
"exponent alpha for the power weight_type, " &
698 //
"set to -3 for MFA, and zero otherwise")
700 end subroutine aero_weight_array_output_netcdf
710 integer,
intent(in) :: ncid
712 integer :: dimid_aero_weight_group, dimid_aero_weight_class, n_group
714 character(len=1000) :: name
715 integer,
allocatable :: type(:, :)
716 real(kind=dp),
allocatable :: magnitude(:, :), exponent(:, :)
718 call
pmc_nc_check(nf90_inq_dimid(ncid,
"aero_weight_group", &
719 dimid_aero_weight_group))
720 call
pmc_nc_check(nf90_inq_dimid(ncid,
"aero_weight_class", &
721 dimid_aero_weight_class))
723 dimid_aero_weight_group, name, n_group))
725 dimid_aero_weight_class, name, n_class))
726 call
assert(719221386, n_group < 1000)
727 call
assert(520105999, n_class < 1000)
729 allocate(
type(n_group, n_class
))
730 allocate(magnitude(n_group, n_class))
731 allocate(exponent(n_group, n_class))
737 call
assert(309191498,
size(magnitude) ==
size(type))
738 call
assert(588649520,
size(magnitude) ==
size(exponent))
743 aero_weight_array%weight%type =
type
744 aero_weight_array%weight%magnitude = magnitude
745 aero_weight_array%weight%exponent = exponent
748 deallocate(magnitude)
real(kind=dp) function aero_weight_array_single_num_conc(aero_weight_array, aero_particle)
Compute the number concentration for a particle (m^{-3}).
real(kind=dp) function aero_weight_num_conc_at_radius(aero_weight, radius)
Compute the number concentration at a given radius (m^{-3}).
subroutine aero_weight_array_minmax_num_conc(aero_weight_array, i_class, radius_1, radius_2, num_conc_min, num_conc_max)
Compute the maximum and minimum number concentrations between the given radii.
subroutine pmc_mpi_unpack_aero_weight(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
An input file with extra data for printing messages.
integer function pmc_mpi_pack_size_integer(val)
Determines the number of bytes required to pack the given value.
elemental subroutine aero_weight_normalize(aero_weight)
Sets the aero_weight to a non-zero normalized value.
subroutine aero_weight_array_check_monotonicity(aero_weight_array, monotone_increasing, monotone_decreasing)
Determine whether all weight functions in an array are monotone increasing, monotone decreasing...
subroutine aero_weight_netcdf_dim_aero_weight_class(aero_weight_array, ncid, dimid_aero_weight_class)
Write the aero_weight_class dimension to the given NetCDF file if it is not already present and in an...
subroutine aero_weight_array_allocate_size(aero_weight_array, n_group, n_class)
Allocates an aero_weight_array to the given size.
subroutine aero_weight_array_deallocate(aero_weight_array)
Free all storage.
elemental subroutine aero_weight_copy(aero_weight_from, aero_weight_to)
Copy an aero_weight.
The aero_weight_t structure and associated subroutines.
The aero_particle_t structure and associated subroutines.
elemental subroutine aero_weight_allocate(aero_weight)
Allocates an aero_weight.
elemental subroutine aero_weight_shift(aero_weight_from, aero_weight_to, sample_prop, overwrite_to)
Adjust source and destination weights to reflect moving sample_prop proportion of particles from aero...
subroutine aero_weight_array_scale(aero_weight_array, factor)
Scale the weights by the given factor, so new_weight = old_weight * factor.
integer function pmc_mpi_pack_size_aero_weight_array(val)
Determines the number of bytes required to pack the given value.
subroutine pmc_nc_check(status)
Check the status of a NetCDF function call.
subroutine aero_weight_array_allocate_flat(aero_weight_array, n_class)
Allocates an aero_weight_array as flat weightings.
subroutine spec_file_read_aero_weight_array(file, aero_weight_array)
Read an aero_weight_array from a spec file.
integer function sample_cts_pdf(pdf)
Sample the given continuous probability density function.
subroutine aero_weight_check_valid_exponent(aero_weight)
Ensures that a weight function exponent is valid.
elemental subroutine aero_weight_scale(aero_weight, factor)
Scale the weight by the given fraction, so new_weight = old_weight * factor.
elemental real(kind=dp) function aero_particle_radius(aero_particle)
Total radius of the particle (m).
integer function aero_weight_array_rand_group(aero_weight_array, i_class, radius)
Choose a random group at the given radius, with probability inversely proportional to group weight at...
An aerosol size distribution weighting function.
Random number generators.
real(kind=dp) function aero_weight_array_num_conc(aero_weight_array, aero_particle)
Compute the number concentration for a particle (m^{-3}).
subroutine pmc_mpi_pack_integer(buffer, position, val)
Packs the given value into the buffer, advancing position.
integer function pmc_mpi_pack_size_aero_weight(val)
Determines the number of bytes required to pack the given value.
elemental subroutine aero_weight_combine(aero_weight, aero_weight_delta)
Combine aero_weight_delta into aero_weight with a harmonic mean.
subroutine pmc_mpi_pack_aero_weight(buffer, position, val)
Packs the given value into the buffer, advancing position.
Common utility subroutines.
subroutine aero_weight_array_input_netcdf(aero_weight_array, ncid)
Read full aero_weight_array.
subroutine aero_weight_array_allocate(aero_weight_array)
Allocates an aero_weight_array.
subroutine pmc_mpi_unpack_integer(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
subroutine aero_weight_netcdf_dim_aero_weight_group(aero_weight_array, ncid, dimid_aero_weight_group)
Write the aero_weight_group dimension to the given NetCDF file if it is not already present and in an...
An array of aerosol size distribution weighting functions.
subroutine pmc_nc_read_real_2d(ncid, var, name, must_be_present)
Read a simple real 2D array from a NetCDF file.
Wrapper functions for MPI.
subroutine aero_weight_array_allocate_power(aero_weight_array, n_class, exponent)
Allocates an aero_weight_array as power weightings.
real(kind=dp) function aero_weight_array_num_conc_at_radius(aero_weight_array, i_class, radius)
Compute the total number concentration at a given radius (m^3).
The aero_weight_array_t structure and associated subroutines.
subroutine pmc_mpi_unpack_aero_weight_array(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
subroutine pmc_mpi_pack_aero_weight_array(buffer, position, val)
Packs the given value into the buffer, advancing position.
integer function aero_weight_array_n_class(aero_weight_array)
Return the number of weight classes.
Single aerosol particle data structure.
subroutine pmc_nc_write_real_2d(ncid, var, name, dimids, dim_name_1, dim_name_2, unit, long_name, standard_name, description)
Write a simple real 2D array to a NetCDF file.
Reading formatted text input.
integer function aero_weight_array_n_group(aero_weight_array)
Return the number of weight groups.
Wrapper functions for NetCDF. These all take a NetCDF ncid in data mode and return with it again in d...
subroutine pmc_nc_write_integer_2d(ncid, var, name, dimids, dim_name_1, dim_name_2, unit, long_name, standard_name, description)
Write a simple integer 2D array to a NetCDF file.
subroutine aero_weight_array_allocate_nummass(aero_weight_array, n_class)
Allocates an aero_weight_array as joint flat/power-3 weightings..
subroutine aero_weight_check_monotonicity(aero_weight, monotone_increasing, monotone_decreasing)
Determine whether a weight function is monotone increasing, monotone decreasing, or neither...
logical function aero_weight_array_check_flat(aero_weight_array)
Check whether a given aero_weight array is flat in total.
real(kind=dp) function aero_weight_num_conc(aero_weight, aero_particle)
Compute the number concentration for a particle (m^{-3}).
subroutine aero_weight_array_zero(aero_weight_array)
Zeros the contents of the aero_weight_array.
subroutine pmc_nc_read_integer_2d(ncid, var, name, must_be_present)
Read a simple integer 2D array from a NetCDF file.
elemental subroutine aero_weight_zero(aero_weight)
Zeros the contents of the aero_weight.
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
subroutine aero_weight_array_shift(aero_weight_array_from, aero_weight_array_to, sample_prop, overwrite_to)
Adjust source and destination weights to reflect moving sample_prop proportion of particles from aero...
subroutine aero_weight_array_combine(aero_weight_array, aero_weight_array_delta)
Combine aero_weight_array_delta into aero_weight_array with a harmonic mean.
subroutine aero_weight_array_copy(aero_weight_array_from, aero_weight_array_to)
Copy an aero_weight_array.
elemental subroutine aero_weight_deallocate(aero_weight)
Free all storage.
elemental subroutine aero_weight_array_normalize(aero_weight_array)
Normalizes the aero_weight_array to a non-zero value.