79 real(kind=
dp),
allocatable :: n_part_ideal(:, :)
84 type(aero_rep_update_data_single_particle_number_t) :: update_number
105 subroutine spec_file_read_aero_state_weighting_type(file, weighting_type, &
111 integer,
intent(out) :: weighting_type
114 real(kind=
dp),
intent(out) :: exponent
116 character(len=SPEC_LINE_MAX_VAR_LEN) :: weighting_name
139 if (trim(weighting_name) ==
'flat')
then
141 elseif (trim(weighting_name) ==
'power')
then
144 elseif (trim(weighting_name) ==
'nummass')
then
146 elseif (trim(weighting_name) ==
'flat_source')
then
148 elseif (trim(weighting_name) ==
'power_source')
then
151 elseif (trim(weighting_name) ==
'nummass_source')
then
153 elseif (trim(weighting_name) ==
'flat_specified')
then
155 elseif (trim(weighting_name) ==
'power_specified')
then
158 elseif (trim(weighting_name) ==
'nummass_specified')
then
162 "Unknown weighting type: " // trim(weighting_name))
165 end subroutine spec_file_read_aero_state_weighting_type
177 aero_state_to%awa = aero_state_from%awa
192 integer,
intent(in) :: weight_type
195 real(kind=
dp),
intent(in),
optional :: exponent
197 aero_state%valid_sort = .false.
198 select case(weight_type)
203 call assert_msg(656670336,
present(exponent), &
204 "exponent parameter required for AERO_STATE_WEIGHT_POWER")
212 call assert_msg(102143848,
present(exponent), &
213 "exponent parameter required for AERO_STATE_WEIGHT_POWER")
223 call assert_msg(430273501,
present(exponent), &
224 "exponent parameter required for AERO_STATE_WEIGHT_POWER")
231 call die_msg(969076992,
"unknown weight_type: " &
246 real(kind=
dp),
intent(in) :: n_part
248 integer :: n_group, n_class
252 if (
allocated(aero_state%n_part_ideal))
then
253 deallocate(aero_state%n_part_ideal)
255 allocate(aero_state%n_part_ideal(n_group, n_class))
256 aero_state%n_part_ideal = n_part / real(n_group * n_class, kind=
dp)
268 integer,
intent(in) :: source
272 call assert(932390238, source >= 1)
275 if (n_class > 1)
then
276 call assert(765048788, source <= n_class)
292 integer,
optional,
intent(in) :: i_group
294 integer,
optional,
intent(in) :: i_class
298 if (
present(i_group))
then
299 call assert(908743823,
present(i_class))
300 if (aero_state%valid_sort)
then
303 aero_state%aero_sorted%group_class%inverse(i_group, i_class))
308 if ((aero_state%apa%particle(i_part)%weight_group == i_group) &
310 (aero_state%apa%particle(i_part)%weight_class == i_class)) &
331 integer,
optional,
intent(in) :: i_group
333 integer,
optional,
intent(in) :: i_class
337 aero_state, i_group, i_class)
357 aero_state%valid_sort = .false.
375 logical,
optional,
intent(in) :: allow_resort
377 if (aero_state%valid_sort)
then
379 aero_particle, aero_data, allow_resort)
394 integer,
intent(in) :: i_part
396 if (aero_state%valid_sort)
then
398 aero_state%apa, i_part)
414 integer,
intent(in) :: i_part
428 record_removal, aero_info)
433 integer,
intent(in) :: i_part
435 logical,
intent(in) :: record_removal
439 if (record_removal)
then
453 i_bin, i_class, aero_particle)
458 integer,
intent(in) :: i_bin
460 integer,
intent(in) :: i_class
464 integer :: i_entry, i_part
466 call assert(742996300, aero_state%valid_sort)
468 aero_state%aero_sorted%size_class%inverse(i_bin, i_class)) > 0)
470 aero_state%aero_sorted%size_class%inverse(i_bin, i_class)))
471 i_part = aero_state%aero_sorted%size_class%inverse(i_bin, &
472 i_class)%entry(i_entry)
473 aero_particle = aero_state%apa%particle(i_part)
489 n_part_mean, random_weight_group)
496 integer,
intent(in) :: i_part
498 real(kind=
dp),
intent(in) :: n_part_mean
501 logical,
optional,
intent(in) :: random_weight_group
503 integer :: n_copies, i_dup, new_group
506 logical :: record_removal
509 if (n_copies == 0)
then
510 aero_info%id = aero_state%apa%particle(i_part)%id
512 aero_info%other_id = 0
514 record_removal = .false.
516 record_removal = .true.
519 record_removal, aero_info)
520 elseif (n_copies > 1)
then
521 do i_dup = 1,(n_copies - 1)
522 new_aero_particle = aero_state%apa%particle(i_part)
524 if (
present(random_weight_group))
then
525 if (random_weight_group)
then
528 aero_state%apa%particle(i_part)%weight_class, &
545 aero_particle, aero_data)
572 real(kind=
dp),
intent(out) &
578 reweight_num_conc(i_part) &
580 aero_state%apa%particle(i_part), aero_data)
605 real(kind=
dp),
intent(in) &
608 integer :: i_part, i_group, i_class
609 real(kind=
dp) :: n_part_old(
size(aero_state%awa%weight, 1), &
610 size(aero_state%awa%weight, 2))
611 real(kind=
dp) :: n_part_new(
size(aero_state%awa%weight, 1), &
612 size(aero_state%awa%weight, 2))
613 real(kind=
dp) :: old_num_conc, new_num_conc, n_part_mean
620 old_num_conc = reweight_num_conc(i_part)
622 aero_state%apa%particle(i_part), aero_data)
623 n_part_mean = old_num_conc / new_num_conc
624 i_group = aero_state%apa%particle(i_part)%weight_group
625 i_class = aero_state%apa%particle(i_part)%weight_class
626 n_part_new(i_group, i_class) = n_part_new(i_group, i_class) &
628 n_part_old(i_group, i_class) = n_part_old(i_group, i_class) + 1d0
633 do i_group = 1,
size(aero_state%awa%weight, 1)
634 do i_class = 1,
size(aero_state%awa%weight, 2)
635 if (n_part_old(i_group, i_class) == 0d0) cycle
637 n_part_new(i_group, i_class) / n_part_old(i_group, i_class))
644 old_num_conc = reweight_num_conc(i_part)
647 aero_state%apa%particle(i_part), aero_data)
648 n_part_mean = old_num_conc / new_num_conc
688 integer :: i_part, i_bin
690 do i_part = 1,aero_state_delta%apa%n_part
692 aero_state_delta%apa%particle(i_part), aero_data)
695 aero_state_delta%aero_info_array)
705 i_group, i_class, n_add, allow_doubling, allow_halving)
712 integer,
intent(in) :: i_group
714 integer,
intent(in) :: i_class
716 real(kind=
dp),
intent(in) :: n_add
718 logical,
intent(in) :: allow_doubling
720 logical,
intent(in) :: allow_halving
722 integer :: global_n_part, n_group, n_class
723 real(kind=
dp) :: mean_n_part, n_part_new, weight_ratio
724 real(kind=
dp) :: n_part_ideal_local_group
730 mean_n_part = real(global_n_part, kind=
dp)
736 n_part_new = mean_n_part + n_add
737 if (n_part_new == 0d0)
return
739 n_part_ideal_local_group = aero_state%n_part_ideal(i_group, i_class)
741 n_part_ideal_local_group = aero_state%n_part_ideal(i_group, i_class) &
744 if ((n_part_new < n_part_ideal_local_group / 2d0) &
745 .or. (n_part_new > n_part_ideal_local_group * 2d0)) &
747 weight_ratio = n_part_new / n_part_ideal_local_group
749 i_class, weight_ratio, allow_doubling, allow_halving)
759 aero_dist, sample_prop, characteristic_factor, create_time, &
760 allow_doubling, allow_halving, n_part_add)
769 real(kind=
dp),
intent(in) :: sample_prop
771 real(kind=
dp),
intent(in) :: characteristic_factor
773 real(kind=
dp),
intent(in) :: create_time
775 logical,
intent(in) :: allow_doubling
777 logical,
intent(in) :: allow_halving
779 integer,
intent(out),
optional :: n_part_add
781 real(kind=
dp) :: n_samp_avg, radius, total_vol
783 real(kind=
dp) :: size_factor
784 integer :: n_samp, i_mode, i_samp, i_group, i_class, n_group, n_class
787 n_group =
size(aero_state%awa%weight, 1)
788 n_class =
size(aero_state%awa%weight, 2)
789 if (
present(n_part_add))
then
792 do i_group = 1,n_group
795 aero_mode_get_weight_class(aero_dist%mode(i_mode)))
797 n_samp_avg = sample_prop * aero_mode_number(aero_dist%mode(i_mode), &
798 aero_state%awa%weight(i_group, i_class))
800 i_group, i_class, n_samp_avg, allow_doubling, allow_halving)
801 if (n_samp_avg == 0d0) cycle
804 n_samp_avg = sample_prop * aero_mode_number(aero_dist%mode(i_mode), &
805 aero_state%awa%weight(i_group, i_class))
807 size_factor = min((1.0d0 / (characteristic_factor * n_samp_avg)), &
810 if (
present(n_part_add))
then
811 n_part_add = n_part_add + n_samp
815 call aero_mode_sample_radius(aero_dist%mode(i_mode), aero_data, &
816 aero_state%awa%weight(i_group, i_class), radius, size_factor)
818 call aero_mode_sample_vols(aero_dist%mode(i_mode), total_vol, &
824 aero_dist%mode(i_mode)%source, create_time)
825 aero_particle%n_primary_parts = 1
841 integer,
intent(out) :: i_part
857 aero_data, sample_prob, removal_action)
866 real(kind=
dp),
intent(in) :: sample_prob
869 integer,
intent(in) :: removal_action
871 integer :: n_transfer, i_transfer, i_part
872 integer :: i_group, i_class
873 logical :: do_add, do_remove
874 real(kind=
dp) :: num_conc_from, num_conc_to
876 integer :: n_parts_before
878 call assert(721006962, (sample_prob >= 0d0) .and. (sample_prob <= 1d0))
883 do while (i_transfer < n_transfer)
887 aero_state_from%apa%particle(i_part), aero_data)
889 aero_state_from%apa%particle(i_part), aero_data)
890 if (num_conc_to == num_conc_from)
then
893 elseif (num_conc_to < num_conc_from)
then
896 if (
pmc_random() < num_conc_to / num_conc_from)
then
901 if (
pmc_random() < num_conc_from / num_conc_to)
then
908 aero_state_from%apa%particle(i_part), aero_data)
910 if (.not. do_remove)
then
912 particle(aero_state_to%apa%n_part))
917 aero_info%id = aero_state_from%apa%particle(i_part)%id
918 aero_info%action = removal_action
925 i_transfer = i_transfer + 1
937 aero_data, sample_prob, removal_action)
946 real(kind=
dp),
intent(in) :: sample_prob
949 integer,
intent(in) :: removal_action
951 integer :: n_transfer, i_transfer, i_part
952 logical :: do_add, do_remove, overwrite_to
953 real(kind=
dp) :: num_conc_from, num_conc_to
956 call assert(393205561, (sample_prob >= 0d0) .and. (sample_prob <= 1d0))
962 do i_transfer = 1,n_transfer
967 aero_state_from%apa%particle(i_part), aero_data)
969 aero_info%id = aero_state_from%apa%particle(i_part)%id
970 aero_info%action = removal_action
978 overwrite_to = .true.
980 sample_prob, overwrite_to)
999 integer :: i_part, i_bin
1000 real(kind=
dp) :: factor
1002 aero_binned%num_conc = 0d0
1003 aero_binned%vol_conc = 0d0
1007 if ((i_bin < 1) .or. (i_bin >
bin_grid_size(bin_grid)))
then
1008 call warn_msg(980232449,
"particle ID " // trim( &
1010 //
" outside of bin_grid, discarding")
1013 aero_state%apa%particle(i_part), aero_data) &
1014 / bin_grid%widths(i_bin)
1015 aero_binned%vol_conc(i_bin,:) = aero_binned%vol_conc(i_bin,:) &
1016 + aero_state%apa%particle(i_part)%vol * factor
1017 aero_binned%num_conc(i_bin) = aero_binned%num_conc(i_bin) &
1053 character(len=*),
optional,
intent(in) :: include(:)
1055 character(len=*),
optional,
intent(in) :: exclude(:)
1096 type(env_state_t),
intent(in) :: env_state
1107 aero_state%apa%particle(i_part), aero_data, env_state)
1126 type(
aero_data_t),
optional,
intent(in) :: aero_data
1128 character(len=*),
optional,
intent(in) :: include(:)
1130 character(len=*),
optional,
intent(in) :: exclude(:)
1135 logical,
allocatable :: use_species(:)
1136 integer :: i_name, i_spec
1138 if ((.not.
present(include)) .and. (.not.
present(exclude)))
then
1142 call assert_msg(599558703,
present(aero_data), &
1143 "must provide 'aero_data' if using 'include' or 'exclude'")
1145 if (
present(include))
then
1146 use_species = .false.
1147 do i_name = 1,
size(include)
1150 "unknown species: " // trim(include(i_name)))
1151 use_species(i_spec) = .true.
1154 use_species = .true.
1156 if (
present(exclude))
then
1157 do i_name = 1,
size(exclude)
1160 "unknown species: " // trim(exclude(i_name)))
1161 use_species(i_spec) = .false.
1166 if (use_species(i_spec))
then
1193 character(len=*),
optional,
intent(in) :: include(:)
1195 character(len=*),
optional,
intent(in) :: exclude(:)
1201 integer :: i_name, i_spec
1203 if ((.not.
present(include)) .and. (.not.
present(exclude)))
then
1208 if (
present(include))
then
1209 use_species = .false.
1210 do i_name = 1,
size(include)
1213 "unknown species: " // trim(include(i_name)))
1214 use_species(i_spec) = .true.
1217 use_species = .true.
1219 if (
present(exclude))
then
1220 do i_name = 1,
size(exclude)
1223 "unknown species: " // trim(exclude(i_name)))
1224 use_species(i_spec) = .false.
1229 if (use_species(i_spec))
then
1258 aero_state%apa%particle(i_part), aero_data)
1279 aero_state%apa%particle(i_part), aero_data)
1297 if (aero_data%i_water > 0)
then
1299 if (aero_state%apa%particle(i_part)%vol(aero_data%i_water) > 0d0) &
1303 aero_state%apa%particle(i_part), aero_data)
1329 integer :: i_part, i_source, i_comp
1330 real(kind=
dp) :: source_weighted_conc
1336 aero_state%apa%particle(i_part))
1337 i_source = aero_state%apa%particle(i_part)%component(i_comp)% &
1341 * (aero_state%apa%particle(i_part)%n_primary_parts &
1367 particle_frozen(i_part) = aero_state%apa%particle(i_part)%frozen
1371 / sum(particle_num_concs)
1379 aero_data, i_group, i_class)
1390 integer :: i_part, i_entry, n_entry
1394 aero_state%aero_sorted%group_class%inverse(i_group,i_class))
1395 do i_entry = 1,n_entry
1396 i_part = aero_state%aero_sorted%group_class%inverse(i_group, &
1397 i_class)%entry(i_entry)
1400 aero_state%apa%particle(i_part), aero_data)
1426 character(len=*),
optional :: include(:)
1428 character(len=*),
optional :: exclude(:)
1430 character(len=*),
optional :: group(:)
1432 character(len=*),
optional :: groups(:,:)
1439 integer :: i_name, i_spec, i_part, i_group, n_group
1441 real(kind=
dp) :: group_mass, non_group_mass, mass
1442 real(kind=
dp),
allocatable :: group_masses(:)
1444 if (
present(include))
then
1445 use_species = .false.
1446 do i_name = 1,
size(include)
1449 "unknown species: " // trim(include(i_name)))
1450 use_species(i_spec) = .true.
1453 use_species = .true.
1455 if (
present(exclude))
then
1456 do i_name = 1,
size(exclude)
1459 "unknown species: " // trim(exclude(i_name)))
1460 use_species(i_spec) = .false.
1463 if (
present(group))
then
1464 group_species = .false.
1465 do i_name = 1,
size(group)
1468 "unknown species: " // trim(group(i_name)))
1469 group_species(i_spec) = .true.
1473 non_group_mass = 0d0
1475 if (use_species(i_spec))
then
1477 aero_state%apa%particle(i_part), i_spec, aero_data)
1478 if (group_species(i_spec))
then
1479 group_mass = group_mass + mass
1481 non_group_mass = non_group_mass + mass
1486 =
entropy([group_mass, non_group_mass])
1488 else if (
present(groups))
then
1489 call assert_msg(161633285, .not.
present(include), &
1490 "cannot specify both 'include' and 'groups' arguments")
1491 call assert_msg(273540426, .not.
present(exclude), &
1492 "cannot specify both 'exclude' and 'groups' arguments")
1493 call assert_msg(499993914, .not.
present(group), &
1494 "cannot specify both 'group' and 'groups' arguments")
1496 n_group =
size(groups, 1)
1499 species_group_numbers = 0
1500 do i_group = 1, n_group
1501 do i_name = 1,
size(groups, 2)
1502 if (len_trim(groups(i_group, i_name)) > 0)
then
1504 groups(i_group, i_name))
1506 "unknown species: " // trim(groups(i_group, i_name)))
1507 if (use_species(i_spec))
then
1508 species_group_numbers(i_spec) = i_group
1514 allocate(group_masses(n_group))
1519 aero_state%apa%particle(i_part), i_spec, aero_data)
1520 i_group = species_group_numbers(i_spec)
1521 if (i_group > 0)
then
1522 group_masses(i_group) = group_masses(i_group) + mass
1531 aero_data), use_species))
1553 d_gamma, chi, include, exclude, group, groups)
1560 real(kind=
dp),
intent(out) :: d_alpha
1562 real(kind=
dp),
intent(out) :: d_gamma
1564 real(kind=
dp),
intent(out) :: chi
1566 character(len=*),
optional :: include(:)
1568 character(len=*),
optional :: exclude(:)
1570 character(len=*),
optional :: group(:)
1572 character(len=*),
optional :: groups(:,:)
1574 real(kind=
dp),
allocatable :: entropies(:), entropies_of_avg_part(:)
1575 real(kind=
dp),
allocatable :: masses(:), num_concs(:), &
1576 num_concs_of_avg_part(:), masses_of_avg_part(:)
1582 if (
present(groups))
then
1583 call assert_msg(726652236, .not.
present(include), &
1584 "cannot specify both 'include' and 'groups' arguments")
1585 call assert_msg(891097454, .not.
present(exclude), &
1586 "cannot specify both 'exclude' and 'groups' arguments")
1587 call assert_msg(938789093, .not.
present(group), &
1588 "cannot specify both 'group' and 'groups' arguments")
1590 include=pack(groups, len_trim(groups) > 0))
1598 include, exclude, group, groups)
1600 d_alpha = exp(sum(entropies * masses * num_concs) &
1601 / sum(masses * num_concs))
1605 aero_state_averaged = aero_state
1610 if (
present(groups))
then
1612 include=pack(groups, len_trim(groups) > 0))
1618 aero_data, include, exclude, group, groups)
1620 d_gamma = exp(sum(entropies_of_avg_part * masses_of_avg_part &
1621 * num_concs_of_avg_part) &
1622 / sum(masses_of_avg_part * num_concs_of_avg_part))
1624 chi = (d_alpha - 1) / (d_gamma - 1)
1638 type(env_state_t),
intent(in) :: env_state
1649 aero_state%apa%particle(i_part), aero_data, env_state)
1664 type(env_state_t),
intent(in) :: env_state
1673 aero_state%apa%particle(i_part), aero_data, env_state)
1693 integer :: i_part, i_bin
1694 real(kind=
dp) :: factor
1696 aero_binned%num_conc = 0d0
1697 aero_binned%vol_conc = 0d0
1702 if ((i_bin < 1) .or. (i_bin >
bin_grid_size(bin_grid)))
then
1703 call warn_msg(503871022,
"particle ID " // trim( &
1705 //
" outside of bin_grid, discarding")
1708 aero_state%apa%particle(i_part), aero_data) &
1709 / bin_grid%widths(i_bin)
1710 aero_binned%vol_conc(i_bin,:) = aero_binned%vol_conc(i_bin,:) &
1711 + aero_state%apa%particle(i_part)%vol * factor
1712 aero_binned%num_conc(i_bin) = aero_binned%num_conc(i_bin) &
1729 integer,
intent(in) :: i_group
1731 integer,
intent(in) :: i_class
1737 if ((aero_state%apa%particle(i_part)%weight_group == i_group) &
1738 .and. (aero_state%apa%particle(i_part)%weight_class == i_class)) &
1740 aero_particle = aero_state%apa%particle(i_part)
1745 aero_state%valid_sort = .false.
1758 integer,
intent(in) :: i_group
1760 integer,
intent(in) :: i_class
1764 logical :: record_removal
1767 if ((aero_state%apa%particle(i_part)%weight_group == i_group) &
1768 .and. (aero_state%apa%particle(i_part)%weight_class == i_class)) &
1771 aero_info%id = aero_state%apa%particle(i_part)%id
1774 record_removal = .false.
1776 record_removal = .true.
1779 record_removal, aero_info)
1793 allow_halving, initial_state_warning)
1800 logical,
intent(in) :: allow_doubling
1802 logical,
intent(in) :: allow_halving
1804 logical,
intent(in) :: initial_state_warning
1806 integer :: i_group, i_class, n_group, n_class, global_n_part
1808 n_group =
size(aero_state%awa%weight, 1)
1809 n_class =
size(aero_state%awa%weight, 2)
1813 if (allow_doubling)
then
1814 do i_group = 1,n_group
1815 do i_class = 1,n_class
1819 do while ((real(global_n_part, kind=
dp) &
1820 < aero_state%n_part_ideal(i_group, i_class) / 2d0) &
1821 .and. (global_n_part > 0))
1822 if (initial_state_warning)
then
1823 call warn_msg(716882783,
"doubling particles in initial " &
1836 if (allow_halving)
then
1837 do i_group = 1,n_group
1838 do i_class = 1,n_class
1840 i_group, i_class), kind=
dp) &
1841 > aero_state%n_part_ideal(i_group, i_class) * 2d0)
1842 if (initial_state_warning)
then
1844 "halving particles in initial condition")
1860 i_class, weight_ratio, allow_doubling, allow_halving)
1867 integer,
intent(in) :: i_group
1869 integer,
intent(in) :: i_class
1871 real(kind=
dp),
intent(in) :: weight_ratio
1873 logical,
intent(in) :: allow_doubling
1875 logical,
intent(in) :: allow_halving
1877 real(kind=
dp) :: ratio
1878 integer :: i_part, i_remove, n_remove, i_entry, n_part
1880 logical :: record_removal
1888 aero_state%aero_sorted%group_class%inverse(i_group, i_class))
1890 if ((weight_ratio > 1d0) .and. (allow_halving .or. (n_part == 0)))
then
1894 * (1d0 - 1d0 / weight_ratio))
1895 do i_remove = 1,n_remove
1897 aero_state%aero_sorted%group_class%inverse(i_group, i_class)))
1898 i_part = aero_state%aero_sorted%group_class%inverse(i_group, &
1899 i_class)%entry(i_entry)
1900 aero_info%id = aero_state%apa%particle(i_part)%id
1903 record_removal = .false.
1905 record_removal = .true.
1908 record_removal, aero_info)
1910 elseif ((weight_ratio < 1d0) &
1911 .and. (allow_doubling .or. (n_part == 0)))
then
1914 do i_entry = n_part,1,-1
1915 i_part = aero_state%aero_sorted%group_class%inverse(i_group, &
1916 i_class)%entry(i_entry)
1929 aero_data, specify_prob_transfer)
1934 real(kind=
dp),
intent(in) :: del_t
1936 real(kind=
dp),
intent(in) :: mix_timescale
1941 real(kind=
dp),
optional,
intent(in) :: specify_prob_transfer
1944 integer :: rank, n_proc, i_proc, ierr
1945 integer :: buffer_size, buffer_size_check
1946 character,
allocatable :: buffer(:)
1949 real(kind=
dp) :: prob_transfer, prob_not_transferred
1950 real(kind=
dp) :: prob_transfer_given_not_transferred
1955 if (n_proc == 1)
then
1962 allocate(aero_state_sends(n_proc))
1963 allocate(aero_state_recvs(n_proc))
1966 if (
present(specify_prob_transfer))
then
1967 prob_transfer = specify_prob_transfer / real(n_proc, kind=
dp)
1969 prob_transfer = (1d0 - exp(- del_t / mix_timescale)) &
1970 / real(n_proc, kind=
dp)
1974 prob_not_transferred = 1d0
1975 do i_proc = 0,(n_proc - 1)
1976 if (i_proc /= rank)
then
1981 prob_transfer_given_not_transferred = prob_transfer &
1982 / prob_not_transferred
1984 aero_state_sends(i_proc + 1), aero_data, &
1986 prob_not_transferred = prob_not_transferred - prob_transfer
1994 do i_proc = 0,(n_proc - 1)
1995 if (i_proc /= rank)
then
2002 deallocate(aero_state_sends)
2003 deallocate(aero_state_recvs)
2021 character,
allocatable :: sendbuf(:), recvbuf(:)
2022 integer :: sendcounts(size(send)), sdispls(size(send))
2023 integer :: recvcounts(size(send)), rdispls(size(send))
2024 integer :: i_proc, position, old_position, max_sendbuf_size, ierr
2028 max_sendbuf_size = 0
2031 max_sendbuf_size = max_sendbuf_size &
2036 allocate(sendbuf(max_sendbuf_size))
2040 old_position = position
2044 sendcounts(i_proc) = position - old_position
2046 call assert(393267406, position <= max_sendbuf_size)
2049 allocate(recvbuf(sum(recvcounts)))
2054 sdispls(i_proc) = sdispls(i_proc - 1) + sendcounts(i_proc - 1)
2055 rdispls(i_proc) = rdispls(i_proc - 1) + recvcounts(i_proc - 1)
2058 call mpi_alltoallv(sendbuf, sendcounts, sdispls, mpi_character, recvbuf, &
2059 recvcounts, rdispls, mpi_character, mpi_comm_world, ierr)
2064 call assert(189739257, position == rdispls(i_proc))
2065 if (recvcounts(i_proc) > 0)
then
2092 real(kind=
dp) :: total_volume_conc, particle_volume, num_conc
2093 integer :: i_bin, i_class, i_entry, i_part, i_spec
2098 species_volume_conc = 0d0
2099 total_volume_conc = 0d0
2100 do i_class = 1,
size(aero_state%awa%weight, 2)
2102 aero_state%aero_sorted%size_class%inverse(i_bin, i_class))
2103 i_part = aero_state%aero_sorted%size_class%inverse(i_bin, &
2104 i_class)%entry(i_entry)
2106 aero_state%apa%particle(i_part), aero_data)
2108 aero_state%apa%particle(i_part))
2109 species_volume_conc = species_volume_conc &
2110 + num_conc * aero_state%apa%particle(i_part)%vol
2111 total_volume_conc = total_volume_conc + num_conc * particle_volume
2114 do i_class = 1,
size(aero_state%awa%weight, 2)
2116 aero_state%aero_sorted%size_class%inverse(i_bin, i_class))
2117 i_part = aero_state%aero_sorted%size_class%inverse(i_bin, &
2118 i_class)%entry(i_entry)
2120 aero_state%apa%particle(i_part))
2121 aero_state%apa%particle(i_part)%vol &
2122 = particle_volume * species_volume_conc / total_volume_conc
2146 bin_center, preserve_number)
2156 logical,
intent(in) :: bin_center
2160 logical,
intent(in) :: preserve_number
2162 real(kind=
dp) :: total_volume_conc, particle_volume
2163 real(kind=
dp) :: new_particle_volume, num_conc, total_num_conc
2164 real(kind=
dp) :: lower_volume, upper_volume, center_volume
2165 real(kind=
dp) :: lower_function, upper_function, center_function
2166 integer :: i_bin, i_class, i_entry, i_part, i_bisect, n_part
2167 logical :: monotone_increasing, monotone_decreasing
2172 do i_class = 1,
size(aero_state%awa%weight, 2)
2174 aero_state%aero_sorted%size_class%inverse(i_bin, i_class)) &
2180 aero_state%aero_sorted%size_class%inverse(i_bin, i_class))
2181 total_num_conc = 0d0
2182 total_volume_conc = 0d0
2184 aero_state%aero_sorted%size_class%inverse(i_bin, i_class))
2185 i_part = aero_state%aero_sorted%size_class%inverse(i_bin, &
2186 i_class)%entry(i_entry)
2188 aero_state%apa%particle(i_part), aero_data)
2189 total_num_conc = total_num_conc + num_conc
2191 aero_state%apa%particle(i_part))
2192 total_volume_conc = total_volume_conc &
2193 + num_conc * particle_volume
2197 if (bin_center)
then
2199 bin_grid%centers(i_bin))
2204 new_particle_volume = total_volume_conc / num_conc &
2206 aero_state%aero_sorted%size_class%inverse(i_bin, i_class)), &
2208 elseif (preserve_number)
then
2219 monotone_increasing, monotone_decreasing)
2221 monotone_increasing .or. monotone_decreasing, &
2222 "monotone weight function required for averaging")
2225 do i_entry = 1,n_part
2226 i_part = aero_state%aero_sorted%size_class%inverse(i_bin, &
2227 i_class)%entry(i_entry)
2229 aero_state%apa%particle(i_part))
2230 if (i_part == 1)
then
2231 lower_volume = particle_volume
2232 upper_volume = particle_volume
2234 lower_volume = min(lower_volume, particle_volume)
2235 upper_volume = max(upper_volume, particle_volume)
2238 lower_function = real(n_part, kind=
dp) &
2242 upper_function = real(n_part, kind=
dp) &
2249 center_volume = (lower_volume + upper_volume) / 2d0
2250 center_function = real(n_part, kind=
dp) &
2254 if ((lower_function > 0d0 .and. center_function > 0d0) &
2255 .or. (lower_function < 0d0 .and. center_function < 0d0)) &
2257 lower_volume = center_volume
2258 lower_function = center_function
2260 upper_volume = center_volume
2261 upper_function = center_function
2265 new_particle_volume = center_volume
2277 monotone_increasing, monotone_decreasing)
2279 monotone_increasing .or. monotone_decreasing, &
2280 "monotone weight function required for averaging")
2283 do i_entry = 1,n_part
2284 i_part = aero_state%aero_sorted%size_class%inverse(i_bin, &
2285 i_class)%entry(i_entry)
2287 aero_state%apa%particle(i_part))
2288 if (i_part == 1)
then
2289 lower_volume = particle_volume
2290 upper_volume = particle_volume
2292 lower_volume = min(lower_volume, particle_volume)
2293 upper_volume = max(upper_volume, particle_volume)
2296 lower_function = real(n_part, kind=
dp) &
2299 lower_volume)) * lower_volume - total_volume_conc
2300 upper_function = real(n_part, kind=
dp) &
2303 upper_volume)) * upper_volume - total_volume_conc
2307 center_volume = (lower_volume + upper_volume) / 2d0
2308 center_function = real(n_part, kind=
dp) &
2311 center_volume)) * center_volume - total_volume_conc
2312 if ((lower_function > 0d0 .and. center_function > 0d0) &
2313 .or. (lower_function < 0d0 .and. center_function < 0d0)) &
2315 lower_volume = center_volume
2316 lower_function = center_function
2318 upper_volume = center_volume
2319 upper_function = center_function
2323 new_particle_volume = center_volume
2326 do i_entry = 1,n_part
2327 i_part = aero_state%aero_sorted%size_class%inverse(i_bin, &
2328 i_class)%entry(i_entry)
2330 aero_state%apa%particle(i_part))
2331 aero_state%apa%particle(i_part)%vol &
2332 = aero_state%apa%particle(i_part)%vol &
2333 / particle_volume * new_particle_volume
2351 real(kind=
dp) :: reweight_num_conc(aero_state%apa%n_part)
2354 aero_state%valid_sort = .false.
2358 if (aero_data%i_water > 0)
then
2360 aero_state%apa%particle(i_part)%vol(aero_data%i_water) = 0d0
2362 aero_state%valid_sort = .false.
2377 integer :: total_size, i_group
2394 character,
intent(inout) :: buffer(:)
2396 integer,
intent(inout) :: position
2401 integer :: prev_position, i_group
2403 prev_position = position
2420 character,
intent(inout) :: buffer(:)
2422 integer,
intent(inout) :: position
2427 integer :: prev_position, i_group, n_group
2429 val%valid_sort = .false.
2430 prev_position = position
2455 integer :: n_proc, ierr, status(MPI_STATUS_SIZE)
2456 integer :: buffer_size, max_buffer_size, i_proc, position
2457 character,
allocatable :: buffer(:)
2461 aero_state_total = aero_state
2469 max_buffer_size = max_buffer_size &
2471 allocate(buffer(max_buffer_size))
2474 call assert(542772170, position <= max_buffer_size)
2475 buffer_size = position
2476 call mpi_send(buffer, buffer_size, mpi_character, 0, &
2483 do i_proc = 1,(n_proc - 1)
2488 call mpi_get_count(status, mpi_character, buffer_size, ierr)
2492 allocate(buffer(buffer_size))
2493 call mpi_recv(buffer, buffer_size, mpi_character, i_proc, &
2500 aero_state_transfer)
2501 call assert(518174881, position == buffer_size)
2519 dimid_aero_particle)
2524 integer,
intent(in) :: ncid
2526 integer,
intent(out) :: dimid_aero_particle
2528 integer :: status, i_part
2529 integer :: varid_aero_particle
2530 integer :: aero_particle_centers(aero_state_n_part(aero_state))
2533 status = nf90_inq_dimid(ncid,
"aero_particle", dimid_aero_particle)
2534 if (status == nf90_noerr)
return
2535 if (status /= nf90_ebaddim)
call pmc_nc_check(status)
2538 call pmc_nc_check(nf90_redef(ncid))
2540 call pmc_nc_check(nf90_def_dim(ncid,
"aero_particle", &
2541 aero_state_n_part(aero_state), dimid_aero_particle))
2543 call pmc_nc_check(nf90_enddef(ncid))
2545 do i_part = 1,aero_state_n_part(aero_state)
2546 aero_particle_centers(i_part) = i_part
2548 call pmc_nc_write_integer_1d(ncid, aero_particle_centers, &
2549 "aero_particle", (/ dimid_aero_particle /), &
2550 description=
"dummy dimension variable (no useful value)")
2565 integer,
intent(in) :: ncid
2567 integer,
intent(out) :: dimid_aero_removed
2569 integer :: status, i_remove, dim_size
2570 integer :: varid_aero_removed
2571 integer :: aero_removed_centers( &
2572 max(1, aero_info_array_n_item(aero_state%aero_info_array)))
2575 status = nf90_inq_dimid(ncid,
"aero_removed", dimid_aero_removed)
2576 if (status == nf90_noerr)
return
2577 if (status /= nf90_ebaddim)
call pmc_nc_check(status)
2580 call pmc_nc_check(nf90_redef(ncid))
2582 dim_size = max(1, aero_info_array_n_item(aero_state%aero_info_array))
2583 call pmc_nc_check(nf90_def_dim(ncid,
"aero_removed", &
2584 dim_size, dimid_aero_removed))
2586 call pmc_nc_check(nf90_enddef(ncid))
2588 do i_remove = 1,dim_size
2589 aero_removed_centers(i_remove) = i_remove
2591 call pmc_nc_write_integer_1d(ncid, aero_removed_centers, &
2592 "aero_removed", (/ dimid_aero_removed /), &
2593 description=
"dummy dimension variable (no useful value)")
2603 dimid_aero_components)
2608 integer,
intent(in) :: ncid
2610 integer,
intent(out) :: dimid_aero_components
2612 integer :: status, dim_size
2615 status = nf90_inq_dimid(ncid,
"aero_components", dimid_aero_components)
2616 if (status == nf90_noerr)
return
2617 if (status /= nf90_ebaddim)
call pmc_nc_check(status)
2620 call pmc_nc_check(nf90_redef(ncid))
2623 call pmc_nc_check(nf90_def_dim(ncid,
"aero_components", &
2624 dim_size, dimid_aero_components))
2626 call pmc_nc_check(nf90_enddef(ncid))
2633 subroutine aero_state_output_netcdf(aero_state, ncid, aero_data, &
2634 record_removals, record_optical)
2639 integer,
intent(in) :: ncid
2643 logical,
intent(in) :: record_removals
2645 logical,
intent(in) :: record_optical
2647 integer :: dimid_aero_particle, dimid_aero_species, dimid_aero_source
2648 integer :: dimid_aero_removed
2649 integer :: dimid_aero_components
2650 integer :: dimid_optical_wavelengths
2651 integer :: i_part, i_remove
2654 integer :: aero_particle_weight_group(aero_state_n_part(aero_state))
2655 integer :: aero_particle_weight_class(aero_state_n_part(aero_state))
2656 real(kind=
dp) :: aero_absorb_cross_sect(aero_state_n_part(aero_state), &
2658 real(kind=
dp) :: aero_scatter_cross_sect(aero_state_n_part(aero_state), &
2660 real(kind=
dp) :: aero_asymmetry(aero_state_n_part(aero_state),
n_swbands)
2661 real(kind=
dp) :: aero_refract_shell_real(aero_state_n_part(aero_state), &
2663 real(kind=
dp) :: aero_refract_shell_imag(aero_state_n_part(aero_state), &
2665 real(kind=
dp) :: aero_refract_core_real(aero_state_n_part(aero_state), &
2667 real(kind=
dp) :: aero_refract_core_imag(aero_state_n_part(aero_state), &
2669 real(kind=
dp) :: aero_core_vol(aero_state_n_part(aero_state))
2670 integer :: aero_water_hyst_leg(aero_state_n_part(aero_state))
2671 real(kind=
dp) :: aero_num_conc(aero_state_n_part(aero_state))
2672 integer(kind=8) :: aero_id(aero_state_n_part(aero_state))
2673 integer :: aero_frozen(aero_state_n_part(aero_state))
2674 real(kind=
dp) :: aero_imf_temperature(aero_state_n_part(aero_state))
2675 real(kind=
dp) :: aero_ice_density(aero_state_n_part(aero_state))
2676 real(kind=
dp) :: aero_ice_shape_phi(aero_state_n_part(aero_state))
2677 real(kind=
dp) :: aero_least_create_time(aero_state_n_part(aero_state))
2678 real(kind=
dp) :: aero_greatest_create_time(aero_state_n_part(aero_state))
2679 integer(kind=8) :: aero_removed_id( &
2680 max(1, aero_info_array_n_item(aero_state%aero_info_array)))
2681 integer :: aero_removed_action( &
2682 max(1, aero_info_array_n_item(aero_state%aero_info_array)))
2683 integer(kind=8) :: aero_removed_other_id( &
2684 max(1, aero_info_array_n_item(aero_state%aero_info_array)))
2685 integer :: aero_component_particle_num(aero_state_total_n_components( &
2687 integer :: aero_component_source_num(aero_state_total_n_components( &
2689 real(kind=
dp) :: aero_component_create_time( &
2690 aero_state_total_n_components(aero_state))
2691 integer :: aero_component_len(aero_state_n_part(aero_state))
2692 integer :: aero_component_start_ind(aero_state_n_part(aero_state))
2693 integer :: aero_particle_n_primary_parts(aero_state_n_part(aero_state))
2694 integer :: array_position, i_comp, next_start_component_ind
2791 call aero_weight_array_output_netcdf(aero_state%awa, ncid)
2798 if (record_optical)
then
2800 dimid_optical_wavelengths)
2803 if (aero_state_n_part(aero_state) > 0)
then
2805 dimid_aero_particle)
2807 dimid_aero_components)
2808 next_start_component_ind = 1
2809 do i_part = 1,aero_state_n_part(aero_state)
2811 = aero_state%apa%particle(i_part)%vol * aero_data%density
2813 aero_state%apa%particle(i_part))
2814 aero_component_start_ind(i_part) = next_start_component_ind
2815 next_start_component_ind = next_start_component_ind &
2816 + aero_component_len(i_part)
2817 do i_comp = 1,aero_component_len(i_part)
2818 array_position = aero_component_start_ind(i_part) + i_comp - 1
2819 aero_component_particle_num(array_position) = i_part
2820 aero_component_source_num(array_position) &
2821 = aero_state%apa%particle(i_part)%component(i_comp)%source_id
2822 aero_component_create_time(array_position) &
2823 = aero_state%apa%particle(i_part)%component( &
2826 aero_particle_weight_group(i_part) &
2827 = aero_state%apa%particle(i_part)%weight_group
2828 aero_particle_weight_class(i_part) &
2829 = aero_state%apa%particle(i_part)%weight_class
2830 aero_water_hyst_leg(i_part) &
2831 = aero_state%apa%particle(i_part)%water_hyst_leg
2832 aero_num_conc(i_part) &
2834 aero_state%apa%particle(i_part), aero_data)
2835 aero_id(i_part) = aero_state%apa%particle(i_part)%id
2836 if (aero_state%apa%particle(i_part)%frozen)
then
2837 aero_frozen(i_part) = 1
2839 aero_frozen(i_part) = 0
2841 aero_imf_temperature(i_part) &
2842 = aero_state%apa%particle(i_part)%imf_temperature
2843 aero_ice_density(i_part) = aero_state%apa%particle(i_part)%den_ice
2844 aero_ice_shape_phi(i_part) &
2845 = aero_state%apa%particle(i_part)%ice_shape_phi
2846 aero_least_create_time(i_part) &
2847 = aero_state%apa%particle(i_part)%least_create_time
2848 aero_greatest_create_time(i_part) &
2849 = aero_state%apa%particle(i_part)%greatest_create_time
2850 aero_particle_n_primary_parts(i_part) &
2851 = aero_state%apa%particle(i_part)%n_primary_parts
2852 if (record_optical)
then
2853 aero_absorb_cross_sect(i_part,:) &
2854 = aero_state%apa%particle(i_part)%absorb_cross_sect
2855 aero_scatter_cross_sect(i_part,:) &
2856 = aero_state%apa%particle(i_part)%scatter_cross_sect
2857 aero_asymmetry(i_part,:) &
2858 = aero_state%apa%particle(i_part)%asymmetry
2859 aero_refract_shell_real(i_part,:) &
2860 = real(aero_state%apa%particle(i_part)%refract_shell)
2861 aero_refract_shell_imag(i_part,:) &
2862 = aimag(aero_state%apa%particle(i_part)%refract_shell)
2863 aero_refract_core_real(i_part,:) &
2864 = real(aero_state%apa%particle(i_part)%refract_core)
2865 aero_refract_core_imag(i_part,:) &
2866 = aimag(aero_state%apa%particle(i_part)%refract_core)
2867 aero_core_vol(i_part) = aero_state%apa%particle(i_part)%core_vol
2871 "aero_particle_mass", (/ dimid_aero_particle, &
2872 dimid_aero_species /), unit=
"kg", &
2873 long_name=
"constituent masses of each aerosol particle")
2875 call pmc_nc_write_integer_1d(ncid, aero_component_len, &
2876 "aero_component_len", (/ dimid_aero_particle /), &
2877 long_name=
"number of aero_components for each aerosol particle")
2878 call pmc_nc_write_integer_1d(ncid, aero_component_start_ind, &
2879 "aero_component_start_ind", (/ dimid_aero_particle /), &
2880 long_name=
"start index of aero_component for each aerosol " &
2882 call pmc_nc_write_integer_1d(ncid, aero_component_particle_num, &
2883 "aero_component_particle_num", (/ dimid_aero_components /), &
2884 long_name=
"associated aerosol particle number for each component")
2885 call pmc_nc_write_integer_1d(ncid, aero_component_source_num, &
2886 "aero_component_source_num", (/ dimid_aero_components /), &
2887 long_name=
"associated source number for each component")
2888 call pmc_nc_write_real_1d(ncid, aero_component_create_time, &
2889 "aero_component_create_time", (/ dimid_aero_components /), &
2890 long_name=
"associated creation time for each component")
2891 call pmc_nc_write_integer_1d(ncid, aero_particle_weight_group, &
2892 "aero_particle_weight_group", (/ dimid_aero_particle /), &
2893 long_name=
"weight group number of each aerosol particle")
2894 call pmc_nc_write_integer_1d(ncid, aero_particle_weight_class, &
2895 "aero_particle_weight_class", (/ dimid_aero_particle /), &
2896 long_name=
"weight class number of each aerosol particle")
2897 call pmc_nc_write_integer_1d(ncid, aero_water_hyst_leg, &
2898 "aero_water_hyst_leg", (/ dimid_aero_particle /), &
2899 long_name=
"leg of the water hysteresis curve leg of each "&
2900 //
"aerosol particle")
2901 call pmc_nc_write_real_1d(ncid, aero_num_conc, &
2902 "aero_num_conc", (/ dimid_aero_particle /), unit=
"m^{-3}", &
2903 long_name=
"number concentration for each particle")
2904 call pmc_nc_write_integer64_1d(ncid, aero_id, &
2905 "aero_id", (/ dimid_aero_particle /), &
2906 long_name=
"unique ID number of each aerosol particle")
2907 call pmc_nc_write_integer_1d(ncid, aero_frozen, &
2908 "aero_frozen", (/ dimid_aero_particle /), &
2909 long_name=
"flag indicating ice phase of each aerosol particle")
2910 call pmc_nc_write_real_1d(ncid, aero_imf_temperature, &
2911 "aero_imf_temperature", (/ dimid_aero_particle /), &
2912 long_name=
"immersion freezing temperature (Singular)")
2913 call pmc_nc_write_real_1d(ncid, aero_ice_density, &
2914 "aero_ice_density", (/ dimid_aero_particle /), &
2915 long_name=
"Ice density if the particle nucleates to ice, -9999 indicates the particle is not an ice.")
2916 call pmc_nc_write_real_1d(ncid, aero_ice_shape_phi, &
2917 "aero_ice_shape_phi", (/ dimid_aero_particle /), &
2918 long_name=
"Ice shape parameter phi")
2919 call pmc_nc_write_real_1d(ncid, aero_least_create_time, &
2920 "aero_least_create_time", (/ dimid_aero_particle /), unit=
"s", &
2921 long_name=
"least creation time of each aerosol particle", &
2922 description=
"least (earliest) creation time of any original " &
2923 //
"constituent particles that coagulated to form each " &
2924 //
"particle, measured from the start of the simulation")
2925 call pmc_nc_write_real_1d(ncid, aero_greatest_create_time, &
2926 "aero_greatest_create_time", (/ dimid_aero_particle /), &
2928 long_name=
"greatest creation time of each aerosol particle", &
2929 description=
"greatest (latest) creation time of any original " &
2930 //
"constituent particles that coagulated to form each " &
2931 //
"particle, measured from the start of the simulation")
2932 call pmc_nc_write_integer_1d(ncid, aero_particle_n_primary_parts, &
2933 "aero_particle_n_primary_parts", (/ dimid_aero_particle /), &
2934 unit=
"1", long_name=
"number of primary particles that contribute" &
2935 //
"to each particle.")
2936 if (record_optical)
then
2937 call pmc_nc_write_real_2d(ncid, aero_absorb_cross_sect, &
2938 "aero_absorb_cross_sect", (/ dimid_aero_particle, &
2939 dimid_optical_wavelengths /), unit=
"m^2", &
2940 long_name=
"optical absorption cross sections of each " &
2941 //
"aerosol particle")
2942 call pmc_nc_write_real_2d(ncid, aero_scatter_cross_sect, &
2943 "aero_scatter_cross_sect", (/ dimid_aero_particle, &
2944 dimid_optical_wavelengths /), unit=
"m^2", &
2945 long_name=
"optical scattering cross sections of each " &
2946 //
"aerosol particle")
2947 call pmc_nc_write_real_2d(ncid, aero_asymmetry, &
2948 "aero_asymmetry", (/ dimid_aero_particle, &
2949 dimid_optical_wavelengths /), unit=
"1", &
2950 long_name=
"optical asymmetry parameters of each " &
2951 //
"aerosol particle")
2952 call pmc_nc_write_real_2d(ncid, aero_refract_shell_real, &
2953 "aero_refract_shell_real", (/ dimid_aero_particle, &
2954 dimid_optical_wavelengths /), unit=
"1", &
2955 long_name=
"real part of the refractive indices of the " &
2956 //
"shell of each aerosol particle")
2957 call pmc_nc_write_real_2d(ncid, aero_refract_shell_imag, &
2958 "aero_refract_shell_imag", (/ dimid_aero_particle, &
2959 dimid_optical_wavelengths /), unit=
"1", &
2960 long_name=
"imaginary part of the refractive indices of " &
2961 //
"the shell of each aerosol particle")
2962 call pmc_nc_write_real_2d(ncid, aero_refract_core_real, &
2963 "aero_refract_core_real", (/ dimid_aero_particle, &
2964 dimid_optical_wavelengths /), unit=
"1", &
2965 long_name=
"real part of the refractive indices of the core " &
2966 //
"of each aerosol particle")
2967 call pmc_nc_write_real_2d(ncid, aero_refract_core_imag, &
2968 "aero_refract_core_imag", (/ dimid_aero_particle, &
2969 dimid_optical_wavelengths /), unit=
"1", &
2970 long_name=
"imaginary part of the refractive indices of " &
2971 //
"the core of each aerosol particle")
2972 call pmc_nc_write_real_1d(ncid, aero_core_vol, &
2973 "aero_core_vol", (/ dimid_aero_particle /), unit=
"m^3", &
2974 long_name=
"volume of the optical cores of each " &
2975 //
"aerosol particle")
2981 if (record_removals)
then
2984 if (aero_info_array_n_item(aero_state%aero_info_array) >= 1)
then
2985 do i_remove = 1,aero_info_array_n_item(aero_state%aero_info_array)
2986 aero_removed_id(i_remove) = &
2987 aero_state%aero_info_array%aero_info(i_remove)%id
2988 aero_removed_action(i_remove) = &
2989 aero_state%aero_info_array%aero_info(i_remove)%action
2990 aero_removed_other_id(i_remove) = &
2991 aero_state%aero_info_array%aero_info(i_remove)%other_id
2994 aero_removed_id(1) = 0
2996 aero_removed_other_id(1) = 0
2998 call pmc_nc_write_integer64_1d(ncid, aero_removed_id, &
2999 "aero_removed_id", (/ dimid_aero_removed /), &
3000 long_name=
"ID of removed particles")
3001 call pmc_nc_write_integer_1d(ncid, aero_removed_action, &
3002 "aero_removed_action", (/ dimid_aero_removed /), &
3003 long_name=
"reason for particle removal", &
3004 description=
"valid is 0 (invalid entry), 1 (removed due to " &
3005 //
"dilution), 2 (removed due to coagulation -- combined " &
3006 //
"particle ID is in \c aero_removed_other_id), 3 (removed " &
3007 //
"due to populating halving), or 4 (removed due to " &
3008 //
"weighting changes")
3009 call pmc_nc_write_integer64_1d(ncid, aero_removed_other_id, &
3010 "aero_removed_other_id", (/ dimid_aero_removed /), &
3011 long_name=
"ID of other particle involved in removal", &
3012 description=
"if <tt>aero_removed_action(i)</tt> is 2 " &
3013 //
"(due to coagulation), then " &
3014 //
"<tt>aero_removed_other_id(i)</tt> is the ID of the " &
3015 //
"resulting combined particle, or 0 if the new particle " &
3016 //
"was not created")
3019 end subroutine aero_state_output_netcdf
3091 integer,
intent(in) :: ncid
3095 integer :: dimid_aero_particle, dimid_aero_removed, n_info_item, n_part
3096 integer :: i_bin, i_part_in_bin, i_part, i_remove, status
3098 character(len=1000) :: name
3101 integer,
allocatable :: aero_particle_weight_group(:)
3102 integer,
allocatable :: aero_particle_weight_class(:)
3103 real(kind=
dp),
allocatable :: aero_absorb_cross_sect(:,:)
3104 real(kind=
dp),
allocatable :: aero_scatter_cross_sect(:,:)
3105 real(kind=
dp),
allocatable :: aero_asymmetry(:,:)
3106 real(kind=
dp),
allocatable :: aero_refract_shell_real(:,:)
3107 real(kind=
dp),
allocatable :: aero_refract_shell_imag(:,:)
3108 real(kind=
dp),
allocatable :: aero_refract_core_real(:,:)
3109 real(kind=
dp),
allocatable :: aero_refract_core_imag(:,:)
3110 real(kind=
dp),
allocatable :: aero_core_vol(:)
3111 integer,
allocatable :: aero_water_hyst_leg(:)
3112 real(kind=
dp),
allocatable :: aero_num_conc(:)
3113 integer,
allocatable :: aero_frozen(:)
3114 real(kind=
dp),
allocatable :: aero_imf_temperature(:)
3115 real(kind=
dp),
allocatable :: aero_ice_density(:)
3116 real(kind=
dp),
allocatable :: aero_ice_shape_phi(:)
3117 integer(kind=8),
allocatable :: aero_id(:)
3118 real(kind=
dp),
allocatable :: aero_least_create_time(:)
3119 real(kind=
dp),
allocatable :: aero_greatest_create_time(:)
3120 integer,
allocatable :: aero_removed_id(:)
3121 integer,
allocatable :: aero_removed_action(:)
3122 integer(kind=8),
allocatable :: aero_removed_other_id(:)
3123 integer,
allocatable :: aero_component_particle_num(:)
3124 integer,
allocatable :: aero_component_source_num(:)
3125 integer,
allocatable :: aero_component_len(:)
3126 integer,
allocatable :: aero_component_start_ind(:)
3127 integer,
allocatable :: aero_particle_n_primary_parts(:)
3128 real(kind=
dp),
allocatable :: aero_component_create_time(:)
3134 status = nf90_inq_dimid(ncid,
"aero_particle", dimid_aero_particle)
3135 if (status == nf90_ebaddim)
then
3140 call pmc_nc_check(status)
3141 call pmc_nc_check(nf90_inquire_dimension(ncid, dimid_aero_particle, &
3145 "aero_particle_mass")
3146 call pmc_nc_read_integer_1d(ncid, aero_particle_n_primary_parts, &
3147 "aero_particle_n_primary_parts")
3148 call pmc_nc_read_integer_1d(ncid, aero_component_particle_num, &
3149 "aero_component_particle_num")
3150 call pmc_nc_read_integer_1d(ncid, aero_component_source_num, &
3151 "aero_component_source_num")
3152 call pmc_nc_read_real_1d(ncid, aero_component_create_time, &
3153 "aero_component_create_time")
3154 call pmc_nc_read_integer_1d(ncid, aero_component_len,
"aero_component_len")
3155 call pmc_nc_read_integer_1d(ncid, aero_component_start_ind, &
3156 "aero_component_start_ind")
3157 call pmc_nc_read_integer_1d(ncid, aero_particle_weight_group, &
3158 "aero_particle_weight_group")
3159 call pmc_nc_read_integer_1d(ncid, aero_particle_weight_class, &
3160 "aero_particle_weight_class")
3161 call pmc_nc_read_real_2d(ncid, aero_absorb_cross_sect, &
3162 "aero_absorb_cross_sect", must_be_present=.false.)
3163 call pmc_nc_read_real_2d(ncid, aero_scatter_cross_sect, &
3164 "aero_scatter_cross_sect", must_be_present=.false.)
3165 call pmc_nc_read_real_2d(ncid, aero_asymmetry, &
3166 "aero_asymmetry", must_be_present=.false.)
3167 call pmc_nc_read_real_2d(ncid, aero_refract_shell_real, &
3168 "aero_refract_shell_real", must_be_present=.false.)
3169 call pmc_nc_read_real_2d(ncid, aero_refract_shell_imag, &
3170 "aero_refract_shell_imag", must_be_present=.false.)
3171 call pmc_nc_read_real_2d(ncid, aero_refract_core_real, &
3172 "aero_refract_core_real", must_be_present=.false.)
3173 call pmc_nc_read_real_2d(ncid, aero_refract_core_imag, &
3174 "aero_refract_core_imag", must_be_present=.false.)
3175 call pmc_nc_read_real_1d(ncid, aero_core_vol, &
3176 "aero_core_vol", must_be_present=.false.)
3177 call pmc_nc_read_integer_1d(ncid, aero_water_hyst_leg, &
3178 "aero_water_hyst_leg")
3179 call pmc_nc_read_real_1d(ncid, aero_num_conc, &
3181 call pmc_nc_read_integer64_1d(ncid, aero_id, &
3183 call pmc_nc_read_integer_1d(ncid, aero_frozen, &
3185 call pmc_nc_read_real_1d(ncid, aero_imf_temperature, &
3186 "aero_imf_temperature")
3187 call pmc_nc_read_real_1d(ncid, aero_ice_density, &
3188 "aero_ice_density", must_be_present=.true.)
3189 call pmc_nc_read_real_1d(ncid, aero_ice_shape_phi, &
3190 "aero_ice_shape_phi", must_be_present=.true.)
3191 call pmc_nc_read_real_1d(ncid, aero_least_create_time, &
3192 "aero_least_create_time")
3193 call pmc_nc_read_real_1d(ncid, aero_greatest_create_time, &
3194 "aero_greatest_create_time")
3199 do i_part = 1,n_part
3202 aero_particle%n_primary_parts = aero_particle_n_primary_parts(i_part)
3203 if (
allocated(aero_particle%component)) &
3204 deallocate(aero_particle%component)
3205 allocate(aero_particle%component(aero_component_len(i_part)))
3206 do i_comp = 1,aero_component_len(i_part)
3207 aero_particle%component(i_comp)%source_id = &
3208 aero_component_source_num(aero_component_start_ind(i_part) &
3210 aero_particle%component(i_comp)%create_time = &
3211 aero_component_create_time(aero_component_start_ind(i_part) &
3214 aero_particle%weight_group = aero_particle_weight_group(i_part)
3215 aero_particle%weight_class = aero_particle_weight_class(i_part)
3216 if (
size(aero_absorb_cross_sect, 1) == n_part)
then
3217 aero_particle%absorb_cross_sect = aero_absorb_cross_sect(i_part, :)
3219 if (
size(aero_scatter_cross_sect, 1) == n_part)
then
3220 aero_particle%scatter_cross_sect = &
3221 aero_scatter_cross_sect(i_part, :)
3223 if (
size(aero_asymmetry, 1) == n_part)
then
3224 aero_particle%asymmetry = aero_asymmetry(i_part, :)
3226 if ((
size(aero_refract_shell_real, 1) == n_part) &
3227 .and. (
size(aero_refract_shell_imag, 1) == n_part))
then
3228 aero_particle%refract_shell = &
3229 cmplx(aero_refract_shell_real(i_part, :), &
3230 aero_refract_shell_imag(i_part, :), kind=
dc)
3232 if ((
size(aero_refract_core_real, 1) == n_part) &
3233 .and. (
size(aero_refract_core_imag, 1) == n_part))
then
3234 aero_particle%refract_core = cmplx(aero_refract_core_real( &
3235 i_part, :), aero_refract_core_imag(i_part, :), kind=
dc)
3237 if (
size(aero_core_vol) == n_part)
then
3238 aero_particle%core_vol = aero_core_vol(i_part)
3240 aero_particle%water_hyst_leg = aero_water_hyst_leg(i_part)
3241 aero_particle%id = aero_id(i_part)
3242 if (aero_frozen(i_part) == 1)
then
3243 aero_particle%frozen = .true.
3245 aero_particle%frozen = .false.
3247 aero_particle%imf_temperature = aero_imf_temperature(i_part)
3248 aero_particle%den_ice = aero_ice_density(i_part)
3249 aero_particle%ice_shape_phi = aero_ice_shape_phi(i_part)
3250 aero_particle%least_create_time = aero_least_create_time(i_part)
3251 aero_particle%greatest_create_time = aero_greatest_create_time(i_part)
3262 call pmc_nc_read_integer_1d(ncid, aero_removed_id, &
3263 "aero_removed_id", must_be_present=.false.)
3264 call pmc_nc_read_integer_1d(ncid, aero_removed_action, &
3265 "aero_removed_action", must_be_present=.false.)
3266 call pmc_nc_read_integer64_1d(ncid, aero_removed_other_id, &
3267 "aero_removed_other_id", must_be_present=.false.)
3269 n_info_item =
size(aero_removed_id)
3270 if (n_info_item >= 1)
then
3271 if ((n_info_item > 1) &
3272 .or. ((n_info_item == 1) .and. (aero_removed_id(1) /= 0)))
then
3275 do i_remove = 1,n_info_item
3276 aero_state%aero_info_array%aero_info(i_remove)%id &
3277 = aero_removed_id(i_remove)
3278 aero_state%aero_info_array%aero_info(i_remove)%action &
3279 = aero_removed_action(i_remove)
3280 aero_state%aero_info_array%aero_info(i_remove)%other_id &
3281 = aero_removed_other_id(i_remove)
3298 type(
bin_grid_t),
optional,
intent(in) :: bin_grid
3300 logical,
optional,
intent(in) :: all_procs_same
3303 aero_data, aero_state%valid_sort,
size(aero_state%awa%weight, 1), &
3304 size(aero_state%awa%weight, 2), bin_grid, all_procs_same)
3305 aero_state%valid_sort = .true.
3319 logical,
parameter :: continue_on_error = .false.
3323 if (aero_state%valid_sort)
then
3325 aero_data,
size(aero_state%awa%weight, 1), &
3326 size(aero_state%awa%weight, 2), continue_on_error)
3335 subroutine aero_state_initialize(aero_state, aero_data, camp_core)
3342 type(camp_core_t),
intent(in) :: camp_core
3344 select type( aero_rep => aero_data%aero_rep_ptr)
3345 type is(aero_rep_single_particle_t)
3347 call camp_core%initialize_update_object(aero_rep, &
3348 aero_state%update_number)
3350 call die_msg(927605681,
"Wrong aerosol representation type")
3353 end subroutine aero_state_initialize
3384 aero_state%apa%particle(i_part))
3400 integer :: wavelength
3403 real(kind=
dp) :: b_scat
3411 b_scat = b_scat + num_concs(i_part) &
3412 * aero_state%apa%particle(i_part)%scatter_cross_sect(wavelength)
3430 integer :: wavelength
3433 real(kind=
dp) :: b_abs
3441 b_abs = b_abs + num_concs(i_part) &
3442 * aero_state%apa%particle(i_part)%absorb_cross_sect(wavelength)
3454 bin_values, i_wavelength)
3463 real(kind=
dp),
allocatable :: bin_values(:)
3465 integer :: i_wavelength
3469 integer :: i_bin, i_part
3480 * aero_state%apa%particle(i_part)%scatter_cross_sect( &
3491 bin_values, i_wavelength)
3500 real(kind=
dp),
allocatable :: bin_values(:)
3502 integer :: i_wavelength
3506 integer :: i_bin, i_part
3517 * aero_state%apa%particle(i_part)%absorb_cross_sect( &
3540 bin_grid, bin_values, d_alpha, d_gamma, chi, include, exclude, group, &
3550 real(kind=
dp),
allocatable,
intent(in) :: bin_values(:)
3552 real(kind=
dp),
allocatable,
intent(inout) :: d_alpha(:)
3554 real(kind=
dp),
allocatable,
intent(inout) :: d_gamma(:)
3556 real(kind=
dp),
allocatable,
intent(inout) :: chi(:)
3558 character(len=*),
optional :: include(:)
3560 character(len=*),
optional :: exclude(:)
3562 character(len=*),
optional :: group(:)
3564 character(len=*),
optional :: groups(:,:)
3572 if (
allocated(d_alpha))
deallocate(d_alpha)
3573 if (
allocated(d_gamma))
deallocate(d_gamma)
3574 if (
allocated(chi))
deallocate(chi)
3584 aero_state_size_range = aero_state
3593 d_alpha(i_bin), d_gamma(i_bin), chi(i_bin), include, exclude, &
3612 aero_state_to = aero_state_from
3618 aero_state_to%n_part_ideal = aero_state_from%n_part_ideal
3620 aero_state_to%update_number = aero_state_from%update_number