PartMC 2.1.4
|
00001 ! Copyright (C) 2005-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 pmc_output module. 00007 00008 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00009 00010 !> \page output_format Output File Format 00011 !! 00012 !! PartMC output files are in the <a 00013 !! href="http://www.unidata.ucar.edu/software/netcdf/">NetCDF Classic 00014 !! Format</a> (also known as NetCDF-3 format). The dimensions and 00015 !! variables in the files will depend on the type of run (particle, 00016 !! analytical solution, etc), and options in the spec file (e.g. \c 00017 !! record_removals and \c do_optical). 00018 !! 00019 !! The state of the simulation is periodically output during the run, 00020 !! with frequency determined by the \c t_output input parameter. Each 00021 !! output file has a filename of the form \c PREFIX_RRRR_SSSSSSSS.nc, 00022 !! where \c PREFIX is given by the \c output_prefix input parameter, 00023 !! \c RRRR is the four-digit repeat number (starting from 1), and \c 00024 !! SSSSSSSS is the eight-digit output index (starting at 1 and 00025 !! incremented each time the state is output). For exact and sectional 00026 !! simulations all repeats would be identical so there is no support 00027 !! for repeating and the filename is of the format \c 00028 !! PREFIX_SSSSSSSS.nc. 00029 !! 00030 !! If run in parallel and \c output_type is \c central or \c dist, 00031 !! then the output files have names like \c 00032 !! PREFIX_RRRR_PPPP_SSSSSSSS.nc, where \c PPPP is a four-digit 00033 !! process number (starting from 1) and the other variables are as 00034 !! above. If \c output_type is \c single then the output file naming 00035 !! scheme as the same as for serial runs. 00036 !! 00037 !! The data in each output file comes in several different groups, as 00038 !! follows: 00039 !! 00040 !! \subpage output_format_general "General Information" 00041 !! 00042 !! \subpage output_format_env_state "Environment State" 00043 !! 00044 !! \subpage output_format_gas_data "Gas Material Data" 00045 !! 00046 !! \subpage output_format_gas_state "Gas State" 00047 !! 00048 !! \subpage output_format_aero_data "Aerosol Material Data" 00049 !! 00050 !! \subpage output_format_aero_state "Aerosol Particle State" 00051 !! (only for particle-resolved simulations) 00052 !! 00053 !! \subpage output_format_aero_removed "Aerosol Particle Removal Information" 00054 !! (only for particle-resolved simulations, if \c record_removals is \c yes) 00055 !! 00056 !! \subpage output_format_aero_weight "Aerosol Weighting Function" 00057 !! (only for particle-resolved simulations) 00058 !! 00059 !! \subpage output_format_bin_grid "Bin Grid Data" 00060 !! (only for exact and sectional simulations) 00061 !! 00062 !! \subpage output_format_aero_binned "Aerosol Binned Sectional State" 00063 !! (only for exact and sectional simulations) 00064 00065 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00066 00067 !> Write data in NetCDF format. 00068 module pmc_output 00069 00070 use pmc_bin_grid 00071 use pmc_aero_data 00072 use pmc_aero_state 00073 use pmc_aero_binned 00074 use pmc_netcdf 00075 use pmc_env_state 00076 use pmc_util 00077 use pmc_gas_data 00078 use pmc_mpi 00079 #ifdef PMC_USE_MPI 00080 use mpi 00081 #endif 00082 00083 !> Type code for undefined or invalid output. 00084 integer, parameter :: OUTPUT_TYPE_INVALID = 0 00085 !> Type code for centralized output (one file per process, all written 00086 !> by process 0). 00087 integer, parameter :: OUTPUT_TYPE_CENTRAL = 1 00088 !> Type code for distributed output (one file per process, written by 00089 !> each process). 00090 integer, parameter :: OUTPUT_TYPE_DIST = 2 00091 !> Type code for single output (one file for all processes, written by 00092 !> process 0). 00093 integer, parameter :: OUTPUT_TYPE_SINGLE = 3 00094 00095 !> Internal-use variable only. 00096 integer, parameter :: TAG_OUTPUT_STATE_CENTRAL = 4341 00097 !> Internal-use variable only. 00098 integer, parameter :: TAG_OUTPUT_STATE_SINGLE = 4342 00099 00100 contains 00101 00102 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00103 00104 !> Write the current state. 00105 subroutine output_state(prefix, output_type, bin_grid, aero_data, & 00106 aero_weight, aero_state, gas_data, gas_state, env_state, index, & 00107 time, del_t, i_repeat, record_removals, record_optical, uuid) 00108 00109 !> Prefix of state file. 00110 character(len=*), intent(in) :: prefix 00111 !> Output type for parallel runs (see module constants). 00112 integer, intent(in) :: output_type 00113 !> Bin grid. 00114 type(bin_grid_t), intent(in) :: bin_grid 00115 !> Aerosol data. 00116 type(aero_data_t), intent(in) :: aero_data 00117 !> Aerosol weight. 00118 type(aero_weight_t), intent(in) :: aero_weight 00119 !> Aerosol state. 00120 type(aero_state_t), intent(in) :: aero_state 00121 !> Gas data. 00122 type(gas_data_t), intent(in) :: gas_data 00123 !> Gas state. 00124 type(gas_state_t), intent(in) :: gas_state 00125 !> Environment state. 00126 type(env_state_t), intent(in) :: env_state 00127 !> Filename index. 00128 integer, intent(in) :: index 00129 !> Current time (s). 00130 real(kind=dp), intent(in) :: time 00131 !> Current timestep (s). 00132 real(kind=dp), intent(in) :: del_t 00133 !> Current repeat number. 00134 integer, intent(in) :: i_repeat 00135 !> Whether to output particle removal info. 00136 logical, intent(in) :: record_removals 00137 !> Whether to output aerosol optical properties. 00138 logical, intent(in) :: record_optical 00139 !> UUID of the simulation. 00140 character(len=PMC_UUID_LEN), intent(in) :: uuid 00141 00142 integer :: rank, n_proc 00143 #ifdef PMC_USE_MPI 00144 type(env_state_t) :: env_state_write 00145 type(gas_state_t) :: gas_state_write 00146 type(aero_state_t) :: aero_state_write 00147 integer :: ierr, status(MPI_STATUS_SIZE), i_proc, position 00148 character, allocatable :: buffer(:) 00149 #endif 00150 00151 rank = pmc_mpi_rank() 00152 n_proc = pmc_mpi_size() 00153 if (output_type == OUTPUT_TYPE_CENTRAL) then 00154 ! write per-process data to separate files, but do it by 00155 ! transferring data to process 0 and having it do the writes 00156 if (rank == 0) then 00157 call output_state_to_file(prefix, bin_grid, aero_data, & 00158 aero_weight, aero_state, gas_data, gas_state, env_state, & 00159 index, time, del_t, i_repeat, record_removals, & 00160 record_optical, rank, n_proc, uuid) 00161 #ifdef PMC_USE_MPI 00162 do i_proc = 1,(n_proc - 1) 00163 call recv_output_state_central(prefix, bin_grid, & 00164 aero_data, aero_weight, gas_data, index, time, del_t, & 00165 i_repeat, record_removals, record_optical, uuid, i_proc) 00166 end do 00167 #endif 00168 else ! rank /= 0 00169 call send_output_state_central(aero_state, gas_state, env_state) 00170 end if 00171 elseif (output_type == OUTPUT_TYPE_DIST) then 00172 ! have each process write its own data directly 00173 call output_state_to_file(prefix, bin_grid, aero_data, & 00174 aero_weight, aero_state, gas_data, gas_state, env_state, & 00175 index, time, del_t, i_repeat, record_removals, record_optical, & 00176 rank, n_proc, uuid) 00177 elseif (output_type == OUTPUT_TYPE_SINGLE) then 00178 if (n_proc == 1) then 00179 call output_state_to_file(prefix, bin_grid, aero_data, & 00180 aero_weight, aero_state, gas_data, gas_state, & 00181 env_state, index, time, del_t, i_repeat, & 00182 record_removals, record_optical, rank, n_proc, uuid) 00183 else 00184 #ifdef PMC_USE_MPI 00185 ! collect all data onto process 0 and then write it to a 00186 ! single file 00187 call env_state_allocate(env_state_write) 00188 call gas_state_allocate(gas_state_write) 00189 call env_state_copy(env_state, env_state_write) 00190 call gas_state_copy(gas_state, gas_state_write) 00191 call env_state_reduce_avg(env_state_write) 00192 call gas_state_reduce_avg(gas_state_write) 00193 call aero_state_allocate(aero_state_write) 00194 call aero_state_mpi_gather(aero_state, aero_state_write) 00195 if (rank == 0) then 00196 call output_state_to_file(prefix, bin_grid, aero_data, & 00197 aero_weight, aero_state_write, gas_data, gas_state_write, & 00198 env_state_write, index, time, del_t, i_repeat, & 00199 record_removals, record_optical, rank, 1, uuid) 00200 end if 00201 call aero_state_deallocate(aero_state_write) 00202 call env_state_deallocate(env_state_write) 00203 call gas_state_deallocate(gas_state_write) 00204 #endif 00205 end if 00206 else 00207 call die_msg(626743323, "Unknown output_type: " & 00208 // trim(integer_to_string(output_type))) 00209 end if 00210 00211 end subroutine output_state 00212 00213 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00214 00215 !> Helper routine to write various global attributes. Do not call 00216 !> directly. 00217 subroutine write_header_and_time(ncid, time, del_t, index, uuid) 00218 00219 !> NetCDF file ID, in data mode. 00220 integer, intent(in) :: ncid 00221 !> Current time (s). 00222 real(kind=dp), intent(in) :: time 00223 !> Current timestep (s). 00224 real(kind=dp), intent(in) :: del_t 00225 !> Filename index. 00226 integer, intent(in) :: index 00227 !> UUID of the simulation. 00228 character(len=PMC_UUID_LEN), intent(in) :: uuid 00229 00230 character(len=500) :: history 00231 00232 call pmc_nc_check(nf90_redef(ncid)) 00233 00234 call pmc_nc_check(nf90_put_att(ncid, NF90_GLOBAL, "source", & 00235 "PartMC version 2.1.4")) 00236 call pmc_nc_check(nf90_put_att(ncid, NF90_GLOBAL, "UUID", uuid)) 00237 call iso8601_date_and_time(history) 00238 history((len_trim(history)+1):) = " created by PartMC" 00239 call pmc_nc_check(nf90_put_att(ncid, NF90_GLOBAL, "history", history)) 00240 call pmc_nc_check(nf90_put_att(ncid, NF90_GLOBAL, "Conventions", & 00241 "CF-1.4")) 00242 00243 call pmc_nc_check(nf90_enddef(ncid)) 00244 00245 call pmc_nc_write_real(ncid, time, "time", unit="s", & 00246 description="time elapsed since simulation start") 00247 call pmc_nc_write_real(ncid, del_t, "timestep", unit="s", & 00248 description="current timestep size") 00249 call pmc_nc_write_integer(ncid, index, "timestep_index", & 00250 description="an integer that is 1 on the first timestep, " & 00251 // "2 on the second timestep, etc.") 00252 00253 end subroutine write_header_and_time 00254 00255 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00256 00257 !> Write the current state for a single process. Do not call this 00258 !> subroutine directly, but rather call output_state(). 00259 subroutine output_state_to_file(prefix, bin_grid, aero_data, & 00260 aero_weight, aero_state, gas_data, gas_state, env_state, index, & 00261 time, del_t, i_repeat, record_removals, record_optical, write_rank, & 00262 write_n_proc, uuid) 00263 00264 !> Prefix of state file. 00265 character(len=*), intent(in) :: prefix 00266 !> Bin grid. 00267 type(bin_grid_t), intent(in) :: bin_grid 00268 !> Aerosol data. 00269 type(aero_data_t), intent(in) :: aero_data 00270 !> Aerosol weight. 00271 type(aero_weight_t), intent(in) :: aero_weight 00272 !> Aerosol state. 00273 type(aero_state_t), intent(in) :: aero_state 00274 !> Gas data. 00275 type(gas_data_t), intent(in) :: gas_data 00276 !> Gas state. 00277 type(gas_state_t), intent(in) :: gas_state 00278 !> Environment state. 00279 type(env_state_t), intent(in) :: env_state 00280 !> Filename index. 00281 integer, intent(in) :: index 00282 !> Current time (s). 00283 real(kind=dp), intent(in) :: time 00284 !> Current timestep (s). 00285 real(kind=dp), intent(in) :: del_t 00286 !> Current repeat number. 00287 integer, intent(in) :: i_repeat 00288 !> Whether to output particle removal info. 00289 logical, intent(in) :: record_removals 00290 !> Whether to output aerosol optical properties. 00291 logical, intent(in) :: record_optical 00292 !> Rank to write into file. 00293 integer, intent(in) :: write_rank 00294 !> Number of processes to write into file. 00295 integer, intent(in) :: write_n_proc 00296 !> UUID of the simulation. 00297 character(len=PMC_UUID_LEN), intent(in) :: uuid 00298 00299 character(len=len(prefix)+100) :: filename 00300 integer :: ncid 00301 00302 #ifdef PMC_USE_MPI 00303 if (write_n_proc > 1) then 00304 write(filename, '(a,a,i4.4,a,i4.4,a,i8.8,a)') trim(prefix), & 00305 '_', i_repeat, '_', (write_rank + 1), '_', index, '.nc' 00306 else 00307 write(filename, '(a,a,i4.4,a,i8.8,a)') trim(prefix), & 00308 '_', i_repeat, '_', index, '.nc' 00309 end if 00310 #else 00311 write(filename, '(a,a,i4.4,a,i8.8,a)') trim(prefix), & 00312 '_', i_repeat, '_', index, '.nc' 00313 #endif 00314 call pmc_nc_check_msg(nf90_create(filename, NF90_CLOBBER, ncid), & 00315 "opening " // trim(filename)) 00316 00317 !> \page output_format_general Output File Format: General Information 00318 !! 00319 !! The general information global NetCDF attributes are: 00320 !! - \b title: always set to the string "PartMC output file" 00321 !! - \b source: set to the string "PartMC version V.V.V" where V.V.V 00322 !! is the PartMC version that created the file 00323 !! - \b UUID: a string of the form F47AC10B-58CC-4372-A567-0E02B2C3D479 00324 !! which is the same for all files generated by a single call of 00325 !! PartMC. 00326 !! - \b Conventions: set to the string "CF-1.4", indicating 00327 !! compliance with the <a 00328 !! href="http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.4">CF 00329 !! convention format</a> 00330 !! - \b history: set to the string 00331 !! "YYYY-MM-DDThh:mm:ss[+-]ZZ:zz created by PartMC" where the first 00332 !! term is the file creation time in the 00333 !! <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO 8601 00334 !! format</a>. For example, noon Pacific Standard Time (PST) on 00335 !! February 1st, 2000 would be written 2000-02-01T12:00:00-08:00. 00336 !! The date and time variables are: 00337 !! - YYYY: four-digit year 00338 !! - MM: two-digit month number 00339 !! - DD: two-digit day within month 00340 !! - T: literal "T" character 00341 !! - hh: two-digit hour in 24-hour format 00342 !! - mm: two-digit minute 00343 !! - ss: two-digit second 00344 !! - [+-]: a literal "+" or "-" character giving the time zone 00345 !! offset sign 00346 !! - ZZ: two-digit hours of the time zone offset from UTC 00347 !! - zz: two-digit minutes of the time zone offset from UTC 00348 !! 00349 !! The general information NetCDF variables are: 00350 !! - \b time (unit s): time elapsed since the simulation start time, 00351 !! as specified in the \ref output_format_env_state section 00352 !! - \b timestep (unit s): the current timestep size 00353 !! - \b repeat: the repeat number of this simulation (starting from 1) 00354 !! - \b timestep_index: an integer that is 1 on the first timestep, 2 00355 !! on the second timestep, etc. 00356 !! - \b process (MPI only): the process number (starting from 1) 00357 !! that output this data file 00358 !! - \b total_processes (MPI only): the total number of processes 00359 !! involved in writing data (may be less than the total number of 00360 !! processes that computed the data) 00361 00362 call pmc_nc_check(nf90_put_att(ncid, NF90_GLOBAL, "title", & 00363 "PartMC output file")) 00364 call pmc_nc_check(nf90_enddef(ncid)) 00365 00366 call write_header_and_time(ncid, time, del_t, index, uuid) 00367 call pmc_nc_write_integer(ncid, i_repeat, "repeat", & 00368 description="repeat repeat number of this simulation " & 00369 // "(starting from 1)") 00370 #ifdef PMC_USE_MPI 00371 call pmc_nc_write_integer(ncid, write_rank + 1, "process", & 00372 description="the process number (starting from 1) " & 00373 // "that output this data file") 00374 call pmc_nc_write_integer(ncid, write_n_proc, "total_processes", & 00375 description="total number of processes") 00376 #endif 00377 00378 call env_state_output_netcdf(env_state, ncid) 00379 call gas_data_output_netcdf(gas_data, ncid) 00380 call gas_state_output_netcdf(gas_state, ncid, gas_data) 00381 call aero_data_output_netcdf(aero_data, ncid) 00382 call aero_weight_output_netcdf(aero_weight, ncid) 00383 call aero_state_output_netcdf(aero_state, ncid, bin_grid, & 00384 aero_data, aero_weight, record_removals, record_optical) 00385 00386 call pmc_nc_check(nf90_close(ncid)) 00387 00388 end subroutine output_state_to_file 00389 00390 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00391 00392 !> Send the state for the "central" output method to the root process. 00393 subroutine send_output_state_central(aero_state, gas_state, env_state) 00394 00395 !> Aerosol state. 00396 type(aero_state_t), intent(in) :: aero_state 00397 !> Gas state. 00398 type(gas_state_t), intent(in) :: gas_state 00399 !> Environment state. 00400 type(env_state_t), intent(in) :: env_state 00401 00402 #ifdef PMC_USE_MPI 00403 integer :: buffer_size, max_buffer_size, position, ierr 00404 character, allocatable :: buffer(:) 00405 00406 call assert(645797304, pmc_mpi_rank() /= 0) 00407 00408 max_buffer_size = 0 00409 max_buffer_size = max_buffer_size & 00410 + pmc_mpi_pack_size_env_state(env_state) 00411 max_buffer_size = max_buffer_size & 00412 + pmc_mpi_pack_size_gas_state(gas_state) 00413 max_buffer_size = max_buffer_size & 00414 + pmc_mpi_pack_size_aero_state(aero_state) 00415 allocate(buffer(max_buffer_size)) 00416 position = 0 00417 call pmc_mpi_pack_env_state(buffer, position, env_state) 00418 call pmc_mpi_pack_gas_state(buffer, position, gas_state) 00419 call pmc_mpi_pack_aero_state(buffer, position, aero_state) 00420 call assert(839343839, position <= max_buffer_size) 00421 buffer_size = position 00422 call mpi_send(buffer, buffer_size, MPI_CHARACTER, 0, & 00423 TAG_OUTPUT_STATE_CENTRAL, MPI_COMM_WORLD, ierr) 00424 call pmc_mpi_check_ierr(ierr) 00425 deallocate(buffer) 00426 #endif 00427 00428 end subroutine send_output_state_central 00429 00430 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00431 00432 !> Receive the state for the "central" output method on the root 00433 !> process. 00434 subroutine recv_output_state_central(prefix, bin_grid, aero_data, & 00435 aero_weight, gas_data, index, time, del_t, i_repeat, & 00436 record_removals, record_optical, uuid, remote_proc) 00437 00438 !> Prefix of state file. 00439 character(len=*), intent(in) :: prefix 00440 !> Bin grid. 00441 type(bin_grid_t), intent(in) :: bin_grid 00442 !> Aerosol data. 00443 type(aero_data_t), intent(in) :: aero_data 00444 !> Aerosol weight. 00445 type(aero_weight_t), intent(in) :: aero_weight 00446 !> Gas data. 00447 type(gas_data_t), intent(in) :: gas_data 00448 !> Filename index. 00449 integer, intent(in) :: index 00450 !> Current time (s). 00451 real(kind=dp), intent(in) :: time 00452 !> Current timestep (s). 00453 real(kind=dp), intent(in) :: del_t 00454 !> Current repeat number. 00455 integer, intent(in) :: i_repeat 00456 !> Whether to output particle removal info. 00457 logical, intent(in) :: record_removals 00458 !> Whether to output aerosol_optical_properties. 00459 logical, intent(in) :: record_optical 00460 !> UUID of the simulation. 00461 character(len=PMC_UUID_LEN), intent(in) :: uuid 00462 !> Process number to receive from. 00463 integer, intent(in) :: remote_proc 00464 00465 #ifdef PMC_USE_MPI 00466 type(env_state_t) :: env_state 00467 type(gas_state_t) :: gas_state 00468 type(aero_state_t) :: aero_state 00469 integer :: buffer_size, position, status(MPI_STATUS_SIZE) 00470 integer :: n_proc, ierr 00471 character, allocatable :: buffer(:) 00472 00473 call assert(206980035, pmc_mpi_rank() == 0) 00474 call assert(291452117, remote_proc /= 0) 00475 n_proc = pmc_mpi_size() 00476 00477 ! get buffer size 00478 call mpi_probe(remote_proc, TAG_OUTPUT_STATE_CENTRAL, MPI_COMM_WORLD, & 00479 status, ierr) 00480 call pmc_mpi_check_ierr(ierr) 00481 call mpi_get_count(status, MPI_CHARACTER, buffer_size, ierr) 00482 00483 ! get message 00484 allocate(buffer(buffer_size)) 00485 call mpi_recv(buffer, buffer_size, MPI_CHARACTER, remote_proc, & 00486 TAG_OUTPUT_STATE_CENTRAL, MPI_COMM_WORLD, status, ierr) 00487 call pmc_mpi_check_ierr(ierr) 00488 00489 ! unpack message 00490 position = 0 00491 call env_state_allocate(env_state) 00492 call gas_state_allocate(gas_state) 00493 call aero_state_allocate(aero_state) 00494 call pmc_mpi_unpack_env_state(buffer, position, env_state) 00495 call pmc_mpi_unpack_gas_state(buffer, position, gas_state) 00496 call pmc_mpi_unpack_aero_state(buffer, position, aero_state) 00497 call assert(279581330, position == buffer_size) 00498 deallocate(buffer) 00499 00500 call output_state_to_file(prefix, bin_grid, aero_data, & 00501 aero_weight, aero_state, gas_data, gas_state, env_state, & 00502 index, time, del_t, i_repeat, record_removals, record_optical, & 00503 remote_proc, n_proc, uuid) 00504 00505 call env_state_deallocate(env_state) 00506 call gas_state_deallocate(gas_state) 00507 call aero_state_deallocate(aero_state) 00508 #endif 00509 00510 end subroutine recv_output_state_central 00511 00512 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00513 00514 !> Read the current state. 00515 subroutine input_state(filename, bin_grid, aero_data, & 00516 aero_weight, aero_state, gas_data, gas_state, env_state, index, & 00517 time, del_t, i_repeat, uuid) 00518 00519 !> Prefix of state file. 00520 character(len=*), intent(in) :: filename 00521 !> Bin grid. 00522 type(bin_grid_t), intent(in) :: bin_grid 00523 !> Aerosol data. 00524 type(aero_data_t), intent(inout) :: aero_data 00525 !> Aerosol weight. 00526 type(aero_weight_t), intent(inout) :: aero_weight 00527 !> Aerosol state. 00528 type(aero_state_t), intent(inout) :: aero_state 00529 !> Gas data. 00530 type(gas_data_t), intent(inout) :: gas_data 00531 !> Gas state. 00532 type(gas_state_t), intent(inout) :: gas_state 00533 !> Environment state. 00534 type(env_state_t), intent(inout) :: env_state 00535 !> Filename index. 00536 integer, intent(out) :: index 00537 !> Current time (s). 00538 real(kind=dp), intent(out) :: time 00539 !> Current timestep (s). 00540 real(kind=dp), intent(out) :: del_t 00541 !> Current repeat number. 00542 integer, intent(out) :: i_repeat 00543 !> UUID of the simulation. 00544 character(len=PMC_UUID_LEN), intent(out) :: uuid 00545 00546 integer :: ncid 00547 00548 ! only root process actually reads from the file 00549 if (pmc_mpi_rank() == 0) then 00550 call pmc_nc_open_read(filename, ncid) 00551 00552 call pmc_nc_check(nf90_get_att(ncid, NF90_GLOBAL, "UUID", uuid)) 00553 00554 call pmc_nc_read_real(ncid, time, "time") 00555 call pmc_nc_read_real(ncid, del_t, "timestep") 00556 call pmc_nc_read_integer(ncid, i_repeat, "repeat") 00557 call pmc_nc_read_integer(ncid, index, "timestep_index") 00558 00559 call env_state_input_netcdf(env_state, ncid) 00560 call gas_data_input_netcdf(gas_data, ncid) 00561 call gas_state_input_netcdf(gas_state, ncid, gas_data) 00562 call aero_data_input_netcdf(aero_data, ncid) 00563 call aero_weight_input_netcdf(aero_weight, ncid) 00564 call aero_state_input_netcdf(aero_state, ncid, bin_grid, & 00565 aero_data, aero_weight) 00566 00567 call pmc_nc_close(ncid) 00568 end if 00569 00570 end subroutine input_state 00571 00572 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00573 00574 !> Write the current sectional data. 00575 subroutine output_sectional(prefix, bin_grid, aero_data, aero_binned, & 00576 gas_data, gas_state, env_state, index, time, del_t, uuid) 00577 00578 !> Prefix of filename to write 00579 character(len=*), intent(in) :: prefix 00580 !> Bin grid. 00581 type(bin_grid_t), intent(in) :: bin_grid 00582 !> Aerosol data. 00583 type(aero_data_t), intent(in) :: aero_data 00584 !> Binned aerosol data. 00585 type(aero_binned_t), intent(in) :: aero_binned 00586 !> Gas data. 00587 type(gas_data_t), intent(in) :: gas_data 00588 !> Gas state. 00589 type(gas_state_t), intent(in) :: gas_state 00590 !> Environment state. 00591 type(env_state_t), intent(in) :: env_state 00592 !> Filename index. 00593 integer, intent(in) :: index 00594 !> Current time (s). 00595 real(kind=dp), intent(in) :: time 00596 !> Current output time-step (s). 00597 real(kind=dp), intent(in) :: del_t 00598 !> UUID of the simulation. 00599 character(len=PMC_UUID_LEN), intent(in) :: uuid 00600 00601 integer :: ncid 00602 character(len=len(prefix)+100) :: filename 00603 00604 write(filename, '(a,a,i8.8,a)') trim(prefix), & 00605 '_', index, '.nc' 00606 call pmc_nc_check_msg(nf90_create(filename, NF90_CLOBBER, ncid), & 00607 "opening " // trim(filename)) 00608 00609 ! write header attributes 00610 call pmc_nc_check(nf90_put_att(ncid, NF90_GLOBAL, "title", & 00611 "PartMC sectional output file")) 00612 call pmc_nc_check(nf90_enddef(ncid)) 00613 00614 call write_header_and_time(ncid, time, del_t, index, uuid) 00615 00616 ! write data 00617 call env_state_output_netcdf(env_state, ncid) 00618 call gas_data_output_netcdf(gas_data, ncid) 00619 call gas_state_output_netcdf(gas_state, ncid, gas_data) 00620 call aero_data_output_netcdf(aero_data, ncid) 00621 call aero_binned_output_netcdf(aero_binned, ncid, bin_grid, & 00622 aero_data) 00623 00624 call pmc_nc_check(nf90_close(ncid)) 00625 00626 end subroutine output_sectional 00627 00628 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00629 00630 !> Read the specification for an output type from a spec file and 00631 !> generate it. 00632 subroutine spec_file_read_output_type(file, output_type) 00633 00634 !> Spec file. 00635 type(spec_file_t), intent(inout) :: file 00636 !> Kernel type. 00637 integer, intent(out) :: output_type 00638 00639 character(len=SPEC_LINE_MAX_VAR_LEN) :: output_type_name 00640 00641 !> \page input_format_output Input File Format: Output Type 00642 !! 00643 !! The output type is specified by the parameter: 00644 !! - \b output_type (string): type of disk output --- must be 00645 !! one of: \c central to write one file per process, but all 00646 !! written by process 0; \c dist for every process to 00647 !! write its own state file; or \c single to transfer all data 00648 !! to process 0 and write a single unified output file 00649 !! 00650 !! See also: 00651 !! - \ref spec_file_format --- the input file text format 00652 00653 call spec_file_read_string(file, 'output_type', output_type_name) 00654 if (trim(output_type_name) == 'central') then 00655 output_type = OUTPUT_TYPE_CENTRAL 00656 elseif (trim(output_type_name) == 'dist') then 00657 output_type = OUTPUT_TYPE_DIST 00658 elseif (trim(output_type_name) == 'single') then 00659 output_type = OUTPUT_TYPE_SINGLE 00660 else 00661 call spec_file_die_msg(494684716, file, & 00662 "Unknown output type: " // trim(output_type_name)) 00663 end if 00664 00665 end subroutine spec_file_read_output_type 00666 00667 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00668 00669 end module pmc_output