33 use camp_env_state,
only: camp_env_state_t =>
env_state_t
35 #ifdef PMC_USE_SUNDIALS
52 real(kind=
dp) :: t_max
54 real(kind=
dp) :: t_output
56 real(kind=
dp) :: t_progress
58 real(kind=
dp) :: del_t
60 character(len=300) :: output_prefix
62 integer :: coag_kernel_type
64 integer :: nucleate_type
66 integer :: nucleate_source
68 integer :: nucleate_weight_class
70 logical :: do_coagulation
72 logical :: do_nucleation
74 logical :: do_immersion_freezing
76 integer :: immersion_freezing_scheme_type
78 real(kind=
dp) :: inas_a
80 real(kind=
dp) :: inas_b
82 real(kind=
dp) :: freezing_rate
85 logical :: do_freezing_naive
87 logical :: allow_doubling
89 logical :: allow_halving
91 logical :: do_condensation
97 logical :: do_select_weighting
99 integer :: weighting_type
101 real(kind=
dp) :: weighting_exponent
107 real(kind=
dp) :: t_wall_start
109 logical :: record_removals
111 logical :: do_parallel
113 integer :: output_type
115 real(kind=
dp) :: mix_timescale
117 logical :: gas_average
119 logical :: env_average
121 integer :: parallel_coag_type
123 logical :: do_camp_chem
127 character(len=PMC_UUID_LEN) :: uuid
136 subroutine run_part(scenario, env_state, aero_data, aero_state, gas_data, &
137 gas_state, run_part_opt, camp_core, photolysis)
139 subroutine run_part(scenario, env_state, aero_data, aero_state, gas_data, &
140 gas_state, run_part_opt)
159 type(camp_core_t),
pointer,
intent(inout),
optional :: camp_core
161 type(photolysis_t),
pointer,
intent(inout),
optional :: photolysis
164 real(kind=
dp) :: time, pre_time, pre_del_t, prop_done
165 real(kind=
dp) :: last_output_time, last_progress_time
166 integer :: rank, n_proc, pre_index, ncid
167 integer :: pre_i_repeat
168 integer :: n_samp, n_coag, n_emit, n_dil_in, n_dil_out, n_nuc
169 integer :: progress_n_samp, progress_n_coag
170 integer :: progress_n_emit, progress_n_dil_in, progress_n_dil_out
171 integer :: progress_n_nuc, n_part_before
172 integer :: global_n_part, global_n_samp, global_n_coag
173 integer :: global_n_emit, global_n_dil_in, global_n_dil_out
174 integer :: global_n_nuc
175 logical :: do_output, do_state, do_state_netcdf, do_progress, did_coag
176 real(kind=
dp) :: t_start, t_wall_now, t_wall_elapsed, t_wall_remain
178 integer :: n_time, i_time, pre_i_time
179 integer :: i_state, i_state_netcdf, i_output
180 integer :: i_cur, i_next
193 progress_n_dil_in = 0
194 progress_n_dil_out = 0
198 "del_t", run_part_opt%del_t)
200 "del_t", run_part_opt%del_t)
202 "del_t", run_part_opt%del_t)
204 if (run_part_opt%do_mosaic)
then
205 call mosaic_init(env_state, aero_data, run_part_opt%del_t, &
206 run_part_opt%do_optical)
207 if (run_part_opt%do_optical)
then
209 aero_state, gas_data, gas_state)
214 if (run_part_opt%t_output > 0d0)
then
216 run_part_opt%output_type, aero_data, aero_state, gas_data, &
217 gas_state, env_state, i_state, time, run_part_opt%del_t, &
218 run_part_opt%i_repeat, run_part_opt%record_removals, &
219 run_part_opt%do_optical, run_part_opt%uuid)
220 call aero_info_array_zero(aero_state%aero_info_array)
224 run_part_opt%allow_doubling, &
225 run_part_opt%allow_halving, initial_state_warning=.true.)
227 t_start = env_state%elapsed_time
228 last_output_time = time
229 last_progress_time = time
230 n_time = nint(run_part_opt%t_max / run_part_opt%del_t)
235 if (run_part_opt%i_repeat == 1)
then
240 prop_done = real(run_part_opt%i_repeat - 1, kind=
dp) &
241 / real(run_part_opt%n_repeat, kind=
dp)
242 t_wall_elapsed = t_wall_now - run_part_opt%t_wall_start
243 t_wall_remain = (1d0 - prop_done) / prop_done &
247 global_n_part, 0, 0, 0, 0, 0, t_wall_elapsed, t_wall_remain)
253 gas_data, gas_state, run_part_opt, &
255 camp_core, photolysis, &
257 i_cur, i_next, t_start, last_output_time, last_progress_time, &
258 i_output, progress_n_samp, progress_n_coag, progress_n_emit, &
259 progress_n_dil_in, progress_n_dil_out, progress_n_nuc)
261 if (run_part_opt%do_mosaic)
then
271 n_emit, n_dil_in, n_dil_out, n_nuc, t_wall_elapsed, t_wall_remain)
274 integer,
intent(in) :: i_repeat
276 real(kind=
dp),
intent(in) :: t_sim_elapsed
278 integer,
intent(in) :: n_part
280 integer,
intent(in) :: n_coag
282 integer,
intent(in) :: n_emit
284 integer,
intent(in) :: n_dil_in
286 integer,
intent(in) :: n_dil_out
288 integer,
intent(in) :: n_nuc
290 real(kind=
dp),
intent(in) :: t_wall_elapsed
292 real(kind=
dp),
intent(in) :: t_wall_remain
294 write(*,
'(a6,a1,a6,a1,a7,a1,a7,a1,a7,a1,a8,a1,a9,a1,a7,a1,a6,a1,a6)') &
295 "repeat",
" ",
"t_sim",
" ",
"n_part",
" ",
"n_coag",
" ", &
296 "n_emit",
" ",
"n_dil_in",
" ",
"n_dil_out",
" ",
"n_nuc",
" ", &
297 "t_wall",
" ",
"t_rem"
298 write(*,
'(a6,a1,a6,a1,a7,a1,a7,a1,a7,a1,a8,a1,a9,a1,a7,a1,a6,a1,a6)') &
368 character,
intent(inout) :: buffer(:)
370 integer,
intent(inout) :: position
375 integer :: prev_position
377 prev_position = position
391 val%immersion_freezing_scheme_type)
430 character,
intent(inout) :: buffer(:)
432 integer,
intent(inout) :: position
437 integer :: prev_position
439 prev_position = position
488 aero_state_init, gas_data, gas_state_init, env_state_init, &
489 aero_dist_init, scenario, &
491 camp_core, photolysis, aero_state, &
493 n_part, rand_init, do_init_equilibrate, do_restart)
510 type(aero_dist_t),
intent(inout) :: aero_dist_init
515 type(camp_core_t),
pointer :: camp_core
517 type(photolysis_t),
pointer :: photolysis
522 real(kind=
dp),
intent(inout) :: n_part
524 integer,
intent(out) :: rand_init
526 logical,
intent(out) :: do_init_equilibrate
528 logical,
intent(out) :: do_restart
530 integer :: i_repeat, i_group
531 logical :: read_aero_weight_classes
532 character(len=PMC_MAX_FILENAME_LEN) :: restart_filename
533 integer :: dummy_index, dummy_i_repeat
534 real(kind=
dp) :: dummy_time, dummy_del_t
535 character(len=PMC_MAX_FILENAME_LEN) :: sub_filename
537 character(len=PMC_MAX_FILENAME_LEN) :: camp_config_filename, &
538 tchem_gas_filename, tchem_aero_filename, tchem_numerics_filename
539 integer :: n_grid_cells
542 run_part_opt%output_prefix)
550 if (.not. do_restart)
then
552 run_part_opt%do_select_weighting)
553 read_aero_weight_classes = .false.
554 if (run_part_opt%do_select_weighting)
then
555 call spec_file_read_aero_state_weighting_type(file, &
556 run_part_opt%weighting_type, run_part_opt%weighting_exponent)
557 if (run_part_opt%weighting_type &
559 read_aero_weight_classes = .true.
563 run_part_opt%weighting_exponent = 0.0d0
573 if (run_part_opt%do_camp_chem)
then
576 camp_core => camp_core_t(camp_config_filename)
577 call camp_core%initialize()
578 photolysis => photolysis_t(camp_core)
581 'cannot do camp chem, CAMP support not compiled in')
586 if (run_part_opt%do_tchem)
then
593 tchem_numerics_filename)
597 if (run_part_opt%do_tchem)
then
600 call pmc_tchem_initialize(tchem_gas_filename, tchem_aero_filename, &
601 tchem_numerics_filename, gas_data, aero_data, n_grid_cells)
606 call input_state(restart_filename, dummy_index, dummy_time, &
607 dummy_del_t, dummy_i_repeat, run_part_opt%uuid, aero_data, &
608 aero_state_init, gas_data, gas_state_init, env_state_init)
611 if (.not. do_restart)
then
612 env_state_init%elapsed_time = 0d0
614 if (.not. (run_part_opt%do_camp_chem .or. run_part_opt%do_tchem))
then
617 call spec_file_read_gas_data(sub_file, gas_data)
619 else if (run_part_opt%do_camp_chem)
then
621 call gas_data_initialize(gas_data, camp_core)
626 call spec_file_read_gas_state(sub_file, gas_data, gas_state_init)
629 if (.not. run_part_opt%do_camp_chem)
then
632 call spec_file_read_aero_data(sub_file, aero_data)
635 else if (run_part_opt%do_tchem)
then
638 call spec_file_read_aero_data(sub_file, aero_data)
642 call aero_data_initialize(aero_data, camp_core)
643 call aero_state_initialize(aero_state, aero_data, camp_core)
646 call spec_file_read_fractal(file, aero_data%fractal)
650 call spec_file_read_aero_dist(sub_file, aero_data, &
651 read_aero_weight_classes, aero_dist_init)
655 call spec_file_read_scenario(file, gas_data, aero_data, &
656 read_aero_weight_classes, scenario)
657 call spec_file_read_env_state(file, env_state_init)
660 run_part_opt%do_coagulation)
661 if (run_part_opt%do_coagulation)
then
662 call spec_file_read_coag_kernel_type(file, run_part_opt%coag_kernel_type)
665 env_state_init%additive_kernel_coefficient)
672 run_part_opt%do_condensation)
673 #ifndef PMC_USE_SUNDIALS
675 run_part_opt%do_condensation .eqv. .false., &
676 "cannot use condensation, SUNDIALS support is not compiled in")
678 do_init_equilibrate = .false.
679 if (run_part_opt%do_condensation)
then
687 'cannot use MOSAIC, support is not compiled in')
689 if (run_part_opt%do_mosaic .and. run_part_opt%do_condensation)
then
691 'cannot use MOSAIC and condensation simultaneously')
693 if (run_part_opt%do_mosaic)
then
695 run_part_opt%do_optical)
697 run_part_opt%do_optical = .false.
701 run_part_opt%do_nucleation)
702 if (run_part_opt%do_nucleation)
then
703 call spec_file_read_nucleate_type(file, aero_data, &
704 run_part_opt%nucleate_type, run_part_opt%nucleate_source, &
705 run_part_opt%nucleate_weight_class)
710 run_part_opt%do_immersion_freezing)
712 if (run_part_opt%do_immersion_freezing)
then
714 call spec_file_read_immersion_freezing_scheme_type(file, &
715 run_part_opt%immersion_freezing_scheme_type)
717 if (run_part_opt%immersion_freezing_scheme_type .eq. &
720 run_part_opt%freezing_rate)
723 if ((run_part_opt%immersion_freezing_scheme_type .eq. &
725 (run_part_opt%immersion_freezing_scheme_type .eq. &
728 run_part_opt%do_freezing_naive)
732 if (run_part_opt%immersion_freezing_scheme_type .eq.&
742 run_part_opt%allow_doubling)
744 run_part_opt%allow_halving)
746 run_part_opt%record_removals)
749 if (run_part_opt%do_parallel)
then
752 'cannot use parallel mode, support is not compiled in')
754 call spec_file_read_output_type(file, run_part_opt%output_type)
756 run_part_opt%mix_timescale)
758 run_part_opt%gas_average)
760 run_part_opt%env_average)
761 call spec_file_read_parallel_coag_type(file, &
762 run_part_opt%parallel_coag_type)
765 run_part_opt%mix_timescale = 0d0
766 run_part_opt%gas_average = .false.
767 run_part_opt%env_average = .false.
778 subroutine spec_file_read_parallel_coag_type(file, parallel_coag_type)
783 integer,
intent(out) :: parallel_coag_type
785 character(len=SPEC_LINE_MAX_VAR_LEN) :: parallel_coag_type_name
800 parallel_coag_type_name)
801 if (trim(parallel_coag_type_name) ==
'local')
then
803 elseif (trim(parallel_coag_type_name) ==
'dist')
then
807 "Unknown parallel coagulation type: " &
808 // trim(parallel_coag_type_name))
811 end subroutine spec_file_read_parallel_coag_type
817 gas_data, gas_state, run_part_opt, &
819 camp_core, photolysis, &
821 i_time, t_start, last_output_time, last_progress_time, i_output, &
822 progress_n_samp, progress_n_coag, progress_n_emit, progress_n_dil_in, &
823 progress_n_dil_out, progress_n_nuc)
841 type(camp_core_t),
pointer,
intent(inout),
optional :: camp_core
843 type(photolysis_t),
pointer,
intent(inout),
optional :: photolysis
846 integer,
intent(in) :: i_time
848 real(kind=
dp),
intent(in) :: t_start
850 real(kind=
dp),
intent(inout) :: last_output_time
852 real(kind=
dp),
intent(inout) :: last_progress_time
854 integer,
intent(inout) :: i_output
856 integer,
intent(inout) :: progress_n_samp
858 integer,
intent(inout) :: progress_n_coag
860 integer,
intent(inout) :: progress_n_emit
862 integer,
intent(inout) :: progress_n_dil_in
864 integer,
intent(inout) :: progress_n_dil_out
866 integer,
intent(inout) :: progress_n_nuc
868 real(kind=
dp) :: prop_done
869 integer :: n_samp, n_coag, n_emit, n_dil_in, n_dil_out, n_nuc
870 integer :: n_part_before
871 integer :: global_n_part, global_n_samp, global_n_coag
872 integer :: global_n_emit, global_n_dil_in, global_n_dil_out
873 integer :: global_n_nuc
874 logical :: do_output, do_state, do_state_netcdf, do_progress
875 real(kind=
dp) :: t_wall_now, t_wall_elapsed, t_wall_remain, time
878 type(camp_state_t),
pointer :: camp_state
879 type(camp_state_t),
pointer :: camp_pre_aero_state, camp_post_aero_state
880 type(camp_env_state_t) :: camp_env_state
883 time = i_time * run_part_opt%del_t
886 if (run_part_opt%do_camp_chem)
then
887 camp_env_state%temp = env_state%temp
888 camp_env_state%pressure = env_state%pressure
889 camp_state => camp_core%new_state_one_cell(camp_env_state)
890 camp_pre_aero_state => camp_core%new_state_one_cell(camp_env_state)
891 camp_post_aero_state => camp_core%new_state_one_cell(camp_env_state)
895 old_env_state = env_state
898 if (run_part_opt%do_nucleation)
then
900 call nucleate(run_part_opt%nucleate_type, &
901 run_part_opt%nucleate_source, run_part_opt%nucleate_weight_class, &
902 env_state, gas_data, aero_data, &
903 aero_state, gas_state, run_part_opt%del_t, &
904 run_part_opt%allow_doubling, run_part_opt%allow_halving)
907 progress_n_nuc = progress_n_nuc + n_nuc
909 if (run_part_opt%do_immersion_freezing)
then
911 run_part_opt%del_t, run_part_opt%immersion_freezing_scheme_type, &
912 run_part_opt%freezing_rate, run_part_opt%do_freezing_naive, &
913 run_part_opt%INAS_a, run_part_opt%INAS_b)
916 if (run_part_opt%do_coagulation)
then
917 if (run_part_opt%parallel_coag_type &
919 call mc_coag(run_part_opt%coag_kernel_type, env_state, &
920 aero_data, aero_state, run_part_opt%del_t, n_samp, n_coag)
921 elseif (run_part_opt%parallel_coag_type &
923 call mc_coag_dist(run_part_opt%coag_kernel_type, env_state, &
924 aero_data, aero_state, run_part_opt%del_t, n_samp, n_coag)
926 call die_msg(323011762,
"unknown parallel coagulation type: " &
929 progress_n_samp = progress_n_samp + n_samp
930 progress_n_coag = progress_n_coag + n_coag
933 #ifdef PMC_USE_SUNDIALS
934 if (run_part_opt%do_condensation)
then
936 env_state, run_part_opt%del_t)
941 env_state, old_env_state, gas_data, gas_state)
943 env_state, old_env_state, aero_data, aero_state, n_emit, &
944 n_dil_in, n_dil_out, run_part_opt%allow_doubling, &
945 run_part_opt%allow_halving)
946 progress_n_emit = progress_n_emit + n_emit
947 progress_n_dil_in = progress_n_dil_in + n_dil_in
948 progress_n_dil_out = progress_n_dil_out + n_dil_out
950 if (run_part_opt%do_camp_chem)
then
952 call pmc_camp_interface_solve(camp_core, camp_state, &
953 camp_pre_aero_state, camp_post_aero_state, env_state, &
954 aero_data, aero_state, gas_data, gas_state, photolysis, &
959 if (run_part_opt%do_tchem)
then
961 call pmc_tchem_interface_solve(env_state, aero_data, aero_state, &
962 gas_data, gas_state, run_part_opt%del_t)
966 if (run_part_opt%do_mosaic)
then
968 gas_state, run_part_opt%do_optical, run_part_opt%uuid)
971 if (run_part_opt%mix_timescale > 0d0)
then
973 run_part_opt%mix_timescale, aero_data)
975 if (run_part_opt%gas_average)
then
978 if (run_part_opt%gas_average)
then
983 run_part_opt%allow_doubling, &
984 run_part_opt%allow_halving, initial_state_warning=.false.)
987 if (run_part_opt%t_output > 0d0)
then
988 call check_event(time, run_part_opt%del_t, run_part_opt%t_output, &
989 last_output_time, do_output)
991 i_output = i_output + 1
993 run_part_opt%output_type, aero_data, aero_state, gas_data, &
994 gas_state, env_state, i_output, time, run_part_opt%del_t, &
995 run_part_opt%i_repeat, run_part_opt%record_removals, &
996 run_part_opt%do_optical, run_part_opt%uuid)
997 call aero_info_array_zero(aero_state%aero_info_array)
1001 if (.not. run_part_opt%record_removals)
then
1005 call aero_info_array_zero(aero_state%aero_info_array)
1008 if (run_part_opt%t_progress > 0d0)
then
1010 run_part_opt%t_progress, last_progress_time, do_progress)
1011 if (do_progress)
then
1024 prop_done = (real(run_part_opt%i_repeat - 1, kind=
dp) &
1025 + time / run_part_opt%t_max) &
1026 / real(run_part_opt%n_repeat, kind=
dp)
1027 t_wall_elapsed = t_wall_now - run_part_opt%t_wall_start
1028 t_wall_remain = (1d0 - prop_done) / prop_done * t_wall_elapsed
1030 global_n_part, global_n_coag, global_n_emit, &
1031 global_n_dil_in, global_n_dil_out, global_n_nuc, &
1032 t_wall_elapsed, t_wall_remain)
1039 progress_n_dil_in = 0
1040 progress_n_dil_out = 0
1051 gas_data, gas_state, run_part_opt, &
1053 camp_core, photolysis, &
1055 i_cur, i_next, t_start, last_output_time, last_progress_time, &
1056 i_output, progress_n_samp, progress_n_coag, progress_n_emit, &
1057 progress_n_dil_in, progress_n_dil_out, progress_n_nuc)
1075 type(camp_core_t),
pointer,
intent(inout),
optional :: camp_core
1077 type(photolysis_t),
pointer,
intent(inout),
optional :: photolysis
1080 integer,
intent(in) :: i_cur
1082 real(kind=
dp),
intent(in) :: t_start
1084 integer,
intent(in) :: i_next
1086 real(kind=
dp),
intent(inout) :: last_output_time
1088 real(kind=
dp),
intent(inout) :: last_progress_time
1090 integer,
intent(inout) :: i_output
1092 integer,
intent(inout) :: progress_n_samp
1094 integer,
intent(inout) :: progress_n_coag
1096 integer,
intent(inout) :: progress_n_emit
1098 integer,
intent(inout) :: progress_n_dil_in
1100 integer,
intent(inout) :: progress_n_dil_out
1102 integer,
intent(inout) :: progress_n_nuc
1106 do i_time = i_cur,i_next
1108 gas_data, gas_state, run_part_opt, &
1110 camp_core, photolysis, &
1112 i_time, t_start, last_output_time, last_progress_time, i_output, &
1113 progress_n_samp, progress_n_coag, progress_n_emit, &
1114 progress_n_dil_in, progress_n_dil_out, progress_n_nuc)
1123 aero_state_init, gas_data, gas_state_init, env_state_init, &
1124 aero_dist_init, scenario, &
1126 camp_core, photolysis, aero_state, &
1128 n_part, rand_init, do_init_equilibrate, do_restart)
1139 type(
gas_state_t),
intent(inout) :: gas_state_init
1141 type(
env_state_t),
intent(inout) :: env_state_init
1143 type(aero_dist_t),
intent(inout) :: aero_dist_init
1148 type(camp_core_t),
pointer :: camp_core
1150 type(photolysis_t),
pointer :: photolysis
1155 real(kind=
dp),
intent(inout) :: n_part
1157 integer,
intent(inout) :: rand_init
1159 logical,
intent(inout) :: do_init_equilibrate
1161 logical,
intent(inout) :: do_restart
1163 character,
allocatable :: buffer(:)
1164 integer :: buffer_size, max_buffer_size
1171 max_buffer_size = max_buffer_size &
1173 max_buffer_size = max_buffer_size &
1175 max_buffer_size = max_buffer_size &
1177 max_buffer_size = max_buffer_size &
1179 max_buffer_size = max_buffer_size &
1181 max_buffer_size = max_buffer_size &
1182 + pmc_mpi_pack_size_aero_dist(aero_dist_init)
1183 max_buffer_size = max_buffer_size &
1185 max_buffer_size = max_buffer_size &
1187 max_buffer_size = max_buffer_size &
1189 max_buffer_size = max_buffer_size &
1191 max_buffer_size = max_buffer_size &
1193 max_buffer_size = max_buffer_size &
1196 allocate(buffer(max_buffer_size))
1204 call pmc_mpi_pack_aero_dist(buffer, position, aero_dist_init)
1211 call assert(181905491, position <= max_buffer_size)
1212 buffer_size = position
1220 allocate(buffer(buffer_size))
1234 call pmc_mpi_unpack_aero_dist(buffer, position, aero_dist_init)
1241 call assert(143770146, position == buffer_size)