32 use camp_env_state,
only: camp_env_state_t =>
env_state_t
34 #ifdef PMC_USE_SUNDIALS
51 real(kind=
dp) :: t_max
53 real(kind=
dp) :: t_output
55 real(kind=
dp) :: t_progress
57 real(kind=
dp) :: del_t
59 character(len=300) :: output_prefix
61 integer :: coag_kernel_type
63 integer :: nucleate_type
65 integer :: nucleate_source
67 integer :: nucleate_weight_class
69 logical :: do_coagulation
71 logical :: do_nucleation
73 logical :: allow_doubling
75 logical :: allow_halving
77 logical :: do_condensation
83 logical :: do_select_weighting
85 integer :: weighting_type
87 real(kind=
dp) :: weighting_exponent
93 real(kind=
dp) :: t_wall_start
95 logical :: record_removals
97 logical :: do_parallel
99 integer :: output_type
101 real(kind=
dp) :: mix_timescale
103 logical :: gas_average
105 logical :: env_average
107 integer :: parallel_coag_type
109 logical :: do_camp_chem
113 character(len=PMC_UUID_LEN) :: uuid
122 subroutine run_part(scenario, env_state, aero_data, aero_state, gas_data, &
123 gas_state, run_part_opt, camp_core, photolysis)
125 subroutine run_part(scenario, env_state, aero_data, aero_state, gas_data, &
126 gas_state, run_part_opt)
145 type(camp_core_t),
pointer,
intent(inout),
optional :: camp_core
147 type(photolysis_t),
pointer,
intent(inout),
optional :: photolysis
150 real(kind=
dp) :: time, pre_time, pre_del_t, prop_done
151 real(kind=
dp) :: last_output_time, last_progress_time
152 integer :: rank, n_proc, pre_index, ncid
153 integer :: pre_i_repeat
154 integer :: n_samp, n_coag, n_emit, n_dil_in, n_dil_out, n_nuc
155 integer :: progress_n_samp, progress_n_coag
156 integer :: progress_n_emit, progress_n_dil_in, progress_n_dil_out
157 integer :: progress_n_nuc, n_part_before
158 integer :: global_n_part, global_n_samp, global_n_coag
159 integer :: global_n_emit, global_n_dil_in, global_n_dil_out
160 integer :: global_n_nuc
161 logical :: do_output, do_state, do_state_netcdf, do_progress, did_coag
162 real(kind=
dp) :: t_start, t_wall_now, t_wall_elapsed, t_wall_remain
164 integer :: n_time, i_time, pre_i_time
165 integer :: i_state, i_state_netcdf, i_output
166 integer :: i_cur, i_next
179 progress_n_dil_in = 0
180 progress_n_dil_out = 0
184 "del_t", run_part_opt%del_t)
186 "del_t", run_part_opt%del_t)
188 "del_t", run_part_opt%del_t)
190 if (run_part_opt%do_mosaic)
then
191 call mosaic_init(env_state, aero_data, run_part_opt%del_t, &
192 run_part_opt%do_optical)
193 if (run_part_opt%do_optical)
then
195 aero_state, gas_data, gas_state)
200 if (run_part_opt%t_output > 0d0)
then
202 run_part_opt%output_type, aero_data, aero_state, gas_data, &
203 gas_state, env_state, i_state, time, run_part_opt%del_t, &
204 run_part_opt%i_repeat, run_part_opt%record_removals, &
205 run_part_opt%do_optical, run_part_opt%uuid)
206 call aero_info_array_zero(aero_state%aero_info_array)
210 run_part_opt%allow_doubling, &
211 run_part_opt%allow_halving, initial_state_warning=.true.)
213 t_start = env_state%elapsed_time
214 last_output_time = time
215 last_progress_time = time
216 n_time = nint(run_part_opt%t_max / run_part_opt%del_t)
221 if (run_part_opt%i_repeat == 1)
then
226 prop_done = real(run_part_opt%i_repeat - 1, kind=
dp) &
227 / real(run_part_opt%n_repeat, kind=
dp)
228 t_wall_elapsed = t_wall_now - run_part_opt%t_wall_start
229 t_wall_remain = (1d0 - prop_done) / prop_done &
233 global_n_part, 0, 0, 0, 0, 0, t_wall_elapsed, t_wall_remain)
240 gas_data, gas_state, run_part_opt, &
242 camp_core, photolysis, &
244 i_cur, i_next, t_start, last_output_time, last_progress_time, &
245 i_output, progress_n_samp, progress_n_coag, progress_n_emit, &
246 progress_n_dil_in, progress_n_dil_out, progress_n_nuc)
248 if (run_part_opt%do_mosaic)
then
258 n_emit, n_dil_in, n_dil_out, n_nuc, t_wall_elapsed, t_wall_remain)
261 integer,
intent(in) :: i_repeat
263 real(kind=
dp),
intent(in) :: t_sim_elapsed
265 integer,
intent(in) :: n_part
267 integer,
intent(in) :: n_coag
269 integer,
intent(in) :: n_emit
271 integer,
intent(in) :: n_dil_in
273 integer,
intent(in) :: n_dil_out
275 integer,
intent(in) :: n_nuc
277 real(kind=
dp),
intent(in) :: t_wall_elapsed
279 real(kind=
dp),
intent(in) :: t_wall_remain
281 write(*,
'(a6,a1,a6,a1,a7,a1,a7,a1,a7,a1,a8,a1,a9,a1,a7,a1,a6,a1,a6)') &
282 "repeat",
" ",
"t_sim",
" ",
"n_part",
" ",
"n_coag",
" ", &
283 "n_emit",
" ",
"n_dil_in",
" ",
"n_dil_out",
" ",
"n_nuc",
" ", &
284 "t_wall",
" ",
"t_rem"
285 write(*,
'(a6,a1,a6,a1,a7,a1,a7,a1,a7,a1,a8,a1,a9,a1,a7,a1,a6,a1,a6)') &
349 character,
intent(inout) :: buffer(:)
351 integer,
intent(inout) :: position
356 integer :: prev_position
358 prev_position = position
403 character,
intent(inout) :: buffer(:)
405 integer,
intent(inout) :: position
410 integer :: prev_position
412 prev_position = position
455 aero_state_init, gas_data, gas_state_init, env_state_init, &
456 aero_dist_init, scenario, &
458 camp_core, photolysis, aero_state, &
460 n_part, rand_init, do_init_equilibrate, do_restart)
477 type(aero_dist_t),
intent(inout) :: aero_dist_init
482 type(camp_core_t),
pointer :: camp_core
484 type(photolysis_t),
pointer :: photolysis
489 real(kind=
dp),
intent(inout) :: n_part
491 integer,
intent(out) :: rand_init
493 logical,
intent(out) :: do_init_equilibrate
495 logical,
intent(out) :: do_restart
497 integer :: i_repeat, i_group
498 logical :: read_aero_weight_classes
499 character(len=PMC_MAX_FILENAME_LEN) :: restart_filename
500 integer :: dummy_index, dummy_i_repeat
501 real(kind=
dp) :: dummy_time, dummy_del_t
502 character(len=PMC_MAX_FILENAME_LEN) :: sub_filename
504 character(len=PMC_MAX_FILENAME_LEN) :: camp_config_filename, &
505 tchem_gas_filename, tchem_aero_filename, tchem_numerics_filename
506 integer :: n_grid_cells
509 run_part_opt%output_prefix)
517 if (.not. do_restart)
then
519 run_part_opt%do_select_weighting)
520 read_aero_weight_classes = .false.
521 if (run_part_opt%do_select_weighting)
then
522 call spec_file_read_aero_state_weighting_type(file, &
523 run_part_opt%weighting_type, run_part_opt%weighting_exponent)
524 if (run_part_opt%weighting_type &
526 read_aero_weight_classes = .true.
530 run_part_opt%weighting_exponent = 0.0d0
540 if (run_part_opt%do_camp_chem)
then
543 camp_core => camp_core_t(camp_config_filename)
544 call camp_core%initialize()
545 photolysis => photolysis_t(camp_core)
548 'cannot do camp chem, CAMP support not compiled in')
553 if (run_part_opt%do_tchem)
then
560 tchem_numerics_filename)
564 if (run_part_opt%do_tchem)
then
567 call pmc_tchem_initialize(tchem_gas_filename, tchem_aero_filename, &
568 tchem_numerics_filename, gas_data, aero_data, n_grid_cells)
573 call input_state(restart_filename, dummy_index, dummy_time, &
574 dummy_del_t, dummy_i_repeat, run_part_opt%uuid, aero_data, &
575 aero_state_init, gas_data, gas_state_init, env_state_init)
578 if (.not. do_restart)
then
579 env_state_init%elapsed_time = 0d0
581 if (.not. (run_part_opt%do_camp_chem .or. run_part_opt%do_tchem))
then
584 call spec_file_read_gas_data(sub_file, gas_data)
586 else if (run_part_opt%do_camp_chem)
then
588 call gas_data_initialize(gas_data, camp_core)
593 call spec_file_read_gas_state(sub_file, gas_data, gas_state_init)
596 if (.not. run_part_opt%do_camp_chem)
then
599 call spec_file_read_aero_data(sub_file, aero_data)
602 else if (run_part_opt%do_tchem)
then
605 call spec_file_read_aero_data(sub_file, aero_data)
609 call aero_data_initialize(aero_data, camp_core)
610 call aero_state_initialize(aero_state, aero_data, camp_core)
613 call spec_file_read_fractal(file, aero_data%fractal)
617 call spec_file_read_aero_dist(sub_file, aero_data, &
618 read_aero_weight_classes, aero_dist_init)
622 call spec_file_read_scenario(file, gas_data, aero_data, &
623 read_aero_weight_classes, scenario)
624 call spec_file_read_env_state(file, env_state_init)
627 run_part_opt%do_coagulation)
628 if (run_part_opt%do_coagulation)
then
629 call spec_file_read_coag_kernel_type(file, run_part_opt%coag_kernel_type)
632 env_state_init%additive_kernel_coefficient)
639 run_part_opt%do_condensation)
640 #ifndef PMC_USE_SUNDIALS
642 run_part_opt%do_condensation .eqv. .false., &
643 "cannot use condensation, SUNDIALS support is not compiled in")
645 do_init_equilibrate = .false.
646 if (run_part_opt%do_condensation)
then
654 'cannot use MOSAIC, support is not compiled in')
656 if (run_part_opt%do_mosaic .and. run_part_opt%do_condensation)
then
658 'cannot use MOSAIC and condensation simultaneously')
660 if (run_part_opt%do_mosaic)
then
662 run_part_opt%do_optical)
664 run_part_opt%do_optical = .false.
668 run_part_opt%do_nucleation)
669 if (run_part_opt%do_nucleation)
then
670 call spec_file_read_nucleate_type(file, aero_data, &
671 run_part_opt%nucleate_type, run_part_opt%nucleate_source, &
672 run_part_opt%nucleate_weight_class)
679 run_part_opt%allow_doubling)
681 run_part_opt%allow_halving)
683 run_part_opt%record_removals)
686 if (run_part_opt%do_parallel)
then
689 'cannot use parallel mode, support is not compiled in')
691 call spec_file_read_output_type(file, run_part_opt%output_type)
693 run_part_opt%mix_timescale)
695 run_part_opt%gas_average)
697 run_part_opt%env_average)
698 call spec_file_read_parallel_coag_type(file, &
699 run_part_opt%parallel_coag_type)
702 run_part_opt%mix_timescale = 0d0
703 run_part_opt%gas_average = .false.
704 run_part_opt%env_average = .false.
715 subroutine spec_file_read_parallel_coag_type(file, parallel_coag_type)
720 integer,
intent(out) :: parallel_coag_type
722 character(len=SPEC_LINE_MAX_VAR_LEN) :: parallel_coag_type_name
737 parallel_coag_type_name)
738 if (trim(parallel_coag_type_name) ==
'local')
then
740 elseif (trim(parallel_coag_type_name) ==
'dist')
then
744 "Unknown parallel coagulation type: " &
745 // trim(parallel_coag_type_name))
748 end subroutine spec_file_read_parallel_coag_type
754 gas_data, gas_state, run_part_opt, &
756 camp_core, photolysis, &
758 i_time, t_start, last_output_time, last_progress_time, i_output, &
759 progress_n_samp, progress_n_coag, progress_n_emit, progress_n_dil_in, &
760 progress_n_dil_out, progress_n_nuc)
778 type(camp_core_t),
pointer,
intent(inout),
optional :: camp_core
780 type(photolysis_t),
pointer,
intent(inout),
optional :: photolysis
783 integer,
intent(in) :: i_time
785 real(kind=
dp),
intent(in) :: t_start
787 real(kind=
dp),
intent(inout) :: last_output_time
789 real(kind=
dp),
intent(inout) :: last_progress_time
791 integer,
intent(inout) :: i_output
793 integer,
intent(inout) :: progress_n_samp
795 integer,
intent(inout) :: progress_n_coag
797 integer,
intent(inout) :: progress_n_emit
799 integer,
intent(inout) :: progress_n_dil_in
801 integer,
intent(inout) :: progress_n_dil_out
803 integer,
intent(inout) :: progress_n_nuc
805 real(kind=
dp) :: prop_done
806 integer :: n_samp, n_coag, n_emit, n_dil_in, n_dil_out, n_nuc
807 integer :: n_part_before
808 integer :: global_n_part, global_n_samp, global_n_coag
809 integer :: global_n_emit, global_n_dil_in, global_n_dil_out
810 integer :: global_n_nuc
811 logical :: do_output, do_state, do_state_netcdf, do_progress
812 real(kind=
dp) :: t_wall_now, t_wall_elapsed, t_wall_remain, time
815 type(camp_state_t),
pointer :: camp_state
816 type(camp_state_t),
pointer :: camp_pre_aero_state, camp_post_aero_state
817 type(camp_env_state_t) :: camp_env_state
820 time = i_time * run_part_opt%del_t
823 if (run_part_opt%do_camp_chem)
then
824 camp_env_state%temp = env_state%temp
825 camp_env_state%pressure = env_state%pressure
826 camp_state => camp_core%new_state_one_cell(camp_env_state)
827 camp_pre_aero_state => camp_core%new_state_one_cell(camp_env_state)
828 camp_post_aero_state => camp_core%new_state_one_cell(camp_env_state)
832 old_env_state = env_state
835 if (run_part_opt%do_nucleation)
then
837 call nucleate(run_part_opt%nucleate_type, &
838 run_part_opt%nucleate_source, run_part_opt%nucleate_weight_class, &
839 env_state, gas_data, aero_data, &
840 aero_state, gas_state, run_part_opt%del_t, &
841 run_part_opt%allow_doubling, run_part_opt%allow_halving)
844 progress_n_nuc = progress_n_nuc + n_nuc
847 if (run_part_opt%do_coagulation)
then
848 if (run_part_opt%parallel_coag_type &
850 call mc_coag(run_part_opt%coag_kernel_type, env_state, &
851 aero_data, aero_state, run_part_opt%del_t, n_samp, n_coag)
852 elseif (run_part_opt%parallel_coag_type &
854 call mc_coag_dist(run_part_opt%coag_kernel_type, env_state, &
855 aero_data, aero_state, run_part_opt%del_t, n_samp, n_coag)
857 call die_msg(323011762,
"unknown parallel coagulation type: " &
860 progress_n_samp = progress_n_samp + n_samp
861 progress_n_coag = progress_n_coag + n_coag
864 #ifdef PMC_USE_SUNDIALS
865 if (run_part_opt%do_condensation)
then
867 env_state, run_part_opt%del_t)
872 env_state, old_env_state, gas_data, gas_state)
874 env_state, old_env_state, aero_data, aero_state, n_emit, &
875 n_dil_in, n_dil_out, run_part_opt%allow_doubling, &
876 run_part_opt%allow_halving)
877 progress_n_emit = progress_n_emit + n_emit
878 progress_n_dil_in = progress_n_dil_in + n_dil_in
879 progress_n_dil_out = progress_n_dil_out + n_dil_out
881 if (run_part_opt%do_camp_chem)
then
883 call pmc_camp_interface_solve(camp_core, camp_state, &
884 camp_pre_aero_state, camp_post_aero_state, env_state, &
885 aero_data, aero_state, gas_data, gas_state, photolysis, &
890 if (run_part_opt%do_tchem)
then
892 call pmc_tchem_interface_solve(env_state, aero_data, aero_state, &
893 gas_data, gas_state, run_part_opt%del_t)
897 if (run_part_opt%do_mosaic)
then
899 gas_state, run_part_opt%do_optical, run_part_opt%uuid)
902 if (run_part_opt%mix_timescale > 0d0)
then
904 run_part_opt%mix_timescale, aero_data)
906 if (run_part_opt%gas_average)
then
909 if (run_part_opt%gas_average)
then
914 run_part_opt%allow_doubling, &
915 run_part_opt%allow_halving, initial_state_warning=.false.)
918 if (run_part_opt%t_output > 0d0)
then
919 call check_event(time, run_part_opt%del_t, run_part_opt%t_output, &
920 last_output_time, do_output)
922 i_output = i_output + 1
924 run_part_opt%output_type, aero_data, aero_state, gas_data, &
925 gas_state, env_state, i_output, time, run_part_opt%del_t, &
926 run_part_opt%i_repeat, run_part_opt%record_removals, &
927 run_part_opt%do_optical, run_part_opt%uuid)
928 call aero_info_array_zero(aero_state%aero_info_array)
932 if (.not. run_part_opt%record_removals)
then
936 call aero_info_array_zero(aero_state%aero_info_array)
939 if (run_part_opt%t_progress > 0d0)
then
941 run_part_opt%t_progress, last_progress_time, do_progress)
942 if (do_progress)
then
955 prop_done = (real(run_part_opt%i_repeat - 1, kind=
dp) &
956 + time / run_part_opt%t_max) &
957 / real(run_part_opt%n_repeat, kind=
dp)
958 t_wall_elapsed = t_wall_now - run_part_opt%t_wall_start
959 t_wall_remain = (1d0 - prop_done) / prop_done * t_wall_elapsed
961 global_n_part, global_n_coag, global_n_emit, &
962 global_n_dil_in, global_n_dil_out, global_n_nuc, &
963 t_wall_elapsed, t_wall_remain)
970 progress_n_dil_in = 0
971 progress_n_dil_out = 0
982 gas_data, gas_state, run_part_opt, &
984 camp_core, photolysis, &
986 i_cur, i_next, t_start, last_output_time, last_progress_time, &
987 i_output, progress_n_samp, progress_n_coag, progress_n_emit, &
988 progress_n_dil_in, progress_n_dil_out, progress_n_nuc)
1006 type(camp_core_t),
pointer,
intent(inout),
optional :: camp_core
1008 type(photolysis_t),
pointer,
intent(inout),
optional :: photolysis
1011 integer,
intent(in) :: i_cur
1013 real(kind=
dp),
intent(in) :: t_start
1015 integer,
intent(in) :: i_next
1017 real(kind=
dp),
intent(inout) :: last_output_time
1019 real(kind=
dp),
intent(inout) :: last_progress_time
1021 integer,
intent(inout) :: i_output
1023 integer,
intent(inout) :: progress_n_samp
1025 integer,
intent(inout) :: progress_n_coag
1027 integer,
intent(inout) :: progress_n_emit
1029 integer,
intent(inout) :: progress_n_dil_in
1031 integer,
intent(inout) :: progress_n_dil_out
1033 integer,
intent(inout) :: progress_n_nuc
1037 do i_time = i_cur,i_next
1039 gas_data, gas_state, run_part_opt, &
1041 camp_core, photolysis, &
1043 i_time, t_start, last_output_time, last_progress_time, i_output, &
1044 progress_n_samp, progress_n_coag, progress_n_emit, &
1045 progress_n_dil_in, progress_n_dil_out, progress_n_nuc)
1054 aero_state_init, gas_data, gas_state_init, env_state_init, &
1055 aero_dist_init, scenario, &
1057 camp_core, photolysis, aero_state, &
1059 n_part, rand_init, do_init_equilibrate, do_restart)
1070 type(
gas_state_t),
intent(inout) :: gas_state_init
1072 type(
env_state_t),
intent(inout) :: env_state_init
1074 type(aero_dist_t),
intent(inout) :: aero_dist_init
1079 type(camp_core_t),
pointer :: camp_core
1081 type(photolysis_t),
pointer :: photolysis
1086 real(kind=
dp),
intent(inout) :: n_part
1088 integer,
intent(inout) :: rand_init
1090 logical,
intent(inout) :: do_init_equilibrate
1092 logical,
intent(inout) :: do_restart
1094 character,
allocatable :: buffer(:)
1095 integer :: buffer_size, max_buffer_size
1102 max_buffer_size = max_buffer_size &
1104 max_buffer_size = max_buffer_size &
1106 max_buffer_size = max_buffer_size &
1108 max_buffer_size = max_buffer_size &
1110 max_buffer_size = max_buffer_size &
1112 max_buffer_size = max_buffer_size &
1113 + pmc_mpi_pack_size_aero_dist(aero_dist_init)
1114 max_buffer_size = max_buffer_size &
1116 max_buffer_size = max_buffer_size &
1118 max_buffer_size = max_buffer_size &
1120 max_buffer_size = max_buffer_size &
1122 max_buffer_size = max_buffer_size &
1124 max_buffer_size = max_buffer_size &
1127 allocate(buffer(max_buffer_size))
1135 call pmc_mpi_pack_aero_dist(buffer, position, aero_dist_init)
1142 call assert(181905491, position <= max_buffer_size)
1143 buffer_size = position
1151 allocate(buffer(buffer_size))
1165 call pmc_mpi_unpack_aero_dist(buffer, position, aero_dist_init)
1172 call assert(143770146, position == buffer_size)