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