PartMC  2.2.0
partmc.F90
Go to the documentation of this file.
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 &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;A.&nbsp;Zaveri, J.&nbsp;C.&nbsp;Barnard,
00106 !!     R.&nbsp;C.&nbsp;Easter, N.&nbsp;Riemer, and M.&nbsp;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.&nbsp;Riemer, M.&nbsp;West, R.&nbsp;A.&nbsp;Zaveri, and
00113 !!     R.&nbsp;C.&nbsp;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.&nbsp;Riemer, M.&nbsp;West, R.&nbsp;A.&nbsp;Zaveri, and
00118 !!     R.&nbsp;C.&nbsp;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.&nbsp;McGraw, L.&nbsp;Leng, W.&nbsp;Zhu, N.&nbsp;Riemer, and
00123 !!     M.&nbsp;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