PartMC  2.2.1
partmc.F90
Go to the documentation of this file.
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 &lt;type&gt;
00035 !! </pre>
00036 !! where <tt>&lt;type&gt;</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.&nbsp;E.&nbsp;L.&nbsp;DeVille, N.&nbsp;Riemer, and
00106 !!     M.&nbsp;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.&nbsp;A.&nbsp;Zaveri, J.&nbsp;C.&nbsp;Barnard,
00111 !!     R.&nbsp;C.&nbsp;Easter, N.&nbsp;Riemer, and M.&nbsp;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.&nbsp;Riemer, M.&nbsp;West, R.&nbsp;A.&nbsp;Zaveri, and
00118 !!     R.&nbsp;C.&nbsp;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.&nbsp;Riemer, M.&nbsp;West, R.&nbsp;A.&nbsp;Zaveri, and
00123 !!     R.&nbsp;C.&nbsp;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.&nbsp;McGraw, L.&nbsp;Leng, W.&nbsp;Zhu, N.&nbsp;Riemer, and
00128 !!     M.&nbsp;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