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