PartMC  2.1.5
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 #ifdef PMC_USE_MPI
00499           if (pmc_mpi_size() > 1) then
00500              call spec_file_die_msg(800768865, file, &
00501                   'running in parallel, but do_parallel is false')
00502           end if
00503 #endif
00504           run_part_opt%output_type = OUTPUT_TYPE_SINGLE
00505           run_part_opt%mix_timescale = 0d0
00506           run_part_opt%gas_average = .false.
00507           run_part_opt%env_average = .false.
00508           run_part_opt%parallel_coag_type = PARALLEL_COAG_TYPE_LOCAL
00509        end if
00510        
00511        call spec_file_close(file)
00512     end if
00513 
00514     ! finished reading .spec data, now broadcast data
00515 
00516     ! initialize RNG with random seed for UUID generation
00517     call pmc_srand(0, pmc_mpi_rank())
00518 
00519     if (.not. do_restart) then
00520        call uuid4_str(run_part_opt%uuid)
00521     end if
00522 
00523 #ifdef PMC_USE_MPI
00524     if (pmc_mpi_rank() == 0) then
00525        ! root process determines size
00526        max_buffer_size = 0
00527        max_buffer_size = max_buffer_size &
00528             + pmc_mpi_pack_size_run_part_opt(run_part_opt)
00529        max_buffer_size = max_buffer_size &
00530             + pmc_mpi_pack_size_bin_grid(bin_grid)
00531        max_buffer_size = max_buffer_size &
00532             + pmc_mpi_pack_size_gas_data(gas_data)
00533        max_buffer_size = max_buffer_size &
00534             + pmc_mpi_pack_size_gas_state(gas_state_init)
00535        max_buffer_size = max_buffer_size &
00536             + pmc_mpi_pack_size_aero_data(aero_data)
00537        max_buffer_size = max_buffer_size &
00538             + pmc_mpi_pack_size_aero_weight(aero_weight)
00539        max_buffer_size = max_buffer_size &
00540             + pmc_mpi_pack_size_aero_dist(aero_dist_init)
00541        max_buffer_size = max_buffer_size &
00542             + pmc_mpi_pack_size_env_data(env_data)
00543        max_buffer_size = max_buffer_size &
00544             + pmc_mpi_pack_size_env_state(env_state_init)
00545        max_buffer_size = max_buffer_size &
00546             + pmc_mpi_pack_size_integer(rand_init)
00547        max_buffer_size = max_buffer_size &
00548             + pmc_mpi_pack_size_logical(do_restart)
00549        max_buffer_size = max_buffer_size &
00550             + pmc_mpi_pack_size_logical(do_init_equilibriate)
00551        max_buffer_size = max_buffer_size &
00552             + pmc_mpi_pack_size_aero_state(aero_state_init)
00553 
00554        allocate(buffer(max_buffer_size))
00555 
00556        position = 0
00557        call pmc_mpi_pack_run_part_opt(buffer, position, run_part_opt)
00558        call pmc_mpi_pack_bin_grid(buffer, position, bin_grid)
00559        call pmc_mpi_pack_gas_data(buffer, position, gas_data)
00560        call pmc_mpi_pack_gas_state(buffer, position, gas_state_init)
00561        call pmc_mpi_pack_aero_data(buffer, position, aero_data)
00562        call pmc_mpi_pack_aero_weight(buffer, position, aero_weight)
00563        call pmc_mpi_pack_aero_dist(buffer, position, aero_dist_init)
00564        call pmc_mpi_pack_env_data(buffer, position, env_data)
00565        call pmc_mpi_pack_env_state(buffer, position, env_state_init)
00566        call pmc_mpi_pack_integer(buffer, position, rand_init)
00567        call pmc_mpi_pack_logical(buffer, position, do_restart)
00568        call pmc_mpi_pack_logical(buffer, position, do_init_equilibriate)
00569        call pmc_mpi_pack_aero_state(buffer, position, aero_state_init)
00570        call assert(181905491, position <= max_buffer_size)
00571        buffer_size = position ! might be less than we allocated
00572     end if
00573 
00574     ! tell everyone the size
00575     call pmc_mpi_bcast_integer(buffer_size)
00576 
00577     if (pmc_mpi_rank() /= 0) then
00578        ! non-root processes allocate space
00579        allocate(buffer(buffer_size))
00580     end if
00581 
00582     ! broadcast data to everyone
00583     call pmc_mpi_bcast_packed(buffer)
00584 
00585     if (pmc_mpi_rank() /= 0) then
00586        ! non-root processes unpack data
00587        position = 0
00588        call pmc_mpi_unpack_run_part_opt(buffer, position, run_part_opt)
00589        call pmc_mpi_unpack_bin_grid(buffer, position, bin_grid)
00590        call pmc_mpi_unpack_gas_data(buffer, position, gas_data)
00591        call pmc_mpi_unpack_gas_state(buffer, position, gas_state_init)
00592        call pmc_mpi_unpack_aero_data(buffer, position, aero_data)
00593        call pmc_mpi_unpack_aero_weight(buffer, position, aero_weight)
00594        call pmc_mpi_unpack_aero_dist(buffer, position, aero_dist_init)
00595        call pmc_mpi_unpack_env_data(buffer, position, env_data)
00596        call pmc_mpi_unpack_env_state(buffer, position, env_state_init)
00597        call pmc_mpi_unpack_integer(buffer, position, rand_init)
00598        call pmc_mpi_unpack_logical(buffer, position, do_restart)
00599        call pmc_mpi_unpack_logical(buffer, position, do_init_equilibriate)
00600        call pmc_mpi_unpack_aero_state(buffer, position, aero_state_init)
00601        call assert(143770146, position == buffer_size)
00602     end if
00603 
00604     ! free the buffer
00605     deallocate(buffer)
00606 #endif
00607 
00608     ! re-initialize RNG with the given seed
00609     call pmc_rand_finalize()
00610     call pmc_srand(rand_init, pmc_mpi_rank())
00611 
00612     call gas_state_deallocate(gas_state)
00613     call gas_state_allocate_size(gas_state, gas_data%n_spec)
00614     call cpu_time(run_part_opt%t_wall_start)
00615     
00616     do i_repeat = 1,run_part_opt%n_repeat
00617        run_part_opt%i_repeat = i_repeat
00618        
00619        call gas_state_copy(gas_state_init, gas_state)
00620        if (do_restart) then
00621           call aero_state_copy(aero_state_init, aero_state)
00622        else
00623           call aero_state_deallocate(aero_state)
00624           call aero_state_allocate_size(aero_state, bin_grid%n_bin, &
00625                aero_data%n_spec, aero_data%n_source)
00626           aero_state%comp_vol = real(run_part_opt%n_part_ideal, kind=dp) / 
00627                aero_dist_weighted_num_conc(aero_dist_init, aero_weight)
00628           call aero_state_add_aero_dist_sample(aero_state, bin_grid, &
00629                aero_data, aero_weight, aero_dist_init, 1d0, 0d0)
00630        end if
00631        call env_state_copy(env_state_init, env_state)
00632        call env_data_init_state(env_data, env_state, &
00633             env_state_init%elapsed_time)
00634 
00635 #ifdef PMC_USE_SUNDIALS
00636        if (do_init_equilibriate) then
00637           call condense_equilib_particles(bin_grid, env_state, aero_data, &
00638                aero_weight, aero_state)
00639        end if
00640 #endif
00641        
00642        call run_part(bin_grid, env_data, env_state, aero_data, aero_weight, &
00643             aero_state, gas_data, gas_state, run_part_opt)
00644 
00645     end do
00646 
00647     call gas_data_deallocate(gas_data)
00648     call gas_state_deallocate(gas_state)
00649     call gas_state_deallocate(gas_state_init)
00650     call aero_data_deallocate(aero_data)
00651     call aero_weight_deallocate(aero_weight)
00652     call aero_dist_deallocate(aero_dist_init)
00653     call aero_state_deallocate(aero_state)
00654     call aero_state_deallocate(aero_state_init)
00655     call env_data_deallocate(env_data)
00656     call env_state_deallocate(env_state)
00657     call env_state_deallocate(env_state_init)
00658     call bin_grid_deallocate(bin_grid)
00659 
00660     call pmc_rand_finalize()
00661 
00662   end subroutine partmc_part
00663 
00664 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00665 
00666   !> Run an exact solution simulation.
00667   subroutine partmc_exact(file)
00668 
00669     !> Spec file.
00670     type(spec_file_t), intent(inout) :: file
00671 
00672     character(len=100) :: soln_name
00673     type(aero_data_t) :: aero_data
00674     type(env_data_t) :: env_data
00675     type(env_state_t) :: env_state
00676     type(aero_dist_t) :: aero_dist_init
00677     type(run_exact_opt_t) :: run_exact_opt
00678     type(bin_grid_t) :: bin_grid
00679     type(gas_data_t) :: gas_data
00680     character(len=PMC_MAX_FILENAME_LEN) :: sub_filename
00681     type(spec_file_t) :: sub_file
00682 
00683     !> \page input_format_exact Exact (Analytical) Solution
00684     !!
00685     !! The coagulation kernel and initial distribution must be matched
00686     !! for an exact solution to exist. The valid choices are:
00687     !!
00688     !! <table>
00689     !! <tr><th>Coagulation kernel</th>
00690     !!     <th>Initial aerosol distribution</th></tr>
00691     !! <tr><td>Additive</td>
00692     !!     <td>Single exponential mode</td></tr>
00693     !! <tr><td>Constant</td>
00694     !!     <td>Single exponential mode</td></tr>
00695     !! <tr><td>Zero</td>
00696     !!     <td>Anything</td></tr>
00697     !! </table>
00698     !!
00699     !! See \ref spec_file_format for the input file text format.
00700     !!
00701     !! An exact (analytical) simulation spec file has the parameters:
00702     !! - \b run_type (string): must be \c exact
00703     !! - \b output_prefix (string): prefix of the output filenames ---
00704     !!   the filenames will be of the form \c PREFIX_SSSSSSSS.nc where
00705     !!   \c SSSSSSSS is is the eight-digit output index (starting at 1
00706     !!   and incremented each time the state is output)
00707     !! - \b t_max (real, unit s): total simulation time
00708     !! - \b t_output (real, unit s): the interval on which to output
00709     !!   data to disk and to print progress information to the screen
00710     !!   (see \ref output_format)
00711     !! - \subpage input_format_bin_grid
00712     !! - \b gas_data (string): name of file from which to read the
00713     !!   gas material data --- the file format should be
00714     !!   \subpage input_format_gas_data
00715     !! - \b aerosol_data (string): name of file from which to read the
00716     !!   aerosol material data --- the file format should be
00717     !!   \subpage input_format_aero_data
00718     !! - \b aerosol_init (string): filename containing the initial
00719     !!   aerosol state at the start of the simulation --- the file
00720     !!   format should be \subpage input_format_aero_dist
00721     !! - \subpage input_format_env_data
00722     !! - \subpage input_format_env_state
00723     !! - \b do_coagulation (logical): whether to perform particle
00724     !!   coagulation.  If \c do_coagulation is \c yes, then the
00725     !!   following parameters must also be provided:
00726     !!   - \subpage input_format_coag_kernel
00727     !!
00728     !! Example:
00729     !! <pre>
00730     !! run_type exact                  # exact solution
00731     !! output_prefix additive_exact    # prefix of output files
00732     !! 
00733     !! t_max 600                       # total simulation time (s)
00734     !! t_output 60                     # output interval (0 disables) (s)
00735     !! 
00736     !! n_bin 160                       # number of bins
00737     !! d_min 1e-8                      # minimum diameter (m)
00738     !! d_max 1e-3                      # maximum diameter (m)
00739     !! 
00740     !! gas_data gas_data.dat           # file containing gas data
00741     !!
00742     !! aerosol_data aero_data.dat      # file containing aerosol data
00743     !! aerosol_init aero_init_dist.dat # aerosol initial condition file
00744     !! 
00745     !! temp_profile temp.dat           # temperature profile file
00746     !! height_profile height.dat       # height profile file
00747     !! gas_emissions gas_emit.dat      # gas emissions file
00748     !! gas_background gas_back.dat     # background gas mixing ratios file
00749     !! aero_emissions aero_emit.dat    # aerosol emissions file
00750     !! aero_background aero_back.dat   # aerosol background file
00751     !! 
00752     !! rel_humidity 0.999              # initial relative humidity (1)
00753     !! pressure 1e5                    # initial pressure (Pa)
00754     !! latitude 0                      # latitude (degrees, -90 to 90)
00755     !! longitude 0                     # longitude (degrees, -180 to 180)
00756     !! altitude 0                      # altitude (m)
00757     !! start_time 0                    # start time (s since 00:00 UTC)
00758     !! start_day 1                     # start day of year (UTC)
00759     !!
00760     !! do_coagulation yes              # whether to do coagulation (yes/no)
00761     !! kernel additive                 # Additive coagulation kernel
00762     !! </pre>
00763 
00764     ! only serial code here
00765     if (pmc_mpi_rank() /= 0) then
00766        return
00767     end if
00768     
00769     call bin_grid_allocate(bin_grid)
00770     call gas_data_allocate(gas_data)
00771     call aero_data_allocate(aero_data)
00772     call env_data_allocate(env_data)
00773     call env_state_allocate(env_state)
00774     call aero_dist_allocate(aero_dist_init)
00775 
00776     call spec_file_read_string(file, 'output_prefix', run_exact_opt%prefix)
00777 
00778     call spec_file_read_real(file, 't_max', run_exact_opt%t_max)
00779     call spec_file_read_real(file, 't_output', run_exact_opt%t_output)
00780 
00781     call spec_file_read_bin_grid(file, bin_grid)
00782 
00783     call spec_file_read_string(file, 'gas_data', sub_filename)
00784     call spec_file_open(sub_filename, sub_file)
00785     call spec_file_read_gas_data(sub_file, gas_data)
00786     call spec_file_close(sub_file)
00787 
00788     call spec_file_read_string(file, 'aerosol_data', sub_filename)
00789     call spec_file_open(sub_filename, sub_file)
00790     call spec_file_read_aero_data(sub_file, aero_data)
00791     call spec_file_close(sub_file)
00792 
00793     call spec_file_read_string(file, 'aerosol_init', sub_filename)
00794     call spec_file_open(sub_filename, sub_file)
00795     call spec_file_read_aero_dist(sub_file, aero_data, aero_dist_init)
00796     call spec_file_close(sub_file)
00797 
00798     call spec_file_read_env_data(file, bin_grid, gas_data, aero_data, &
00799          env_data)
00800     call spec_file_read_env_state(file, env_state)
00801 
00802     call spec_file_read_logical(file, 'do_coagulation', &
00803          run_exact_opt%do_coagulation)
00804     if (run_exact_opt%do_coagulation) then
00805        call spec_file_read_coag_kernel_type(file, &
00806             run_exact_opt%coag_kernel_type)
00807     else
00808        run_exact_opt%coag_kernel_type = COAG_KERNEL_TYPE_INVALID
00809     end if
00810     
00811     call spec_file_close(file)
00812 
00813     ! finished reading .spec data, now do the run
00814 
00815     call pmc_srand(0, 0)
00816 
00817     call uuid4_str(run_exact_opt%uuid)
00818 
00819     call env_data_init_state(env_data, env_state, 0d0)
00820 
00821     call run_exact(bin_grid, env_data, env_state, aero_data, &
00822          aero_dist_init, run_exact_opt)
00823 
00824     call aero_data_deallocate(aero_data)
00825     call env_data_deallocate(env_data)
00826     call env_state_deallocate(env_state)
00827     call bin_grid_deallocate(bin_grid)
00828     call gas_data_deallocate(gas_data)
00829     call aero_dist_deallocate(aero_dist_init)
00830 
00831     call pmc_rand_finalize()
00832 
00833   end subroutine partmc_exact
00834 
00835 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00836 
00837   !> Run a sectional code simulation.
00838   subroutine partmc_sect(file)
00839 
00840     !> Spec file.
00841     type(spec_file_t), intent(inout) :: file
00842 
00843     type(run_sect_opt_t) :: run_sect_opt
00844     type(aero_data_t) :: aero_data
00845     type(aero_dist_t) :: aero_dist_init
00846     type(aero_state_t) :: aero_init
00847     type(env_data_t) :: env_data
00848     type(env_state_t) :: env_state
00849     type(bin_grid_t) :: bin_grid
00850     type(gas_data_t) :: gas_data
00851     character(len=PMC_MAX_FILENAME_LEN) :: sub_filename
00852     type(spec_file_t) :: sub_file
00853 
00854     !> \page input_format_sectional Sectional Model Simulation
00855     !!
00856     !! See \ref spec_file_format for the input file text format.
00857     !!
00858     !! A sectional simulation spec file has the parameters:
00859     !! - \b run_type (string): must be \c sectional
00860     !! - \b output_prefix (string): prefix of the output filenames ---
00861     !!   the filenames will be of the form \c PREFIX_SSSSSSSS.nc where
00862     !!   \c SSSSSSSS is is the eight-digit output index (starting at 1
00863     !!   and incremented each time the state is output)
00864     !! - \b del_t (real, unit s): timestep size
00865     !! - \b t_output (real, unit s): the interval on which to
00866     !!   output data to disk (see \ref output_format)
00867     !! - \b t_progress (real, unit s): the interval on which to
00868     !!   write summary information to the screen while running
00869     !! - \subpage input_format_bin_grid
00870     !! - \b gas_data (string): name of file from which to read the
00871     !!   gas material data --- the file format should be
00872     !!   \subpage input_format_gas_data
00873     !! - \b aerosol_data (string): name of file from which to read the
00874     !!   aerosol material data --- the file format should be
00875     !!   \subpage input_format_aero_data
00876     !! - \b aerosol_init (string): filename containing the initial
00877     !!   aerosol state at the start of the simulation --- the file
00878     !!   format should be \subpage input_format_aero_dist
00879     !! - \subpage input_format_env_data
00880     !! - \subpage input_format_env_state
00881     !! - \b do_coagulation (logical): whether to perform particle
00882     !!   coagulation.  If \c do_coagulation is \c yes, then the
00883     !!   following parameters must also be provided:
00884     !!   - \subpage input_format_coag_kernel
00885     !!
00886     !! Example:
00887     !! <pre>
00888     !! run_type sectional              # sectional code run
00889     !! output_prefix brown_sect        # prefix of output files
00890     !! 
00891     !! t_max 86400                     # total simulation time (s)
00892     !! del_t 60                        # timestep (s)
00893     !! t_output 3600                   # output interval (0 disables) (s)
00894     !! t_progress 600                  # progress printing interval (0 disables) (s)
00895     !! 
00896     !! n_bin 220                       # number of bins
00897     !! d_min 1e-10                     # minimum diameter (m)
00898     !! d_max 1e-4                      # maximum diameter (m)
00899     !! 
00900     !! gas_data gas_data.dat           # file containing gas data
00901     !! aerosol_data aero_data.dat      # file containing aerosol data
00902     !! aerosol_init aero_init_dist.dat # initial aerosol distribution
00903     !! 
00904     !! temp_profile temp.dat           # temperature profile file
00905     !! height_profile height.dat       # height profile file
00906     !! gas_emissions gas_emit.dat      # gas emissions file
00907     !! gas_background gas_back.dat     # background gas mixing ratios file
00908     !! aero_emissions aero_emit.dat    # aerosol emissions file
00909     !! aero_background aero_back.dat   # aerosol background file
00910     !! 
00911     !! rel_humidity 0.999              # initial relative humidity (1)
00912     !! pressure 1e5                    # initial pressure (Pa)
00913     !! latitude 0                      # latitude (degrees_north, -90 to 90)
00914     !! longitude 0                     # longitude (degrees_east, -180 to 180)
00915     !! altitude 0                      # altitude (m)
00916     !! start_time 0                    # start time (s since 00:00 UTC)
00917     !! start_day 1                     # start day of year (UTC)
00918     !! 
00919     !! do_coagulation yes              # whether to do coagulation (yes/no)
00920     !! kernel brown                    # coagulation kernel
00921     !! </pre>
00922 
00923     ! only serial code here
00924     if (pmc_mpi_rank() /= 0) then
00925        return
00926     end if
00927     
00928     call aero_data_allocate(aero_data)
00929     call aero_dist_allocate(aero_dist_init)
00930     call env_state_allocate(env_state)
00931     call env_data_allocate(env_data)
00932     call bin_grid_allocate(bin_grid)
00933     call gas_data_allocate(gas_data)
00934 
00935     call spec_file_read_string(file, 'output_prefix', run_sect_opt%prefix)
00936 
00937     call spec_file_read_real(file, 't_max', run_sect_opt%t_max)
00938     call spec_file_read_real(file, 'del_t', run_sect_opt%del_t)
00939     call spec_file_read_real(file, 't_output', run_sect_opt%t_output)
00940     call spec_file_read_real(file, 't_progress', run_sect_opt%t_progress)
00941 
00942     call spec_file_read_bin_grid(file, bin_grid)
00943 
00944     call spec_file_read_string(file, 'gas_data', sub_filename)
00945     call spec_file_open(sub_filename, sub_file)
00946     call spec_file_read_gas_data(sub_file, gas_data)
00947     call spec_file_close(sub_file)
00948     
00949     call spec_file_read_string(file, 'aerosol_data', sub_filename)
00950     call spec_file_open(sub_filename, sub_file)
00951     call spec_file_read_aero_data(sub_file, aero_data)
00952     call spec_file_close(sub_file)
00953 
00954     call spec_file_read_string(file, 'aerosol_init', sub_filename)
00955     call spec_file_open(sub_filename, sub_file)
00956     call spec_file_read_aero_dist(sub_file, aero_data, aero_dist_init)
00957     call spec_file_close(sub_file)
00958 
00959     call spec_file_read_env_data(file, bin_grid, gas_data, aero_data, &
00960          env_data)
00961     call spec_file_read_env_state(file, env_state)
00962 
00963     call spec_file_read_logical(file, 'do_coagulation', &
00964          run_sect_opt%do_coagulation)
00965     if (run_sect_opt%do_coagulation) then
00966        call spec_file_read_coag_kernel_type(file, &
00967             run_sect_opt%coag_kernel_type)
00968     else
00969        run_sect_opt%coag_kernel_type = COAG_KERNEL_TYPE_INVALID
00970     end if
00971     
00972     call spec_file_close(file)
00973 
00974     ! finished reading .spec data, now do the run
00975 
00976     call pmc_srand(0, 0)
00977 
00978     call uuid4_str(run_sect_opt%uuid)
00979 
00980     call env_data_init_state(env_data, env_state, 0d0)
00981 
00982     call run_sect(bin_grid, gas_data, aero_data, aero_dist_init, env_data, &
00983          env_state, run_sect_opt)
00984 
00985     call aero_data_deallocate(aero_data)
00986     call aero_dist_deallocate(aero_dist_init)
00987     call env_state_deallocate(env_state)
00988     call env_data_deallocate(env_data)
00989     call bin_grid_deallocate(bin_grid)
00990     call gas_data_deallocate(gas_data)
00991 
00992     call pmc_rand_finalize()
00993     
00994   end subroutine partmc_sect
00995 
00996 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00997 
00998 end program partmc