PartMC
2.2.0
|
00001 ! Copyright (C) 2007-2011 Nicole Riemer and Matthew West 00002 ! Licensed under the GNU General Public License version 2 or (at your 00003 ! option) any later version. See the file COPYING for details. 00004 00005 !> \file 00006 !> The partmc program. 00007 00008 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00009 00010 !> \mainpage PartMC Code Documentation 00011 !! 00012 !! \subpage input_format - Input file format description. 00013 !! 00014 !! \subpage output_format - Output file format description. 00015 !! 00016 !! \subpage module_diagram - Diagram of modules and dependencies. 00017 !! 00018 !! \subpage coding_style - Description of code conventions and style. 00019 !! 00020 !! \subpage publications - Publications about PartMC. 00021 00022 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00023 00024 !> \page input_format Input File Format 00025 !! 00026 !! The input file format is plain text: 00027 !! 00028 !! \subpage spec_file_format "Spec File Format" 00029 !! 00030 !! When running PartMC with the command <tt>partmc input.spec</tt> the 00031 !! first line of the <tt>input.spec</tt> file must define the \c 00032 !! run_type with: 00033 !! <pre> 00034 !! run_type <type> 00035 !! </pre> 00036 !! where <tt><type></tt> is one of \c particle, \c exact, or \c 00037 !! sectional. This determines the type of run as well as the format of the 00038 !! remainder of the spec file. The rest of the spec file is described by: 00039 !! 00040 !! \subpage input_format_particle "Particle-resolved simulation" 00041 !! 00042 !! \subpage input_format_exact "Exact (analytical) solution" 00043 !! 00044 !! \subpage input_format_sectional "Sectional model simulation" 00045 00046 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00047 00048 !> \page module_diagram Module Diagram 00049 !! 00050 !! \dotfile partmc_modules.gv 00051 00052 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00053 00054 !> \page coding_style Coding Style 00055 !! 00056 !! The code is mainly Fortran 90, with a few parts still clearly 00057 !! showing their Fortran 77 heritage. A few Fortran 95 and Fortran 00058 !! 2003 features are used (mainly the \c COMMAND_ARGUMENT_COUNT and \c 00059 !! GET_COMMAND_ARGUMENT intrinsics). The code needs to be processed 00060 !! with \c cpp or a compatible pre-processor. 00061 !! 00062 !! \section oo_fortran Object Oriented Fortran 00063 !! 00064 !! Extensive use is made of Fortran 90 derived types and pointers for 00065 !! dynamic memory allocation of arrays inside derived types. Derived 00066 !! types are named \c my_type_t and are generally defined in modules 00067 !! named \c pmc_my_type within files named \c my_type.F95. Each 00068 !! derived type has allocation and deallocation functions \c 00069 !! my_type_allocate() and \c my_type_deallocate(), where 00070 !! appropriate. Almost all subroutines and function in each \c 00071 !! my_type.F95 file have names of the form \c my_type_*() and take an 00072 !! object of type \c my_type_t (called \c my_type) as the first argument 00073 !! on which to operate. 00074 !! 00075 !! Module names are always the same as the name of the containing 00076 !! file, but prefixed with \c pmc_. Thus the module \c 00077 !! pmc_condense is contained in the file \c condense.F95. 00078 !! 00079 !! \section mem_manage Memory Management 00080 !! 00081 !! The memory allocation policy is that all functions must be called 00082 !! with an already allocated structure. That is, if a subroutine 00083 !! defines a variable of type \c my_type_t, then it must call \c 00084 !! my_type_allocate() or \c my_type_allocate_size() on it before 00085 !! passing it to any other subroutines or functions. The defining 00086 !! subroutine is also responsible for calling \c my_type_deallocate() 00087 !! on every variable it defines. 00088 !! 00089 !! Similarly, any subroutine that declares a pointer variable must 00090 !! allocate it and any data it points to before passing it to other 00091 !! subroutines or functions. If no specific length is known for an array 00092 !! pointer then it should be allocated to zero size. Any subsequent 00093 !! subroutines are free to deallocate and reallocate if they need to 00094 !! change the size. 00095 !! 00096 !! This means that every subroutine (except for allocate and 00097 !! deallocate routines) should contain matching \c 00098 !! allocate()/deallocate() and 00099 !! <tt>my_type_allocate()/my_type_deallocate()</tt> calls. 00100 00101 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00102 00103 !> \page publications PartMC Publications 00104 !! 00105 !! - R. A. Zaveri, J. C. Barnard, 00106 !! R. C. Easter, N. Riemer, and M. West (2010) 00107 !! Particle-resolved simulation of aerosol size, composition, 00108 !! mixing state, and the associated optical and cloud condensation 00109 !! nuclei activation properties in an evolving urban plume, 00110 !! <i>Journal of Geophysical Research</i> 115(D17210), DOI: <a 00111 !! href="http://dx.doi.org/10.1029/2009JD013616">10.1029/2009JD013616</a>. 00112 !! - N. Riemer, M. West, R. A. Zaveri, and 00113 !! R. C. Easter (2010) Estimating black carbon aging 00114 !! time-scales with a particle-resolved aerosol model, <i>Journal 00115 !! of Aerosol Science</i> 41(1), 143-158, DOI: <a 00116 !! href="http://dx.doi.org/10.1016/j.jaerosci.2009.08.009">10.1016/j.jaerosci.2009.08.009</a> 00117 !! - N. Riemer, M. West, R. A. Zaveri, and 00118 !! R. C. Easter (2009) Simulating the evolution of soot 00119 !! mixing state with a particle-resolved aerosol model, <i>Journal 00120 !! of Geophysical Research</i> 114(D09202), DOI: <a 00121 !! href="http://dx.doi.org/10.1029/2008JD011073">10.1029/2008JD011073</a> 00122 !! - R. McGraw, L. Leng, W. Zhu, N. Riemer, and 00123 !! M. West (2008) Aerosol dynamics using the quadrature 00124 !! method of moments: Comparing several quadrature schemes with 00125 !! particle-resolved simulation, <i>Journal of Physics: Conference 00126 !! Series</i> 125(012020), DOI: <a 00127 !! href="http://dx.doi.org/10.1088/1742-6596/125/1/012020">10.1088/1742-6596/125/1/012020</a> 00128 00129 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00130 00131 !> Top level driver. 00132 program partmc 00133 00134 use pmc_mpi 00135 use pmc_bin_grid 00136 use pmc_aero_state 00137 use pmc_aero_dist 00138 use pmc_aero_binned 00139 use pmc_coag_kernel 00140 use pmc_aero_data 00141 use pmc_env_data 00142 use pmc_env_state 00143 use pmc_run_part 00144 use pmc_run_exact 00145 use pmc_run_sect 00146 use pmc_spec_file 00147 use pmc_gas_data 00148 use pmc_gas_state 00149 use pmc_util 00150 #ifdef PMC_USE_SUNDIALS 00151 use pmc_condense 00152 #endif 00153 00154 character(len=300) :: spec_name 00155 00156 call pmc_mpi_init() 00157 00158 if (pmc_mpi_rank() == 0) then 00159 ! only the root process accesses the commandline 00160 00161 if (command_argument_count() /= 1) then 00162 call print_usage() 00163 call die_msg(739173192, "invalid commandline arguments") 00164 end if 00165 00166 call get_command_argument(1, spec_name) 00167 end if 00168 00169 call pmc_mpi_bcast_string(spec_name) 00170 call partmc_run(spec_name) 00171 00172 call pmc_mpi_finalize() 00173 00174 contains 00175 00176 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00177 00178 !> Print the usage text to stderr. 00179 subroutine print_usage() 00180 00181 write(*,*) 'Usage: partmc <spec-file>' 00182 00183 end subroutine print_usage 00184 00185 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00186 00187 !> Do a PartMC run. 00188 subroutine partmc_run(spec_name) 00189 00190 !> Spec filename. 00191 character(len=*), intent(in) :: spec_name 00192 00193 type(spec_file_t) :: file 00194 character(len=100) :: run_type 00195 integer :: i 00196 00197 ! check filename (must be "filename.spec") 00198 i = len_trim(spec_name) 00199 if (spec_name((i-4):i) /= '.spec') then 00200 call die_msg(710381938, "input filename must end in .spec") 00201 end if 00202 00203 if (pmc_mpi_rank() == 0) then 00204 ! only the root process does I/O 00205 call spec_file_open(spec_name, file) 00206 call spec_file_read_string(file, 'run_type', run_type) 00207 end if 00208 00209 call pmc_mpi_bcast_string(run_type) 00210 if (trim(run_type) == 'particle') then 00211 call partmc_part(file) 00212 elseif (trim(run_type) == 'exact') then 00213 call partmc_exact(file) 00214 elseif (trim(run_type) == 'sectional') then 00215 call partmc_sect(file) 00216 else 00217 call die_msg(719261940, "unknown run_type: " // trim(run_type)) 00218 end if 00219 00220 end subroutine partmc_run 00221 00222 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00223 00224 !> Run a Monte Carlo simulation. 00225 subroutine partmc_part(file) 00226 00227 !> Spec file. 00228 type(spec_file_t), intent(inout) :: file 00229 00230 type(gas_data_t) :: gas_data 00231 type(gas_state_t) :: gas_state 00232 type(gas_state_t) :: gas_state_init 00233 type(aero_data_t) :: aero_data 00234 type(aero_dist_t) :: aero_dist_init 00235 type(aero_state_t) :: aero_state 00236 type(aero_state_t) :: aero_state_init 00237 type(env_data_t) :: env_data 00238 type(env_state_t) :: env_state 00239 type(env_state_t) :: env_state_init 00240 type(run_part_opt_t) :: run_part_opt 00241 integer :: i_repeat, i_group 00242 integer :: rand_init 00243 character, allocatable :: buffer(:) 00244 integer :: buffer_size, max_buffer_size 00245 integer :: position 00246 logical :: do_restart, do_init_equilibriate, aero_mode_type_exp_present 00247 character(len=PMC_MAX_FILENAME_LEN) :: restart_filename 00248 integer :: dummy_index, dummy_i_repeat 00249 real(kind=dp) :: dummy_time, dummy_del_t, n_part_ideal 00250 character(len=PMC_MAX_FILENAME_LEN) :: sub_filename 00251 type(spec_file_t) :: sub_file 00252 00253 !> \page input_format_particle Input File Format: Particle-Resolved Simulation 00254 !! 00255 !! See \ref spec_file_format for the input file text format. 00256 !! 00257 !! A particle-resolved simulation spec file has the parameters: 00258 !! - \b run_type (string): must be \c particle 00259 !! - \b output_prefix (string): prefix of the output filenames 00260 !! --- see \ref output_format for the full name format 00261 !! - \b n_repeat (integer): number of repeats 00262 !! - \b n_part (integer): number of computational particles to 00263 !! simulate (actual number used will vary between <tt>n_part / 00264 !! 2</tt> and <tt>n_part * 2</tt> if \c allow_doubling and \c 00265 !! allow_halving are \c yes) 00266 !! - \b restart (logical): whether to restart the simulation from 00267 !! a saved output data file. If \c restart is \c yes, then the 00268 !! following parameters must also be provided: 00269 !! - \b restart_file (string): name of file from which to load 00270 !! restart data, which must be a PartMC output NetCDF file 00271 !! - \b t_max (real, unit s): total simulation time 00272 !! - \b del_t (real, unit s): timestep size 00273 !! - \b t_output (real, unit s): the interval on which to 00274 !! output data to disk (see \ref output_format) 00275 !! - \b t_progress (real, unit s): the interval on which to 00276 !! write summary information to the screen while running 00277 !! - \b gas_data (string): name of file from which to read the gas 00278 !! material data (only provide if \c restart is \c no) --- the 00279 !! file format should be \subpage input_format_gas_data 00280 !! - \b gas_init (string): name of file from which to read the 00281 !! initial gas state at the start of the simulation (only 00282 !! provide option if \c restart is \c no) --- the file format 00283 !! should be \subpage input_format_gas_state 00284 !! - \b aerosol_data (string): name of file from which to read the 00285 !! aerosol material data (only provide if \c restart is \c no) 00286 !! --- the file format should be \subpage input_format_aero_data 00287 !! - \b aerosol_init (string): filename containing the initial 00288 !! aerosol state at the start of the simulation (only provide 00289 !! option if \c restart is \c no) --- the file format should 00290 !! be \subpage input_format_aero_dist 00291 !! - \subpage input_format_env_data 00292 !! - \subpage input_format_env_state 00293 !! - \b do_coagulation (logical): whether to perform particle 00294 !! coagulation. If \c do_coagulation is \c yes, then the 00295 !! following parameters must also be provided: 00296 !! - \subpage input_format_coag_kernel 00297 !! - \b do_condensation (logical): whether to perform explicit 00298 !! water condensation (requires SUNDIALS support to be compiled 00299 !! in; cannot be used simultaneously with MOSAIC). If \c 00300 !! do_condensation is \c yes, then the following parameters must 00301 !! also be provided: 00302 !! - \b do_init_equilibriate (logical): whether to equilibriate 00303 !! the water content of each particle before starting the 00304 !! simulation 00305 !! - \b do_mosaic (logical): whether to use the MOSAIC chemistry 00306 !! code (requires support to be compiled in; cannot be used 00307 !! simultaneously with condensation). If \c do_mosaic is \c 00308 !! yes, then the following parameters must also be provided: 00309 !! - \b do_optical (logical): whether to compute optical 00310 !! properties of the aersol particles for the output files --- 00311 !! see output_format_aero_state 00312 !! - \b do_nucleation (logical): whether to perform particle 00313 !! nucleation. If \c do_nucleation is \c yes, then the following 00314 !! parameters must also be provided: 00315 !! - \subpage input_format_nucleate 00316 !! - \b rand_init (integer): if greater than zero then use as 00317 !! the seed for the random number generator, or if zero then 00318 !! generate a random seed for the random number generator --- 00319 !! two simulations on the same machine with the same seed 00320 !! (greater than 0) will produce identical output 00321 !! - \b allow_doubling (logical): if \c yes, then whenever the 00322 !! number of simulated particles falls below <tt>n_part / 00323 !! 2</tt>, every particle is duplicated to give better 00324 !! statistics 00325 !! - \b allow_halving (logical): if \c yes, then whenever the 00326 !! number of simulated particles rises above <tt>n_part * 00327 !! 2</tt>, half of the particles are removed (chosen randomly) 00328 !! to reduce the computational expense 00329 !! - \b record_removals (logical): whether to record information 00330 !! about aerosol particles removed from the simulation --- see 00331 !! \ref output_format_aero_removed 00332 !! - \b do_parallel (logical): whether to run in parallel mode 00333 !! (requires MPI support to be compiled in). If \c do_parallel 00334 !! is \c yes, then the following parameters must also be 00335 !! provided: 00336 !! - \subpage input_format_output 00337 !! - \b mix_timescale (real, unit s): timescale on which to mix 00338 !! aerosol particle information amongst processes in an 00339 !! attempt to keep the aerosol state consistent (the mixing 00340 !! rate is inverse to \c mix_timescale) 00341 !! - \b gas_average (logical): whether to average the gas state 00342 !! amongst processes each timestep, to ensure uniform gas 00343 !! concentrations 00344 !! - \b env_average (logical): whether to average the 00345 !! environment state amongst processes each timestep, to 00346 !! ensure a uniform environment 00347 !! - \subpage input_format_parallel_coag 00348 00349 call gas_data_allocate(gas_data) 00350 call gas_state_allocate(gas_state) 00351 call gas_state_allocate(gas_state_init) 00352 call aero_data_allocate(aero_data) 00353 call aero_dist_allocate(aero_dist_init) 00354 call aero_state_allocate(aero_state) 00355 call aero_state_allocate(aero_state_init) 00356 call env_data_allocate(env_data) 00357 call env_state_allocate(env_state) 00358 call env_state_allocate(env_state_init) 00359 00360 if (pmc_mpi_rank() == 0) then 00361 ! only the root process does I/O 00362 00363 call spec_file_read_string(file, 'output_prefix', & 00364 run_part_opt%output_prefix) 00365 call spec_file_read_integer(file, 'n_repeat', run_part_opt%n_repeat) 00366 call spec_file_read_real(file, 'n_part', n_part_ideal) 00367 call spec_file_read_logical(file, 'restart', do_restart) 00368 if (do_restart) then 00369 call spec_file_read_string(file, 'restart_file', restart_filename) 00370 end if 00371 00372 call spec_file_read_real(file, 't_max', run_part_opt%t_max) 00373 call spec_file_read_real(file, 'del_t', run_part_opt%del_t) 00374 call spec_file_read_real(file, 't_output', run_part_opt%t_output) 00375 call spec_file_read_real(file, 't_progress', run_part_opt%t_progress) 00376 00377 if (do_restart) then 00378 call input_state(restart_filename, dummy_index, dummy_time, & 00379 dummy_del_t, dummy_i_repeat, run_part_opt%uuid, aero_data, & 00380 aero_state_init, gas_data, gas_state_init, env_state_init) 00381 end if 00382 00383 if (.not. do_restart) then 00384 call spec_file_read_string(file, 'gas_data', sub_filename) 00385 call spec_file_open(sub_filename, sub_file) 00386 call spec_file_read_gas_data(sub_file, gas_data) 00387 call spec_file_close(sub_file) 00388 00389 call spec_file_read_string(file, 'gas_init', sub_filename) 00390 call spec_file_open(sub_filename, sub_file) 00391 call spec_file_read_gas_state(sub_file, gas_data, & 00392 gas_state_init) 00393 call spec_file_close(sub_file) 00394 00395 call spec_file_read_string(file, 'aerosol_data', sub_filename) 00396 call spec_file_open(sub_filename, sub_file) 00397 call spec_file_read_aero_data(sub_file, aero_data) 00398 call spec_file_close(sub_file) 00399 00400 call spec_file_read_string(file, 'aerosol_init', sub_filename) 00401 call spec_file_open(sub_filename, sub_file) 00402 call spec_file_read_aero_dist(sub_file, aero_data, aero_dist_init) 00403 call spec_file_close(sub_file) 00404 end if 00405 00406 call spec_file_read_env_data(file, gas_data, aero_data, env_data) 00407 call spec_file_read_env_state(file, env_state_init) 00408 00409 call spec_file_read_logical(file, 'do_coagulation', & 00410 run_part_opt%do_coagulation) 00411 if (run_part_opt%do_coagulation) then 00412 call spec_file_read_coag_kernel_type(file, & 00413 run_part_opt%coag_kernel_type) 00414 else 00415 run_part_opt%coag_kernel_type = COAG_KERNEL_TYPE_INVALID 00416 end if 00417 00418 call spec_file_read_logical(file, 'do_condensation', & 00419 run_part_opt%do_condensation) 00420 #ifndef PMC_USE_SUNDIALS 00421 call assert_msg(121370218, & 00422 run_part_opt%do_condensation .eqv. .false., & 00423 "cannot use condensation, SUNDIALS support is not compiled in") 00424 #endif 00425 if (run_part_opt%do_condensation) then 00426 call spec_file_read_logical(file, 'do_init_equilibriate', & 00427 do_init_equilibriate) 00428 else 00429 do_init_equilibriate = .false. 00430 end if 00431 00432 call spec_file_read_logical(file, 'do_mosaic', run_part_opt%do_mosaic) 00433 if (run_part_opt%do_mosaic .and. (.not. mosaic_support())) then 00434 call spec_file_die_msg(230495365, file, & 00435 'cannot use MOSAIC, support is not compiled in') 00436 end if 00437 if (run_part_opt%do_mosaic .and. run_part_opt%do_condensation) then 00438 call spec_file_die_msg(599877804, file, & 00439 'cannot use MOSAIC and condensation simultaneously') 00440 end if 00441 if (run_part_opt%do_mosaic) then 00442 call spec_file_read_logical(file, 'do_optical', & 00443 run_part_opt%do_optical) 00444 else 00445 run_part_opt%do_optical = .false. 00446 end if 00447 00448 call spec_file_read_logical(file, 'do_nucleation', & 00449 run_part_opt%do_nucleation) 00450 if (run_part_opt%do_nucleation) then 00451 call spec_file_read_nucleate_type(file, run_part_opt%nucleate_type) 00452 else 00453 run_part_opt%nucleate_type = NUCLEATE_TYPE_INVALID 00454 end if 00455 00456 call spec_file_read_integer(file, 'rand_init', rand_init) 00457 call spec_file_read_logical(file, 'allow_doubling', & 00458 run_part_opt%allow_doubling) 00459 call spec_file_read_logical(file, 'allow_halving', & 00460 run_part_opt%allow_halving) 00461 call spec_file_read_logical(file, 'record_removals', & 00462 run_part_opt%record_removals) 00463 00464 call spec_file_read_logical(file, 'do_parallel', & 00465 run_part_opt%do_parallel) 00466 if (run_part_opt%do_parallel) then 00467 #ifndef PMC_USE_MPI 00468 call spec_file_die_msg(929006383, file, & 00469 'cannot use parallel mode, support is not compiled in') 00470 #endif 00471 call spec_file_read_output_type(file, run_part_opt%output_type) 00472 call spec_file_read_real(file, 'mix_timescale', & 00473 run_part_opt%mix_timescale) 00474 call spec_file_read_logical(file, 'gas_average', & 00475 run_part_opt%gas_average) 00476 call spec_file_read_logical(file, 'env_average', & 00477 run_part_opt%env_average) 00478 call spec_file_read_parallel_coag_type(file, & 00479 run_part_opt%parallel_coag_type) 00480 else 00481 run_part_opt%output_type = OUTPUT_TYPE_SINGLE 00482 run_part_opt%mix_timescale = 0d0 00483 run_part_opt%gas_average = .false. 00484 run_part_opt%env_average = .false. 00485 run_part_opt%parallel_coag_type = PARALLEL_COAG_TYPE_LOCAL 00486 end if 00487 00488 call spec_file_close(file) 00489 end if 00490 00491 ! finished reading .spec data, now broadcast data 00492 00493 ! initialize RNG with random seed for UUID generation 00494 call pmc_srand(0, pmc_mpi_rank()) 00495 00496 if (.not. do_restart) then 00497 call uuid4_str(run_part_opt%uuid) 00498 end if 00499 00500 #ifdef PMC_USE_MPI 00501 if (pmc_mpi_rank() == 0) then 00502 ! root process determines size 00503 max_buffer_size = 0 00504 max_buffer_size = max_buffer_size & 00505 + pmc_mpi_pack_size_run_part_opt(run_part_opt) 00506 max_buffer_size = max_buffer_size & 00507 + pmc_mpi_pack_size_real(n_part_ideal) 00508 max_buffer_size = max_buffer_size & 00509 + pmc_mpi_pack_size_gas_data(gas_data) 00510 max_buffer_size = max_buffer_size & 00511 + pmc_mpi_pack_size_gas_state(gas_state_init) 00512 max_buffer_size = max_buffer_size & 00513 + pmc_mpi_pack_size_aero_data(aero_data) 00514 max_buffer_size = max_buffer_size & 00515 + pmc_mpi_pack_size_aero_dist(aero_dist_init) 00516 max_buffer_size = max_buffer_size & 00517 + pmc_mpi_pack_size_env_data(env_data) 00518 max_buffer_size = max_buffer_size & 00519 + pmc_mpi_pack_size_env_state(env_state_init) 00520 max_buffer_size = max_buffer_size & 00521 + pmc_mpi_pack_size_integer(rand_init) 00522 max_buffer_size = max_buffer_size & 00523 + pmc_mpi_pack_size_logical(do_restart) 00524 max_buffer_size = max_buffer_size & 00525 + pmc_mpi_pack_size_logical(do_init_equilibriate) 00526 max_buffer_size = max_buffer_size & 00527 + pmc_mpi_pack_size_aero_state(aero_state_init) 00528 00529 allocate(buffer(max_buffer_size)) 00530 00531 position = 0 00532 call pmc_mpi_pack_run_part_opt(buffer, position, run_part_opt) 00533 call pmc_mpi_pack_real(buffer, position, n_part_ideal) 00534 call pmc_mpi_pack_gas_data(buffer, position, gas_data) 00535 call pmc_mpi_pack_gas_state(buffer, position, gas_state_init) 00536 call pmc_mpi_pack_aero_data(buffer, position, aero_data) 00537 call pmc_mpi_pack_aero_dist(buffer, position, aero_dist_init) 00538 call pmc_mpi_pack_env_data(buffer, position, env_data) 00539 call pmc_mpi_pack_env_state(buffer, position, env_state_init) 00540 call pmc_mpi_pack_integer(buffer, position, rand_init) 00541 call pmc_mpi_pack_logical(buffer, position, do_restart) 00542 call pmc_mpi_pack_logical(buffer, position, do_init_equilibriate) 00543 call pmc_mpi_pack_aero_state(buffer, position, aero_state_init) 00544 call assert(181905491, position <= max_buffer_size) 00545 buffer_size = position ! might be less than we allocated 00546 end if 00547 00548 ! tell everyone the size 00549 call pmc_mpi_bcast_integer(buffer_size) 00550 00551 if (pmc_mpi_rank() /= 0) then 00552 ! non-root processes allocate space 00553 allocate(buffer(buffer_size)) 00554 end if 00555 00556 ! broadcast data to everyone 00557 call pmc_mpi_bcast_packed(buffer) 00558 00559 if (pmc_mpi_rank() /= 0) then 00560 ! non-root processes unpack data 00561 position = 0 00562 call pmc_mpi_unpack_run_part_opt(buffer, position, run_part_opt) 00563 call pmc_mpi_unpack_real(buffer, position, n_part_ideal) 00564 call pmc_mpi_unpack_gas_data(buffer, position, gas_data) 00565 call pmc_mpi_unpack_gas_state(buffer, position, gas_state_init) 00566 call pmc_mpi_unpack_aero_data(buffer, position, aero_data) 00567 call pmc_mpi_unpack_aero_dist(buffer, position, aero_dist_init) 00568 call pmc_mpi_unpack_env_data(buffer, position, env_data) 00569 call pmc_mpi_unpack_env_state(buffer, position, env_state_init) 00570 call pmc_mpi_unpack_integer(buffer, position, rand_init) 00571 call pmc_mpi_unpack_logical(buffer, position, do_restart) 00572 call pmc_mpi_unpack_logical(buffer, position, do_init_equilibriate) 00573 call pmc_mpi_unpack_aero_state(buffer, position, aero_state_init) 00574 call assert(143770146, position == buffer_size) 00575 end if 00576 00577 ! free the buffer 00578 deallocate(buffer) 00579 #endif 00580 00581 ! re-initialize RNG with the given seed 00582 call pmc_rand_finalize() 00583 call pmc_srand(rand_init, pmc_mpi_rank()) 00584 00585 call gas_state_deallocate(gas_state) 00586 call gas_state_allocate_size(gas_state, gas_data%n_spec) 00587 call cpu_time(run_part_opt%t_wall_start) 00588 00589 do i_repeat = 1,run_part_opt%n_repeat 00590 run_part_opt%i_repeat = i_repeat 00591 00592 call gas_state_copy(gas_state_init, gas_state) 00593 if (do_restart) then 00594 call aero_state_copy(aero_state_init, aero_state) 00595 aero_state%n_part_ideal = n_part_ideal 00596 else 00597 call aero_state_reset(aero_state) 00598 aero_mode_type_exp_present & 00599 = aero_dist_contains_aero_mode_type(aero_dist_init, & 00600 AERO_MODE_TYPE_EXP) & 00601 .or. env_data_contains_aero_mode_type(env_data, & 00602 AERO_MODE_TYPE_EXP) 00603 if (aero_mode_type_exp_present) then 00604 call warn_msg(245301880, "using flat weighting only due to " & 00605 // "presence of exp aerosol mode") 00606 call aero_state_set_weight(aero_state, AERO_STATE_WEIGHT_FLAT) 00607 else 00608 call aero_state_set_weight(aero_state, AERO_STATE_WEIGHT_NUMMASS) 00609 end if 00610 aero_state%n_part_ideal = n_part_ideal 00611 call aero_state_add_aero_dist_sample(aero_state, aero_data, & 00612 aero_dist_init, 1d0, 0d0) 00613 end if 00614 call env_state_copy(env_state_init, env_state) 00615 call env_data_init_state(env_data, env_state, & 00616 env_state_init%elapsed_time) 00617 00618 #ifdef PMC_USE_SUNDIALS 00619 if (do_init_equilibriate) then 00620 call condense_equilib_particles(env_state, aero_data, aero_state) 00621 end if 00622 #endif 00623 00624 call run_part(env_data, env_state, aero_data, aero_state, gas_data, & 00625 gas_state, run_part_opt) 00626 00627 end do 00628 00629 call gas_data_deallocate(gas_data) 00630 call gas_state_deallocate(gas_state) 00631 call gas_state_deallocate(gas_state_init) 00632 call aero_data_deallocate(aero_data) 00633 call aero_dist_deallocate(aero_dist_init) 00634 call aero_state_deallocate(aero_state) 00635 call aero_state_deallocate(aero_state_init) 00636 call env_data_deallocate(env_data) 00637 call env_state_deallocate(env_state) 00638 call env_state_deallocate(env_state_init) 00639 00640 call pmc_rand_finalize() 00641 00642 end subroutine partmc_part 00643 00644 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00645 00646 !> Run an exact solution simulation. 00647 subroutine partmc_exact(file) 00648 00649 !> Spec file. 00650 type(spec_file_t), intent(inout) :: file 00651 00652 character(len=100) :: soln_name 00653 type(aero_data_t) :: aero_data 00654 type(env_data_t) :: env_data 00655 type(env_state_t) :: env_state 00656 type(aero_dist_t) :: aero_dist_init 00657 type(run_exact_opt_t) :: run_exact_opt 00658 type(bin_grid_t) :: bin_grid 00659 type(gas_data_t) :: gas_data 00660 character(len=PMC_MAX_FILENAME_LEN) :: sub_filename 00661 type(spec_file_t) :: sub_file 00662 00663 !> \page input_format_exact Exact (Analytical) Solution 00664 !! 00665 !! The coagulation kernel and initial distribution must be matched 00666 !! for an exact solution to exist. The valid choices are: 00667 !! 00668 !! <table> 00669 !! <tr><th>Coagulation kernel</th> 00670 !! <th>Initial aerosol distribution</th></tr> 00671 !! <tr><td>Additive</td> 00672 !! <td>Single exponential mode</td></tr> 00673 !! <tr><td>Constant</td> 00674 !! <td>Single exponential mode</td></tr> 00675 !! <tr><td>Zero</td> 00676 !! <td>Anything</td></tr> 00677 !! </table> 00678 !! 00679 !! See \ref spec_file_format for the input file text format. 00680 !! 00681 !! An exact (analytical) simulation spec file has the parameters: 00682 !! - \b run_type (string): must be \c exact 00683 !! - \b output_prefix (string): prefix of the output filenames --- 00684 !! the filenames will be of the form \c PREFIX_SSSSSSSS.nc where 00685 !! \c SSSSSSSS is is the eight-digit output index (starting at 1 00686 !! and incremented each time the state is output) 00687 !! - \b t_max (real, unit s): total simulation time 00688 !! - \b t_output (real, unit s): the interval on which to output 00689 !! data to disk and to print progress information to the screen 00690 !! (see \ref output_format) 00691 !! - \subpage input_format_bin_grid 00692 !! - \b gas_data (string): name of file from which to read the 00693 !! gas material data --- the file format should be 00694 !! \subpage input_format_gas_data 00695 !! - \b aerosol_data (string): name of file from which to read the 00696 !! aerosol material data --- the file format should be 00697 !! \subpage input_format_aero_data 00698 !! - \b aerosol_init (string): filename containing the initial 00699 !! aerosol state at the start of the simulation --- the file 00700 !! format should be \subpage input_format_aero_dist 00701 !! - \subpage input_format_env_data 00702 !! - \subpage input_format_env_state 00703 !! - \b do_coagulation (logical): whether to perform particle 00704 !! coagulation. If \c do_coagulation is \c yes, then the 00705 !! following parameters must also be provided: 00706 !! - \subpage input_format_coag_kernel 00707 !! 00708 !! Example: 00709 !! <pre> 00710 !! run_type exact # exact solution 00711 !! output_prefix additive_exact # prefix of output files 00712 !! 00713 !! t_max 600 # total simulation time (s) 00714 !! t_output 60 # output interval (0 disables) (s) 00715 !! 00716 !! n_bin 160 # number of bins 00717 !! d_min 1e-8 # minimum diameter (m) 00718 !! d_max 1e-3 # maximum diameter (m) 00719 !! 00720 !! gas_data gas_data.dat # file containing gas data 00721 !! 00722 !! aerosol_data aero_data.dat # file containing aerosol data 00723 !! aerosol_init aero_init_dist.dat # aerosol initial condition file 00724 !! 00725 !! temp_profile temp.dat # temperature profile file 00726 !! height_profile height.dat # height profile file 00727 !! gas_emissions gas_emit.dat # gas emissions file 00728 !! gas_background gas_back.dat # background gas mixing ratios file 00729 !! aero_emissions aero_emit.dat # aerosol emissions file 00730 !! aero_background aero_back.dat # aerosol background file 00731 !! 00732 !! rel_humidity 0.999 # initial relative humidity (1) 00733 !! pressure 1e5 # initial pressure (Pa) 00734 !! latitude 0 # latitude (degrees, -90 to 90) 00735 !! longitude 0 # longitude (degrees, -180 to 180) 00736 !! altitude 0 # altitude (m) 00737 !! start_time 0 # start time (s since 00:00 UTC) 00738 !! start_day 1 # start day of year (UTC) 00739 !! 00740 !! do_coagulation yes # whether to do coagulation (yes/no) 00741 !! kernel additive # Additive coagulation kernel 00742 !! </pre> 00743 00744 ! only serial code here 00745 if (pmc_mpi_rank() /= 0) then 00746 return 00747 end if 00748 00749 call bin_grid_allocate(bin_grid) 00750 call gas_data_allocate(gas_data) 00751 call aero_data_allocate(aero_data) 00752 call env_data_allocate(env_data) 00753 call env_state_allocate(env_state) 00754 call aero_dist_allocate(aero_dist_init) 00755 00756 call spec_file_read_string(file, 'output_prefix', run_exact_opt%prefix) 00757 00758 call spec_file_read_real(file, 't_max', run_exact_opt%t_max) 00759 call spec_file_read_real(file, 't_output', run_exact_opt%t_output) 00760 00761 call spec_file_read_bin_grid(file, bin_grid) 00762 00763 call spec_file_read_string(file, 'gas_data', sub_filename) 00764 call spec_file_open(sub_filename, sub_file) 00765 call spec_file_read_gas_data(sub_file, gas_data) 00766 call spec_file_close(sub_file) 00767 00768 call spec_file_read_string(file, 'aerosol_data', sub_filename) 00769 call spec_file_open(sub_filename, sub_file) 00770 call spec_file_read_aero_data(sub_file, aero_data) 00771 call spec_file_close(sub_file) 00772 00773 call spec_file_read_string(file, 'aerosol_init', sub_filename) 00774 call spec_file_open(sub_filename, sub_file) 00775 call spec_file_read_aero_dist(sub_file, aero_data, aero_dist_init) 00776 call spec_file_close(sub_file) 00777 00778 call spec_file_read_env_data(file, gas_data, aero_data, env_data) 00779 call spec_file_read_env_state(file, env_state) 00780 00781 call spec_file_read_logical(file, 'do_coagulation', & 00782 run_exact_opt%do_coagulation) 00783 if (run_exact_opt%do_coagulation) then 00784 call spec_file_read_coag_kernel_type(file, & 00785 run_exact_opt%coag_kernel_type) 00786 else 00787 run_exact_opt%coag_kernel_type = COAG_KERNEL_TYPE_INVALID 00788 end if 00789 00790 call spec_file_close(file) 00791 00792 ! finished reading .spec data, now do the run 00793 00794 call pmc_srand(0, 0) 00795 00796 call uuid4_str(run_exact_opt%uuid) 00797 00798 call env_data_init_state(env_data, env_state, 0d0) 00799 00800 call run_exact(bin_grid, env_data, env_state, aero_data, & 00801 aero_dist_init, run_exact_opt) 00802 00803 call aero_data_deallocate(aero_data) 00804 call env_data_deallocate(env_data) 00805 call env_state_deallocate(env_state) 00806 call bin_grid_deallocate(bin_grid) 00807 call gas_data_deallocate(gas_data) 00808 call aero_dist_deallocate(aero_dist_init) 00809 00810 call pmc_rand_finalize() 00811 00812 end subroutine partmc_exact 00813 00814 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00815 00816 !> Run a sectional code simulation. 00817 subroutine partmc_sect(file) 00818 00819 !> Spec file. 00820 type(spec_file_t), intent(inout) :: file 00821 00822 type(run_sect_opt_t) :: run_sect_opt 00823 type(aero_data_t) :: aero_data 00824 type(aero_dist_t) :: aero_dist_init 00825 type(aero_state_t) :: aero_init 00826 type(env_data_t) :: env_data 00827 type(env_state_t) :: env_state 00828 type(bin_grid_t) :: bin_grid 00829 type(gas_data_t) :: gas_data 00830 character(len=PMC_MAX_FILENAME_LEN) :: sub_filename 00831 type(spec_file_t) :: sub_file 00832 00833 !> \page input_format_sectional Sectional Model Simulation 00834 !! 00835 !! See \ref spec_file_format for the input file text format. 00836 !! 00837 !! A sectional simulation spec file has the parameters: 00838 !! - \b run_type (string): must be \c sectional 00839 !! - \b output_prefix (string): prefix of the output filenames --- 00840 !! the filenames will be of the form \c PREFIX_SSSSSSSS.nc where 00841 !! \c SSSSSSSS is is the eight-digit output index (starting at 1 00842 !! and incremented each time the state is output) 00843 !! - \b del_t (real, unit s): timestep size 00844 !! - \b t_output (real, unit s): the interval on which to 00845 !! output data to disk (see \ref output_format) 00846 !! - \b t_progress (real, unit s): the interval on which to 00847 !! write summary information to the screen while running 00848 !! - \subpage input_format_bin_grid 00849 !! - \b gas_data (string): name of file from which to read the 00850 !! gas material data --- the file format should be 00851 !! \subpage input_format_gas_data 00852 !! - \b aerosol_data (string): name of file from which to read the 00853 !! aerosol material data --- the file format should be 00854 !! \subpage input_format_aero_data 00855 !! - \b aerosol_init (string): filename containing the initial 00856 !! aerosol state at the start of the simulation --- the file 00857 !! format should be \subpage input_format_aero_dist 00858 !! - \subpage input_format_env_data 00859 !! - \subpage input_format_env_state 00860 !! - \b do_coagulation (logical): whether to perform particle 00861 !! coagulation. If \c do_coagulation is \c yes, then the 00862 !! following parameters must also be provided: 00863 !! - \subpage input_format_coag_kernel 00864 !! 00865 !! Example: 00866 !! <pre> 00867 !! run_type sectional # sectional code run 00868 !! output_prefix brown_sect # prefix of output files 00869 !! 00870 !! t_max 86400 # total simulation time (s) 00871 !! del_t 60 # timestep (s) 00872 !! t_output 3600 # output interval (0 disables) (s) 00873 !! t_progress 600 # progress printing interval (0 disables) (s) 00874 !! 00875 !! n_bin 220 # number of bins 00876 !! d_min 1e-10 # minimum diameter (m) 00877 !! d_max 1e-4 # maximum diameter (m) 00878 !! 00879 !! gas_data gas_data.dat # file containing gas data 00880 !! aerosol_data aero_data.dat # file containing aerosol data 00881 !! aerosol_init aero_init_dist.dat # initial aerosol distribution 00882 !! 00883 !! temp_profile temp.dat # temperature profile file 00884 !! height_profile height.dat # height profile file 00885 !! gas_emissions gas_emit.dat # gas emissions file 00886 !! gas_background gas_back.dat # background gas mixing ratios file 00887 !! aero_emissions aero_emit.dat # aerosol emissions file 00888 !! aero_background aero_back.dat # aerosol background file 00889 !! 00890 !! rel_humidity 0.999 # initial relative humidity (1) 00891 !! pressure 1e5 # initial pressure (Pa) 00892 !! latitude 0 # latitude (degrees_north, -90 to 90) 00893 !! longitude 0 # longitude (degrees_east, -180 to 180) 00894 !! altitude 0 # altitude (m) 00895 !! start_time 0 # start time (s since 00:00 UTC) 00896 !! start_day 1 # start day of year (UTC) 00897 !! 00898 !! do_coagulation yes # whether to do coagulation (yes/no) 00899 !! kernel brown # coagulation kernel 00900 !! </pre> 00901 00902 ! only serial code here 00903 if (pmc_mpi_rank() /= 0) then 00904 return 00905 end if 00906 00907 call aero_data_allocate(aero_data) 00908 call aero_dist_allocate(aero_dist_init) 00909 call env_state_allocate(env_state) 00910 call env_data_allocate(env_data) 00911 call bin_grid_allocate(bin_grid) 00912 call gas_data_allocate(gas_data) 00913 00914 call spec_file_read_string(file, 'output_prefix', run_sect_opt%prefix) 00915 00916 call spec_file_read_real(file, 't_max', run_sect_opt%t_max) 00917 call spec_file_read_real(file, 'del_t', run_sect_opt%del_t) 00918 call spec_file_read_real(file, 't_output', run_sect_opt%t_output) 00919 call spec_file_read_real(file, 't_progress', run_sect_opt%t_progress) 00920 00921 call spec_file_read_bin_grid(file, bin_grid) 00922 00923 call spec_file_read_string(file, 'gas_data', sub_filename) 00924 call spec_file_open(sub_filename, sub_file) 00925 call spec_file_read_gas_data(sub_file, gas_data) 00926 call spec_file_close(sub_file) 00927 00928 call spec_file_read_string(file, 'aerosol_data', sub_filename) 00929 call spec_file_open(sub_filename, sub_file) 00930 call spec_file_read_aero_data(sub_file, aero_data) 00931 call spec_file_close(sub_file) 00932 00933 call spec_file_read_string(file, 'aerosol_init', sub_filename) 00934 call spec_file_open(sub_filename, sub_file) 00935 call spec_file_read_aero_dist(sub_file, aero_data, aero_dist_init) 00936 call spec_file_close(sub_file) 00937 00938 call spec_file_read_env_data(file, gas_data, aero_data, env_data) 00939 call spec_file_read_env_state(file, env_state) 00940 00941 call spec_file_read_logical(file, 'do_coagulation', & 00942 run_sect_opt%do_coagulation) 00943 if (run_sect_opt%do_coagulation) then 00944 call spec_file_read_coag_kernel_type(file, & 00945 run_sect_opt%coag_kernel_type) 00946 else 00947 run_sect_opt%coag_kernel_type = COAG_KERNEL_TYPE_INVALID 00948 end if 00949 00950 call spec_file_close(file) 00951 00952 ! finished reading .spec data, now do the run 00953 00954 call pmc_srand(0, 0) 00955 00956 call uuid4_str(run_sect_opt%uuid) 00957 00958 call env_data_init_state(env_data, env_state, 0d0) 00959 00960 call run_sect(bin_grid, gas_data, aero_data, aero_dist_init, env_data, & 00961 env_state, run_sect_opt) 00962 00963 call aero_data_deallocate(aero_data) 00964 call aero_dist_deallocate(aero_dist_init) 00965 call env_state_deallocate(env_state) 00966 call env_data_deallocate(env_data) 00967 call bin_grid_deallocate(bin_grid) 00968 call gas_data_deallocate(gas_data) 00969 00970 call pmc_rand_finalize() 00971 00972 end subroutine partmc_sect 00973 00974 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00975 00976 end program partmc