56 real(kind=
dp),
allocatable :: temp_time(:)
58 real(kind=
dp),
allocatable :: temp(:)
61 real(kind=
dp),
allocatable :: pressure_time(:)
63 real(kind=
dp),
allocatable :: pressure(:)
66 real(kind=
dp),
allocatable :: height_time(:)
68 real(kind=
dp),
allocatable :: height(:)
71 real(kind=
dp),
allocatable :: gas_emission_time(:)
73 real(kind=
dp),
allocatable :: gas_emission_rate_scale(:)
78 real(kind=
dp),
allocatable :: gas_dilution_time(:)
80 real(kind=
dp),
allocatable :: gas_dilution_rate(:)
85 real(kind=
dp),
allocatable :: aero_emission_time(:)
87 real(kind=
dp),
allocatable :: aero_emission_rate_scale(:)
92 real(kind=
dp),
allocatable :: aero_dilution_time(:)
94 real(kind=
dp),
allocatable :: aero_dilution_rate(:)
99 integer :: loss_function_type
117 real(kind=
dp),
intent(in) :: time
119 env_state%temp =
interp_1d(scenario%temp_time, scenario%temp, time)
120 env_state%pressure =
interp_1d(scenario%pressure_time, &
121 scenario%pressure, time)
122 env_state%height =
interp_1d(scenario%height_time, scenario%height, time)
123 env_state%elapsed_time = time
125 env_state%solar_zenith_angle = 0d0
140 real(kind=
dp),
intent(in) :: time
143 real(kind=
dp) :: pmv_old, pmv_new
145 real(kind=
dp) :: pressure_old
147 real(kind=
dp) :: temp_old
153 pressure_old = env_state%pressure
154 temp_old = env_state%temp
156 env_state%temp =
interp_1d(scenario%temp_time, scenario%temp, time)
157 env_state%pressure =
interp_1d(scenario%pressure_time, &
158 scenario%pressure, time)
160 pmv_new = pmv_old * env_state%pressure / pressure_old
163 env_state%height =
interp_1d(scenario%height_time, scenario%height, time)
164 env_state%elapsed_time = time
208 old_env_state, gas_data, gas_state)
213 real(kind=
dp),
intent(in) :: delta_t
223 real(kind=
dp) :: emission_rate_scale, dilution_rate, p
228 scenario%gas_emission_time, scenario%gas_emission_rate_scale, &
229 env_state%elapsed_time, emissions, emission_rate_scale)
231 p = emission_rate_scale * delta_t / env_state%height
236 scenario%gas_dilution_time, scenario%gas_dilution_rate, &
237 env_state%elapsed_time, background, dilution_rate)
238 p = exp(- dilution_rate * delta_t)
239 if (env_state%height > old_env_state%height)
then
240 p = p * old_env_state%height / env_state%height
257 old_env_state, aero_data, aero_state, n_emit, n_dil_in, n_dil_out, &
258 allow_doubling, allow_halving)
263 real(kind=
dp),
intent(in) :: delta_t
273 integer,
intent(out) :: n_emit
275 integer,
intent(out) :: n_dil_in
277 integer,
intent(out) :: n_dil_out
279 logical,
intent(in) :: allow_doubling
281 logical,
intent(in) :: allow_halving
283 real(kind=
dp) :: emission_rate_scale, dilution_rate, p
289 scenario%aero_emission_time, scenario%aero_emission_rate_scale, &
290 env_state%elapsed_time, emissions, emission_rate_scale)
291 p = emission_rate_scale * delta_t / env_state%height
293 emissions, p, env_state%elapsed_time, allow_doubling, allow_halving, &
298 scenario%aero_dilution_time, scenario%aero_dilution_rate, &
299 env_state%elapsed_time, background, dilution_rate)
300 p = exp(- dilution_rate * delta_t)
301 if (env_state%height > old_env_state%height)
then
302 p = p * old_env_state%height / env_state%height
306 aero_data, 1d0 - p, aero_info_dilution)
310 background, 1d0 - p, env_state%elapsed_time, allow_doubling, &
311 allow_halving, n_dil_in)
318 call aero_weight_array_scale(aero_state%awa, &
319 old_env_state%temp * env_state%pressure &
320 / (env_state%temp * old_env_state%pressure))
331 old_env_state, bin_grid, aero_data, aero_binned)
336 real(kind=
dp),
intent(in) :: delta_t
346 type(aero_binned_t),
intent(inout) :: aero_binned
348 real(kind=
dp) :: emission_rate_scale, dilution_rate, p
350 type(aero_binned_t) :: emissions_binned, background_binned
354 scenario%aero_emission_time, scenario%aero_emission_rate_scale, &
355 env_state%elapsed_time, emissions, emission_rate_scale)
356 call aero_binned_add_aero_dist(emissions_binned, bin_grid, aero_data, &
358 p = emission_rate_scale * delta_t / env_state%height
359 call aero_binned_add_scaled(aero_binned, emissions_binned, p)
363 scenario%aero_dilution_time, scenario%aero_dilution_rate, &
364 env_state%elapsed_time, background, dilution_rate)
365 call aero_binned_add_aero_dist(background_binned, bin_grid, aero_data, &
367 p = exp(- dilution_rate * delta_t)
368 if (env_state%height > old_env_state%height)
then
369 p = p * old_env_state%height / env_state%height
371 call aero_binned_scale(aero_binned, p)
372 call aero_binned_add_scaled(aero_binned, background_binned, 1d0 - p)
380 aero_data, env_state)
385 real(kind=
dp),
intent(in) :: vol
387 real(kind=
dp),
intent(in) :: density
406 aero_data, env_state)
410 aero_data, env_state) &
412 aero_data, env_state)
414 call die_msg(201594391,
"Unknown loss function id: " &
429 real(kind=
dp),
intent(in) :: vol
431 real(kind=
dp),
intent(in) :: density
440 real(kind=
dp) :: density_air
441 real(kind=
dp) :: visc_d, visc_k
442 real(kind=
dp) :: gas_speed, gas_mean_free_path
443 real(kind=
dp) :: knud, cunning
444 real(kind=
dp) :: grav
445 real(kind=
dp) :: r_s, r_a
446 real(kind=
dp) :: alpha, beta, gamma, a, eps_0
447 real(kind=
dp) :: diff_p
448 real(kind=
dp) :: von_karman
449 real(kind=
dp) :: st, sc, u_star
450 real(kind=
dp) :: e_b, e_im, e_in, r1
451 real(kind=
dp) :: u_mean, z_ref, z_rough
466 density_air = (
const%air_molec_weight * env_state%pressure) &
467 / (
const%univ_gas_const * env_state%temp)
469 visc_d = 1.8325d-5 * (416.16 / (env_state%temp + 120.0d0)) &
470 * (env_state%temp / 296.16)**1.5d0
472 visc_k = visc_d / density_air
475 sqrt((8.0d0 *
const%boltzmann * env_state%temp *
const%avagadro) / &
478 gas_mean_free_path = (2.0d0 * visc_d) / (density_air * gas_speed)
480 knud = (2.0d0 * gas_mean_free_path) / d_p
482 cunning = 1.0d0 + knud * (1.257d0 + 0.4d0 * exp(-1.1d0 / knud))
486 v_s = (density * d_p**2.0d0 * grav * cunning) / (18.0d0 * visc_d)
490 u_star = .4d0 * u_mean / log(z_ref / z_rough)
491 r_a = (1.0d0 / (.4d0 * u_star)) * log(z_ref / z_rough)
493 diff_p = (
const%boltzmann * env_state%temp * cunning) / &
494 (3.d0 *
const%pi * visc_d * d_p)
500 e_in = .5d0 * (d_p / a)**2.0d0
503 st = (v_s * u_star) / (grav * a)
504 e_im = (st / (alpha + st))**beta
511 r_s = 1.0d0 / (eps_0 * u_star * (e_b + e_in + e_im) * r1)
514 v_d = v_s + (1.0d0 / (r_a + r_s + r_a * r_s * v_s))
530 real(kind=
dp),
intent(in) :: vol
537 integer,
parameter :: n_sample = 3
539 real(kind=
dp) :: d, d_min, d_max, loss
542 d_min = minval(aero_data%density)
543 d_max = maxval(aero_data%density)
576 integer,
parameter :: n_sample = 3
578 real(kind=
dp),
parameter :: over_scale = 2d0
580 real(kind=
dp) :: v_low, v_high, vol, r, r_max
590 r_max = max(r_max, r)
592 loss_max(b) = r_max * over_scale
613 real(kind=
dp),
intent(in) :: delta_t
621 integer :: c, b, s, i_part
622 real(kind=
dp) :: over_rate, over_prob, rand_real, rand_geom
629 do i_part = aero_state%apa%n_part, 1, -1
631 aero_data, aero_state, env_state, i_part, 1d0)
638 if (.not. aero_state%aero_sorted%removal_rate_bounds_valid)
then
640 aero_state%aero_sorted%bin_grid, aero_data, env_state, &
641 aero_state%aero_sorted%removal_rate_max)
642 aero_state%aero_sorted%removal_rate_bounds_valid = .true.
645 do c = 1,aero_sorted_n_class(aero_state%aero_sorted)
646 do b = 1,aero_sorted_n_bin(aero_state%aero_sorted)
647 over_rate = aero_state%aero_sorted%removal_rate_max(b)
648 if (delta_t * over_rate <= 0d0) cycle
649 over_prob = 1d0 - exp(-delta_t * over_rate)
652 do s = aero_state%aero_sorted%size_class%inverse(b, c)%n_entry, &
655 aero_state%aero_sorted%size_class%inverse(b, c)%entry(s)
657 aero_data, aero_state, env_state, i_part, 1d0)
661 s = aero_state%aero_sorted%size_class%inverse(b, c)%n_entry + 1
664 if (rand_real <= 0d0)
exit
665 rand_geom = -log(rand_real) / (delta_t * over_rate) + 1d0
666 if (rand_geom >= real(s, kind=
dp))
exit
667 s = s - floor(rand_geom)
673 aero_state%aero_sorted%size_class%inverse(b, c)%entry(s)
675 aero_data, aero_state, env_state, i_part, over_prob)
693 aero_data, aero_state, env_state, i_part, over_prob)
698 real(kind=
dp),
intent(in) :: delta_t
706 integer,
intent(in) :: i_part
708 real(kind=
dp),
intent(in) :: over_prob
710 real(kind=
dp) :: prob, rate, vol, density
711 type(aero_info_t) :: aero_info
713 vol = aero_particle_volume(aero_state%apa%particle(i_part))
714 density = aero_particle_density(aero_state%apa%particle(i_part), aero_data)
716 prob = 1d0 - exp(-delta_t * rate)
718 "particle loss upper bound estimation is too tight: " &
723 aero_info%id = aero_state%apa%particle(i_part)%id
724 aero_info%action = aero_info_dilution
725 aero_info%other_id = 0
739 integer,
intent(in) :: aero_mode_type
752 subroutine spec_file_read_scenario(file, gas_data, aero_data, scenario)
763 character(len=PMC_MAX_FILENAME_LEN) :: sub_filename
765 character(len=SPEC_LINE_MAX_VAR_LEN) :: function_name
811 scenario%temp_time, scenario%temp)
818 scenario%pressure_time, scenario%pressure)
825 scenario%height_time, scenario%height)
831 call spec_file_read_gas_states_times_rates(sub_file, gas_data, &
832 scenario%gas_emission_time, scenario%gas_emission_rate_scale, &
833 scenario%gas_emission)
839 call spec_file_read_gas_states_times_rates(sub_file, gas_data, &
840 scenario%gas_dilution_time, scenario%gas_dilution_rate, &
841 scenario%gas_background)
847 call spec_file_read_aero_dists_times_rates(sub_file, aero_data, &
848 scenario%aero_emission_time, scenario%aero_emission_rate_scale, &
849 scenario%aero_emission)
855 call spec_file_read_aero_dists_times_rates(sub_file, aero_data, &
856 scenario%aero_dilution_time, scenario%aero_dilution_rate, &
857 scenario%aero_background)
862 if (trim(function_name) ==
'none')
then
864 else if (trim(function_name) ==
'constant')
then
866 else if (trim(function_name) ==
'volume')
then
868 else if (trim(function_name) ==
'drydep')
then
870 else if (trim(function_name) ==
'chamber')
then
872 call spec_file_read_chamber(file, scenario%chamber)
875 "Unknown loss function type: " // trim(function_name))
878 end subroutine spec_file_read_scenario
989 integer :: total_size, i, n
1008 if (
allocated(val%gas_emission_time))
then
1009 do i = 1,
size(val%gas_emission)
1010 total_size = total_size &
1014 if (
allocated(val%gas_dilution_time))
then
1015 do i = 1,
size(val%gas_background)
1016 total_size = total_size &
1020 if (
allocated(val%aero_emission_time))
then
1021 do i = 1,
size(val%aero_emission)
1022 total_size = total_size &
1026 if (
allocated(val%aero_dilution_time))
then
1027 do i = 1,
size(val%aero_background)
1028 total_size = total_size &
1043 character,
intent(inout) :: buffer(:)
1045 integer,
intent(inout) :: position
1050 integer :: prev_position, i
1052 prev_position = position
1065 val%aero_emission_rate_scale)
1070 if (
allocated(val%gas_emission_time))
then
1071 do i = 1,
size(val%gas_emission)
1075 if (
allocated(val%gas_dilution_time))
then
1076 do i = 1,
size(val%gas_background)
1080 if (
allocated(val%aero_emission_time))
then
1081 do i = 1,
size(val%aero_emission)
1085 if (
allocated(val%aero_dilution_time))
then
1086 do i = 1,
size(val%aero_background)
1102 character,
intent(inout) :: buffer(:)
1104 integer,
intent(inout) :: position
1109 integer :: prev_position, i
1111 prev_position = position
1120 val%gas_emission_rate_scale)
1125 val%aero_emission_rate_scale)
1130 if (
allocated(val%gas_emission))
deallocate(val%gas_emission)
1131 if (
allocated(val%gas_background))
deallocate(val%gas_background)
1132 if (
allocated(val%aero_emission))
deallocate(val%aero_emission)
1133 if (
allocated(val%aero_background))
deallocate(val%aero_background)
1134 if (
allocated(val%gas_emission_time))
then
1135 allocate(val%gas_emission(
size(val%gas_emission_time)))
1136 do i = 1,
size(val%gas_emission)
1140 if (
allocated(val%gas_dilution_time))
then
1141 allocate(val%gas_background(
size(val%gas_dilution_time)))
1142 do i = 1,
size(val%gas_background)
1144 val%gas_background(i))
1147 if (
allocated(val%aero_emission_time))
then
1148 allocate(val%aero_emission(
size(val%aero_emission_time)))
1149 do i = 1,
size(val%aero_emission)
1153 if (
allocated(val%aero_dilution_time))
then
1154 allocate(val%aero_background(
size(val%aero_dilution_time)))
1155 do i = 1,
size(val%aero_background)
1157 val%aero_background(i))