PartMC  2.9.0
output.F90
Go to the documentation of this file.
1 ! Copyright (C) 2005-2022 Nicole Riemer and Matthew West
2 ! Licensed under the GNU General Public License version 2 or (at your
3 ! option) any later version. See the file COPYING for details.
4 
5 !> \file
6 !> The pmc_output module.
7 
8 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
9 
10 !> \page output_format Output File Format
11 !!
12 !! PartMC output files are in the <a
13 !! href="http://www.unidata.ucar.edu/software/netcdf/">NetCDF Classic
14 !! Format</a> (also known as NetCDF-3 format). The dimensions and
15 !! variables in the files will depend on the type of run (particle,
16 !! analytical solution, etc), and options in the spec file (e.g. \c
17 !! record_removals and \c do_optical).
18 !!
19 !! The state of the simulation is periodically output during the run,
20 !! with frequency determined by the \c t_output input parameter. Each
21 !! output file has a filename of the form \c PREFIX_RRRR_SSSSSSSS.nc,
22 !! where \c PREFIX is given by the \c output_prefix input parameter,
23 !! \c RRRR is the four-digit repeat number (starting from 1), and \c
24 !! SSSSSSSS is the eight-digit output index (starting at 1 and
25 !! incremented each time the state is output). For exact and sectional
26 !! simulations all repeats would be identical so there is no support
27 !! for repeating and the filename is of the format \c
28 !! PREFIX_SSSSSSSS.nc.
29 !!
30 !! If run in parallel and \c output_type is \c central or \c dist,
31 !! then the output files have names like \c
32 !! PREFIX_RRRR_PPPP_SSSSSSSS.nc, where \c PPPP is a four-digit
33 !! process number (starting from 1) and the other variables are as
34 !! above. If \c output_type is \c single then the output file naming
35 !! scheme as the same as for serial runs.
36 !!
37 !! The data in each output file comes in several different groups, as
38 !! follows:
39 !!
40 !! \subpage output_format_general "General Information"
41 !!
42 !! \subpage output_format_env_state "Environment State"
43 !!
44 !! \subpage output_format_gas_data "Gas Material Data"
45 !!
46 !! \subpage output_format_gas_state "Gas State"
47 !!
48 !! \subpage output_format_aero_data "Aerosol Material Data"
49 !!
50 !! \subpage output_format_aero_state "Aerosol Particle State"
51 !! (only for particle-resolved simulations)
52 !!
53 !! \subpage output_format_aero_removed "Aerosol Particle Removal Information"
54 !! (only for particle-resolved simulations, if \c record_removals is \c yes)
55 !!
56 !! \subpage output_format_aero_weight_array "Aerosol Weighting Function"
57 !! (only for particle-resolved simulations)
58 !!
59 !! \subpage output_format_diam_bin_grid "Diameter Bin Grid Data"
60 !! (only for exact and sectional simulations)
61 !!
62 !! \subpage output_format_aero_binned "Aerosol Binned Sectional State"
63 !! (only for exact and sectional simulations)
64 
65 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
66 
67 !> Write data in NetCDF format.
68 module pmc_output
69 
70  use pmc_bin_grid
71  use pmc_aero_data
72  use pmc_aero_state
73  use pmc_aero_binned
74  use pmc_netcdf
75  use pmc_gas_state
76  use pmc_env_state
77  use pmc_util
78  use pmc_gas_data
79  use pmc_scenario
80  use pmc_mpi
81 #ifdef PMC_USE_MPI
82  use mpi
83 #endif
84 
85  !> PartMC verson number.
86  character(len=100), parameter :: partmc_version = "2.8.0"
87 
88  !> Type code for undefined or invalid output.
89  integer, parameter :: output_type_invalid = 0
90  !> Type code for centralized output (one file per process, all written
91  !> by process 0).
92  integer, parameter :: output_type_central = 1
93  !> Type code for distributed output (one file per process, written by
94  !> each process).
95  integer, parameter :: output_type_dist = 2
96  !> Type code for single output (one file for all processes, written by
97  !> process 0).
98  integer, parameter :: output_type_single = 3
99 
100  !> Internal-use variable only.
101  integer, parameter :: tag_output_state_central = 4341
102  !> Internal-use variable only.
103  integer, parameter :: tag_output_state_single = 4342
104 
105 contains
106 
107 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
108 
109  !> Write the current state.
110  subroutine output_state(prefix, output_type, aero_data, aero_state, &
111  gas_data, gas_state, env_state, index, time, del_t, i_repeat, &
112  record_removals, record_optical, uuid)
113 
114  !> Prefix of state file.
115  character(len=*), intent(in) :: prefix
116  !> Output type for parallel runs (see module constants).
117  integer, intent(in) :: output_type
118  !> Aerosol data.
119  type(aero_data_t), intent(in) :: aero_data
120  !> Aerosol state.
121  type(aero_state_t), intent(in) :: aero_state
122  !> Gas data.
123  type(gas_data_t), intent(in) :: gas_data
124  !> Gas state.
125  type(gas_state_t), intent(in) :: gas_state
126  !> Environment state.
127  type(env_state_t), intent(in) :: env_state
128  !> Filename index.
129  integer, intent(in) :: index
130  !> Current time (s).
131  real(kind=dp), intent(in) :: time
132  !> Current timestep (s).
133  real(kind=dp), intent(in) :: del_t
134  !> Current repeat number.
135  integer, intent(in) :: i_repeat
136  !> Whether to output particle removal info.
137  logical, intent(in) :: record_removals
138  !> Whether to output aerosol optical properties.
139  logical, intent(in) :: record_optical
140  !> UUID of the simulation.
141  character(len=PMC_UUID_LEN), intent(in) :: uuid
142 
143  integer :: rank, n_proc
144 #ifdef PMC_USE_MPI
145  type(env_state_t) :: env_state_write
146  type(gas_state_t) :: gas_state_write
147  type(aero_state_t) :: aero_state_write
148  integer :: ierr, status(MPI_STATUS_SIZE), i_proc, position
149  character, allocatable :: buffer(:)
150 #endif
151 
152  rank = pmc_mpi_rank()
153  n_proc = pmc_mpi_size()
154  if (output_type == output_type_central) then
155  ! write per-process data to separate files, but do it by
156  ! transferring data to process 0 and having it do the writes
157  if (rank == 0) then
158  call output_state_to_file(prefix, aero_data, aero_state, gas_data, &
159  gas_state, env_state, index, time, del_t, i_repeat, &
160  record_removals, record_optical, uuid, rank, n_proc)
161 #ifdef PMC_USE_MPI
162  do i_proc = 1,(n_proc - 1)
163  call recv_output_state_central(prefix, aero_data, gas_data, &
164  index, time, del_t, i_repeat, record_removals, &
165  record_optical, uuid, i_proc)
166  end do
167 #endif
168  else ! rank /= 0
169  call send_output_state_central(aero_state, gas_state, env_state)
170  end if
171  elseif (output_type == output_type_dist) then
172  ! have each process write its own data directly
173  call output_state_to_file(prefix, aero_data, aero_state, gas_data, &
174  gas_state, env_state, index, time, del_t, i_repeat, &
175  record_removals, record_optical, uuid, rank, n_proc)
176  elseif (output_type == output_type_single) then
177  if (n_proc == 1) then
178  call output_state_to_file(prefix, aero_data, aero_state, gas_data, &
179  gas_state, env_state, index, time, del_t, i_repeat, &
180  record_removals, record_optical, uuid, rank, n_proc)
181  else
182 #ifdef PMC_USE_MPI
183  ! collect all data onto process 0 and then write it to a
184  ! single file
185  env_state_write = env_state
186  gas_state_write = gas_state
187  call env_state_reduce_avg(env_state_write)
188  call gas_state_reduce_avg(gas_state_write)
189  call aero_state_mpi_gather(aero_state, aero_state_write, aero_data)
190  if (rank == 0) then
191  call output_state_to_file(prefix, aero_data, aero_state_write, &
192  gas_data, gas_state_write, env_state_write, index, time, &
193  del_t, i_repeat, record_removals, record_optical, uuid, &
194  rank, 1)
195  end if
196 #endif
197  end if
198  else
199  call die_msg(626743323, "Unknown output_type: " &
200  // trim(integer_to_string(output_type)))
201  end if
202 
203  end subroutine output_state
204 
205 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
206 
207  !> Make a filename from a given prefix and other information.
208  subroutine make_filename(filename, prefix, suffix, index, i_repeat, &
209  write_rank, write_n_proc)
210 
211  !> Filename to create.
212  character(len=*), intent(out) :: filename
213  !> Filename prefix.
214  character(len=*), intent(in) :: prefix
215  !> Filename suffix.
216  character(len=*), intent(in) :: suffix
217  !> Filename index.
218  integer, intent(in), optional :: index
219  !> Current repeat number.
220  integer, intent(in), optional :: i_repeat
221  !> Rank to write into file.
222  integer, intent(in), optional :: write_rank
223  !> Number of processes to write into file.
224  integer, intent(in), optional :: write_n_proc
225 
226  integer :: ncid, use_rank, use_n_proc
227  character(len=100) :: proc_string, index_string, repeat_string
228 
229  if (present(write_rank)) then
230  use_rank = write_rank
231  else
232  use_rank = pmc_mpi_rank()
233  end if
234  if (present(write_n_proc)) then
235  use_n_proc = write_n_proc
236  else
237  use_n_proc = pmc_mpi_size()
238  end if
239 
240  repeat_string = ""
241  proc_string = ""
242  index_string = ""
243  if (present(i_repeat)) write(repeat_string, '(a,i4.4)') '_', i_repeat
244  if (use_n_proc > 1) write(proc_string, '(a,i4.4)') '_', (use_rank + 1)
245  if (present(index)) write(index_string, '(a,i8.8)') '_', index
246  write(filename, '(a,a,a,a,a)') trim(prefix), trim(repeat_string), &
247  trim(proc_string), trim(index_string), trim(suffix)
248 
249  end subroutine make_filename
250 
251 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
252 
253  !> Helper routine to write time variables. Do not call directly.
254  subroutine write_time(ncid, time, del_t, index)
255 
256  !> NetCDF file ID, in data mode.
257  integer, intent(in) :: ncid
258  !> Current time (s).
259  real(kind=dp), intent(in) :: time
260  !> Current timestep (s).
261  real(kind=dp), intent(in) :: del_t
262  !> Filename index.
263  integer, intent(in) :: index
264 
265  call pmc_nc_write_real(ncid, time, "time", unit="s", &
266  description="time elapsed since simulation start")
267  call pmc_nc_write_real(ncid, del_t, "timestep", unit="s", &
268  description="current timestep size")
269  call pmc_nc_write_integer(ncid, index, "timestep_index", &
270  description="an integer that is 1 on the first timestep, " &
271  // "2 on the second timestep, etc.")
272 
273  end subroutine write_time
274 
275 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
276 
277  !> Write the current state for a single process. Do not call this
278  !> subroutine directly, but rather call output_state().
279  subroutine output_state_to_file(prefix, aero_data, aero_state, gas_data, &
280  gas_state, env_state, index, time, del_t, i_repeat, record_removals, &
281  record_optical, uuid, write_rank, write_n_proc)
282 
283  !> Prefix of state file.
284  character(len=*), intent(in) :: prefix
285  !> Aerosol data.
286  type(aero_data_t), intent(in) :: aero_data
287  !> Aerosol state.
288  type(aero_state_t), intent(in) :: aero_state
289  !> Gas data.
290  type(gas_data_t), intent(in) :: gas_data
291  !> Gas state.
292  type(gas_state_t), intent(in) :: gas_state
293  !> Environment state.
294  type(env_state_t), intent(in) :: env_state
295  !> Filename index.
296  integer, intent(in) :: index
297  !> Current time (s).
298  real(kind=dp), intent(in) :: time
299  !> Current timestep (s).
300  real(kind=dp), intent(in) :: del_t
301  !> Current repeat number.
302  integer, intent(in) :: i_repeat
303  !> Whether to output particle removal info.
304  logical, intent(in) :: record_removals
305  !> Whether to output aerosol optical properties.
306  logical, intent(in) :: record_optical
307  !> UUID of the simulation.
308  character(len=PMC_UUID_LEN), intent(in) :: uuid
309  !> Rank to write into file.
310  integer, intent(in), optional :: write_rank
311  !> Number of processes to write into file.
312  integer, intent(in), optional :: write_n_proc
313 
314  character(len=len(prefix)+100) :: filename
315  integer :: ncid
316 
317  !> \page output_format_general Output File Format: General Information
318  !!
319  !! The general information global NetCDF attributes are:
320  !! - \b title: always set to the string "PartMC version V.V.V
321  !! output file" where V.V.V is the PartMC version that created
322  !! the file
323  !! - \b source: set to the string "PartMC version V.V.V"
324  !! - \b UUID: a string of the form F47AC10B-58CC-4372-A567-0E02B2C3D479
325  !! which is the same for all files generated by a single call of
326  !! PartMC.
327  !! - \b Conventions: set to the string "CF-1.4", indicating
328  !! compliance with the <a
329  !! href="http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.4">CF
330  !! convention format</a>
331  !! - \b history: set to the string "YYYY-MM-DDThh:mm:ss[+-]ZZ:zz
332  !! created by PartMC version V.V.V" where the first term is
333  !! the file creation time in the <a
334  !! href="http://en.wikipedia.org/wiki/ISO_8601">ISO 8601
335  !! format</a>. For example, noon Pacific Standard Time (PST)
336  !! on February 1st, 2000 would be written
337  !! 2000-02-01T12:00:00-08:00. The date and time variables
338  !! are:
339  !! - YYYY: four-digit year
340  !! - MM: two-digit month number
341  !! - DD: two-digit day within month
342  !! - T: literal "T" character
343  !! - hh: two-digit hour in 24-hour format
344  !! - mm: two-digit minute
345  !! - ss: two-digit second
346  !! - [+-]: a literal "+" or "-" character giving the time zone
347  !! offset sign
348  !! - ZZ: two-digit hours of the time zone offset from UTC
349  !! - zz: two-digit minutes of the time zone offset from UTC
350  !!
351  !! The general information NetCDF variables are:
352  !! - \b time (unit s): time elapsed since the simulation start time,
353  !! as specified in the \ref output_format_env_state section
354  !! - \b timestep (unit s): the current timestep size
355  !! - \b repeat: the repeat number of this simulation (starting from 1)
356  !! - \b timestep_index: an integer that is 1 on the first timestep, 2
357  !! on the second timestep, etc.
358  !! - \b process (MPI only): the process number (starting from 1)
359  !! that output this data file
360  !! - \b total_processes (MPI only): the total number of processes
361  !! involved in writing data (may be less than the total number of
362  !! processes that computed the data)
363 
364  call make_filename(filename, prefix, ".nc", index, i_repeat, write_rank, &
365  write_n_proc)
366  call pmc_nc_open_write(filename, ncid)
367  call pmc_nc_write_info(ncid, uuid, &
368  "PartMC version " // trim(partmc_version), write_rank, write_n_proc)
369  call write_time(ncid, time, del_t, index)
370  call pmc_nc_write_integer(ncid, i_repeat, "repeat", &
371  description="repeat number of this simulation (starting from 1)")
372 
373  call env_state_output_netcdf(env_state, ncid)
374  call gas_data_output_netcdf(gas_data, ncid)
375  call gas_state_output_netcdf(gas_state, ncid, gas_data)
376  call aero_data_output_netcdf(aero_data, ncid)
377  call aero_state_output_netcdf(aero_state, ncid, aero_data, &
378  record_removals, record_optical)
379 
380  call pmc_nc_check(nf90_close(ncid))
381 
382  end subroutine output_state_to_file
383 
384 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
385 
386  !> Send the state for the "central" output method to the root process.
387  subroutine send_output_state_central(aero_state, gas_state, env_state)
388 
389  !> Aerosol state.
390  type(aero_state_t), intent(in) :: aero_state
391  !> Gas state.
392  type(gas_state_t), intent(in) :: gas_state
393  !> Environment state.
394  type(env_state_t), intent(in) :: env_state
395 
396 #ifdef PMC_USE_MPI
397  integer :: buffer_size, max_buffer_size, position, ierr
398  character, allocatable :: buffer(:)
399 
400  call assert(645797304, pmc_mpi_rank() /= 0)
401 
402  max_buffer_size = 0
403  max_buffer_size = max_buffer_size &
404  + pmc_mpi_pack_size_env_state(env_state)
405  max_buffer_size = max_buffer_size &
406  + pmc_mpi_pack_size_gas_state(gas_state)
407  max_buffer_size = max_buffer_size &
408  + pmc_mpi_pack_size_aero_state(aero_state)
409  allocate(buffer(max_buffer_size))
410  position = 0
411  call pmc_mpi_pack_env_state(buffer, position, env_state)
412  call pmc_mpi_pack_gas_state(buffer, position, gas_state)
413  call pmc_mpi_pack_aero_state(buffer, position, aero_state)
414  call assert(839343839, position <= max_buffer_size)
415  buffer_size = position
416  call mpi_send(buffer, buffer_size, mpi_character, 0, &
417  tag_output_state_central, mpi_comm_world, ierr)
418  call pmc_mpi_check_ierr(ierr)
419  deallocate(buffer)
420 #endif
421 
422  end subroutine send_output_state_central
423 
424 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
425 
426  !> Receive the state for the "central" output method on the root
427  !> process.
428  subroutine recv_output_state_central(prefix, aero_data, gas_data, index, &
429  time, del_t, i_repeat, record_removals, record_optical, uuid, &
430  remote_proc)
431 
432  !> Prefix of state file.
433  character(len=*), intent(in) :: prefix
434  !> Aerosol data.
435  type(aero_data_t), intent(in) :: aero_data
436  !> Gas data.
437  type(gas_data_t), intent(in) :: gas_data
438  !> Filename index.
439  integer, intent(in) :: index
440  !> Current time (s).
441  real(kind=dp), intent(in) :: time
442  !> Current timestep (s).
443  real(kind=dp), intent(in) :: del_t
444  !> Current repeat number.
445  integer, intent(in) :: i_repeat
446  !> Whether to output particle removal info.
447  logical, intent(in) :: record_removals
448  !> Whether to output aerosol_optical_properties.
449  logical, intent(in) :: record_optical
450  !> UUID of the simulation.
451  character(len=PMC_UUID_LEN), intent(in) :: uuid
452  !> Process number to receive from.
453  integer, intent(in) :: remote_proc
454 
455 #ifdef PMC_USE_MPI
456  type(env_state_t) :: env_state
457  type(gas_state_t) :: gas_state
458  type(aero_state_t) :: aero_state
459  integer :: buffer_size, position, status(MPI_STATUS_SIZE)
460  integer :: n_proc, ierr
461  character, allocatable :: buffer(:)
462 
463  call assert(206980035, pmc_mpi_rank() == 0)
464  call assert(291452117, remote_proc /= 0)
465  n_proc = pmc_mpi_size()
466 
467  ! get buffer size
468  call mpi_probe(remote_proc, tag_output_state_central, mpi_comm_world, &
469  status, ierr)
470  call pmc_mpi_check_ierr(ierr)
471  call mpi_get_count(status, mpi_character, buffer_size, ierr)
472 
473  ! get message
474  allocate(buffer(buffer_size))
475  call mpi_recv(buffer, buffer_size, mpi_character, remote_proc, &
476  tag_output_state_central, mpi_comm_world, status, ierr)
477  call pmc_mpi_check_ierr(ierr)
478 
479  ! unpack message
480  position = 0
481  call pmc_mpi_unpack_env_state(buffer, position, env_state)
482  call pmc_mpi_unpack_gas_state(buffer, position, gas_state)
483  call pmc_mpi_unpack_aero_state(buffer, position, aero_state)
484  call assert(279581330, position == buffer_size)
485  deallocate(buffer)
486 
487  call output_state_to_file(prefix, aero_data, aero_state, gas_data, &
488  gas_state, env_state, index, time, del_t, i_repeat, &
489  record_removals, record_optical, uuid, remote_proc, n_proc)
490 #endif
491 
492  end subroutine recv_output_state_central
493 
494 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
495 
496  !> Read the current state.
497  subroutine input_state(filename, index, time, del_t, i_repeat, uuid, &
498  aero_data, aero_state, gas_data, gas_state, env_state)
499 
500  !> Prefix of state file.
501  character(len=*), intent(in) :: filename
502  !> Filename index.
503  integer, intent(out) :: index
504  !> Current time (s).
505  real(kind=dp), intent(out) :: time
506  !> Current timestep (s).
507  real(kind=dp), intent(out) :: del_t
508  !> Current repeat number.
509  integer, intent(out) :: i_repeat
510  !> UUID of the simulation.
511  character(len=PMC_UUID_LEN), intent(out) :: uuid
512  !> Aerosol data.
513  type(aero_data_t), optional, intent(inout) :: aero_data
514  !> Aerosol state.
515  type(aero_state_t), optional, intent(inout) :: aero_state
516  !> Gas data.
517  type(gas_data_t), optional, intent(inout) :: gas_data
518  !> Gas state.
519  type(gas_state_t), optional, intent(inout) :: gas_state
520  !> Environment state.
521  type(env_state_t), optional, intent(inout) :: env_state
522 
523  integer :: ncid
524 
525  call assert_msg(819739354, pmc_mpi_rank() == 0, &
526  "can only call from process 0")
527 
528  call pmc_nc_open_read(filename, ncid)
529 
530  call pmc_nc_check(nf90_get_att(ncid, nf90_global, "UUID", uuid))
531 
532  call pmc_nc_read_real(ncid, time, "time")
533  call pmc_nc_read_real(ncid, del_t, "timestep")
534  call pmc_nc_read_integer(ncid, i_repeat, "repeat")
535  call pmc_nc_read_integer(ncid, index, "timestep_index")
536 
537  if (present(aero_data)) then
538  call aero_data_input_netcdf(aero_data, ncid)
539  if (present(aero_state)) then
540  call aero_state_input_netcdf(aero_state, ncid, aero_data)
541  end if
542  else
543  call assert_msg(289621231, present(aero_state) .eqv. .false., &
544  "cannot input aero_state without aero_data")
545  end if
546 
547  if (present(gas_data)) then
548  call gas_data_input_netcdf(gas_data, ncid)
549  if (present(gas_state)) then
550  call gas_state_input_netcdf(gas_state, ncid, gas_data)
551  end if
552  else
553  call assert_msg(874298496, present(gas_state) .eqv. .false., &
554  "cannot input gas_state without gas_data")
555  end if
556 
557  if (present(env_state)) then
558  call env_state_input_netcdf(env_state, ncid)
559  end if
560 
561  call pmc_nc_close(ncid)
562 
563  end subroutine input_state
564 
565 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
566 
567  !> Find all NetCDF (.nc) filenames that match the given prefix.
568  subroutine input_filename_list(prefix, filename_list)
569 
570  !> Filename prefix to search for.
571  character(len=*), intent(in) :: prefix
572  !> Filename list.
573  character(len=*), intent(inout), allocatable :: filename_list(:)
574 
575  integer :: n_file, index, unit, ios
576  character(len=len(prefix)+100) :: filename
577  logical :: done
578 
579  call assert_msg(277193351, pmc_mpi_rank() == 0, &
580  "can only call from process 0")
581 
582  index = 1
583  done = .false.
584  unit = get_unit()
585  do while (.not. done)
586  write(filename, '(a,a,i8.8,a)') trim(prefix), '_', index, '.nc'
587  open(unit=unit, file=filename, status='old', iostat=ios)
588  if (ios /= 0) then
589  done = .true.
590  else
591  index = index + 1
592  close(unit)
593  end if
594  end do
595  call free_unit(unit)
596 
597  n_file = index - 1
598  call ensure_string_array_size(filename_list, n_file)
599  do index = 1,n_file
600  write(filename, '(a,a,i8.8,a)') trim(prefix), '_', index, '.nc'
601  filename_list(index) = filename
602  end do
603 
604  end subroutine input_filename_list
605 
606 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
607 
608  !> Find the number of repeats and indices for the given prefix.
609  subroutine input_n_files(prefix, n_repeat, n_index)
610 
611  !> Filename prefix to search for.
612  character(len=*), intent(in) :: prefix
613  !> Number of repeats found.
614  integer, intent(out) :: n_repeat
615  !> Number of indices found.
616  integer, intent(out) :: n_index
617 
618  integer :: repeat, index, unit, ios
619  character(len=len(prefix)+100) :: filename
620  logical :: done
621 
622  call assert_msg(711223711, pmc_mpi_rank() == 0, &
623  "can only call from process 0")
624 
625  unit = get_unit()
626 
627  repeat = 1
628  index = 1
629  done = .false.
630  do while (.not. done)
631  call make_filename(filename, prefix, ".nc", index, repeat)
632  open(unit=unit, file=filename, status='old', iostat=ios)
633  if (ios /= 0) then
634  done = .true.
635  else
636  repeat = repeat + 1
637  close(unit)
638  end if
639  end do
640  n_repeat = repeat - 1
641  call assert_msg(252703940, n_repeat >= 1, &
642  "no files found with prefix: " // trim(prefix))
643 
644  repeat = 1
645  index = 1
646  done = .false.
647  do while (.not. done)
648  call make_filename(filename, prefix, ".nc", index, repeat)
649  open(unit=unit, file=filename, status='old', iostat=ios)
650  if (ios /= 0) then
651  done = .true.
652  else
653  index = index + 1
654  close(unit)
655  end if
656  end do
657  n_index = index - 1
658 
659  end subroutine input_n_files
660 
661 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
662 
663  !> Write the current sectional data.
664  subroutine output_sectional(prefix, bin_grid, aero_data, aero_binned, &
665  gas_data, gas_state, env_state, index, time, del_t, uuid)
666 
667  !> Prefix of filename to write
668  character(len=*), intent(in) :: prefix
669  !> Bin grid.
670  type(bin_grid_t), intent(in) :: bin_grid
671  !> Aerosol data.
672  type(aero_data_t), intent(in) :: aero_data
673  !> Binned aerosol data.
674  type(aero_binned_t), intent(in) :: aero_binned
675  !> Gas data.
676  type(gas_data_t), intent(in) :: gas_data
677  !> Gas state.
678  type(gas_state_t), intent(in) :: gas_state
679  !> Environment state.
680  type(env_state_t), intent(in) :: env_state
681  !> Filename index.
682  integer, intent(in) :: index
683  !> Current time (s).
684  real(kind=dp), intent(in) :: time
685  !> Current output time-step (s).
686  real(kind=dp), intent(in) :: del_t
687  !> UUID of the simulation.
688  character(len=PMC_UUID_LEN), intent(in) :: uuid
689 
690  integer :: ncid
691  character(len=len(prefix)+100) :: filename
692 
693  write(filename, '(a,a,i8.8,a)') trim(prefix), &
694  '_', index, '.nc'
695  call pmc_nc_open_write(filename, ncid)
696  call pmc_nc_write_info(ncid, uuid, &
697  "PartMC version " // trim(partmc_version))
698  call write_time(ncid, time, del_t, index)
699 
700  ! write data
701  call env_state_output_netcdf(env_state, ncid)
702  call gas_data_output_netcdf(gas_data, ncid)
703  call gas_state_output_netcdf(gas_state, ncid, gas_data)
704  call aero_data_output_netcdf(aero_data, ncid)
705  call aero_binned_output_netcdf(aero_binned, ncid, bin_grid, &
706  aero_data)
707 
708  call pmc_nc_check(nf90_close(ncid))
709 
710  end subroutine output_sectional
711 
712 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
713 
714  !> Input sectional data.
715  subroutine input_sectional(filename, index, time, del_t, uuid, bin_grid, &
716  aero_data, aero_binned, gas_data, gas_state, env_state)
717 
718  !> Filename to read.
719  character(len=*), intent(in) :: filename
720  !> Filename index.
721  integer, intent(out) :: index
722  !> Current time (s).
723  real(kind=dp), intent(out) :: time
724  !> Current output time-step (s).
725  real(kind=dp), intent(out) :: del_t
726  !> UUID of the simulation.
727  character(len=PMC_UUID_LEN), intent(out) :: uuid
728  !> Bin grid.
729  type(bin_grid_t), optional, intent(inout) :: bin_grid
730  !> Aerosol data.
731  type(aero_data_t), optional, intent(inout) :: aero_data
732  !> Binned aerosol data.
733  type(aero_binned_t), optional, intent(inout) :: aero_binned
734  !> Gas data.
735  type(gas_data_t), optional, intent(inout) :: gas_data
736  !> Gas state.
737  type(gas_state_t), optional, intent(inout) :: gas_state
738  !> Environment state.
739  type(env_state_t), optional, intent(inout) :: env_state
740 
741  integer :: ncid
742 
743  call assert_msg(559676785, pmc_mpi_rank() == 0, &
744  "can only call from process 0")
745 
746  call pmc_nc_open_read(filename, ncid)
747 
748  call pmc_nc_check(nf90_get_att(ncid, nf90_global, "UUID", uuid))
749 
750  call pmc_nc_read_real(ncid, time, "time")
751  call pmc_nc_read_real(ncid, del_t, "timestep")
752  call pmc_nc_read_integer(ncid, index, "timestep_index")
753 
754  if (present(bin_grid)) then
755  call bin_grid_input_netcdf(bin_grid, ncid, "aero_diam", scale=0.5d0)
756  end if
757  if (present(aero_data)) then
758  call aero_data_input_netcdf(aero_data, ncid)
759  end if
760  if (present(aero_binned)) then
761  call assert_msg(585353528, &
762  present(bin_grid) .and. present(aero_data), &
763  "cannot input aero_binned without bin_grid and aero_data")
764  call aero_binned_input_netcdf(aero_binned, ncid, bin_grid, &
765  aero_data)
766  end if
767 
768  if (present(gas_data)) then
769  call gas_data_input_netcdf(gas_data, ncid)
770  if (present(gas_state)) then
771  call gas_state_input_netcdf(gas_state, ncid, gas_data)
772  end if
773  else
774  call assert_msg(214545112, present(gas_state) .eqv. .false., &
775  "cannot input gas_state without gas_data")
776  end if
777 
778  if (present(env_state)) then
779  call env_state_input_netcdf(env_state, ncid)
780  end if
781 
782  call pmc_nc_close(ncid)
783 
784  end subroutine input_sectional
785 
786 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
787 
788  !> Write the current modal data.
789  subroutine output_modal(prefix, aero_binned, aero_dist, aero_data, &
790  env_state, gas_data, gas_state, bin_grid, &
791  scenario, index, time, del_t, uuid)
792 
793  !> Prefix of filename to write.
794  character(len=*), intent(in) :: prefix
795  !> Binned aerosol distribution.
796  type(aero_binned_t), intent(in) :: aero_binned
797  !> Aerosol distribution.
798  type(aero_dist_t), intent(in) :: aero_dist
799  !> Aerosol data.
800  type(aero_data_t), intent(in) :: aero_data
801  !> Environment state.
802  type(env_state_t), intent(in) :: env_state
803  !> Gas data.
804  type(gas_data_t), intent(in) :: gas_data
805  !> Gas state.
806  type(gas_state_t), intent(in) :: gas_state
807  !> Bin grid.
808  type(bin_grid_t), intent(in) :: bin_grid
809  !> Scenario data.
810  type(scenario_t), intent(in) :: scenario
811  !> Filename index.
812  integer, intent(in) :: index
813  !> Current time (s).
814  real(kind=dp), intent(in) :: time
815  !> Current output timestep (s).
816  real(kind=dp), intent(in) :: del_t
817  !> UUID of the simulation.
818  character(len=PMC_UUID_LEN), intent(in) :: uuid
819 
820  integer :: ncid
821  character(len=len(prefix)+100) :: filename
822 
823  write(filename, '(a,a,i8.8,a)') trim(prefix), '_', index, '.nc'
824  call pmc_nc_open_write(filename, ncid)
825  call pmc_nc_write_info(ncid, uuid, &
826  "PartMC version " // trim(partmc_version))
827  call write_time(ncid, time, del_t, index)
828 
829  ! Write data.
830  call aero_binned_output_netcdf(aero_binned, ncid, bin_grid, aero_data)
831  call aero_dist_output_netcdf(aero_dist, ncid)
832  call env_state_output_netcdf(env_state, ncid)
833  call gas_data_output_netcdf(gas_data, ncid)
834  call gas_state_output_netcdf(gas_state, ncid, gas_data)
835  call aero_data_output_netcdf(aero_data, ncid)
836  call bin_grid_output_netcdf(bin_grid, ncid, "diam", unit="m")
837  call drydep_params_output_netcdf(scenario%drydep, ncid)
838 
839  call pmc_nc_check(nf90_close(ncid))
840 
841  end subroutine output_modal
842 
843 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
844 
845  !> Input modal data.
846  subroutine input_modal(filename, index, time, del_t, uuid, aero_dist, &
847  aero_binned, aero_data, env_state, gas_data, gas_state, bin_grid, &
848  scenario)
849 
850  !> Filename to read.
851  character(len=*), intent(in) :: filename
852  !> Filename index.
853  integer, intent(out) :: index
854  !> Current time (s).
855  real(kind=dp), intent(out) :: time
856  !> Current output timestep.
857  real(kind=dp), intent(out) :: del_t
858  !> UUID of the simulation.
859  character(len=PMC_UUID_LEN), intent(out) :: uuid
860  !> Aerosol distribution
861  type(aero_dist_t), optional, intent(inout) :: aero_dist
862  !> Binned aerosol distribution.
863  type(aero_binned_t), optional, intent(inout) :: aero_binned
864  !> Aerosol data.
865  type(aero_data_t), optional, intent(inout) :: aero_data
866  !> Environment state.
867  type(env_state_t), optional, intent(inout) :: env_state
868  !> Gas data.
869  type(gas_data_t), optional, intent(inout) :: gas_data
870  !> Gas state.
871  type(gas_state_t), optional, intent(inout) :: gas_state
872  !> Bin grid.
873  type(bin_grid_t), optional, intent(inout) :: bin_grid
874  !> Scenario data.
875  type(scenario_t), optional, intent(inout) :: scenario
876 
877  integer :: ncid
878 
879  call assert_msg(348927561, pmc_mpi_rank() == 0, &
880  "can only call from process 0")
881 
882  call pmc_nc_open_read(filename, ncid)
883 
884  call pmc_nc_check(nf90_get_att(ncid, nf90_global, "UUID", uuid))
885 
886  call pmc_nc_read_real(ncid, time, "time")
887  call pmc_nc_read_real(ncid, del_t, "timestep")
888  call pmc_nc_read_integer(ncid, index, "timestep_index")
889 
890  if (present(aero_data)) then
891  call aero_data_input_netcdf(aero_data, ncid)
892  end if
893 
894  if (present(aero_dist)) then
895  call aero_dist_input_netcdf(aero_dist, ncid)
896  end if
897 
898  if (present(env_state)) then
899  call env_state_input_netcdf(env_state, ncid)
900  end if
901 
902  if (present(gas_data)) then
903  call gas_data_input_netcdf(gas_data, ncid)
904  if (present(gas_state)) then
905  call gas_state_input_netcdf(gas_state, ncid, gas_data)
906  end if
907  else
908  call assert_msg(739182654, present(gas_state) .eqv. .false., &
909  "cannot input gas_state without gas_data")
910  end if
911 
912  if (present(bin_grid)) then
913  call bin_grid_input_netcdf(bin_grid, ncid, "diam")
914  if (present(aero_binned)) then
915  call aero_binned_input_netcdf(aero_binned, ncid, bin_grid, aero_data)
916  end if
917  else
918  call assert_msg(582491376, present(aero_binned) .eqv. .false., &
919  "cannot input aero_binned without bin_grid")
920  end if
921 
922  if (present(scenario)) then
923  call drydep_params_input_netcdf(scenario%drydep, ncid)
924  end if
925 
926  end subroutine input_modal
927 
928 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
929 
930  !> Read the specification for an output type from a spec file and
931  !> generate it.
932  subroutine spec_file_read_output_type(file, output_type)
933 
934  !> Spec file.
935  type(spec_file_t), intent(inout) :: file
936  !> Kernel type.
937  integer, intent(out) :: output_type
938 
939  character(len=SPEC_LINE_MAX_VAR_LEN) :: output_type_name
940 
941  !> \page input_format_output Input File Format: Output Type
942  !!
943  !! The output type is specified by the parameter:
944  !! - \b output_type (string): type of disk output --- must be
945  !! one of: \c central to write one file per process, but all
946  !! written by process 0; \c dist for every process to
947  !! write its own state file; or \c single to transfer all data
948  !! to process 0 and write a single unified output file
949  !!
950  !! See also:
951  !! - \ref spec_file_format --- the input file text format
952 
953  call spec_file_read_string(file, 'output_type', output_type_name)
954  if (trim(output_type_name) == 'central') then
955  output_type = output_type_central
956  elseif (trim(output_type_name) == 'dist') then
957  output_type = output_type_dist
958  elseif (trim(output_type_name) == 'single') then
959  output_type = output_type_single
960  else
961  call spec_file_die_msg(392313600, file, &
962  "Unknown output type: " // trim(output_type_name))
963  end if
964 
965  end subroutine spec_file_read_output_type
966 
967 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
968 
969  !> Writes the current state of a column of a WRF-PartMC domain.
970  subroutine output_column_to_file(prefix, aero_data, aero_states, gas_data, &
971  gas_states, env_states, nz, index, time, del_t, i_repeat, &
972  record_removals, record_optical, uuid, write_rank, write_n_proc)
973 
974  !> Prefix of state file.
975  character(len=*), intent(in) :: prefix
976  !> Aerosol data.
977  type(aero_data_t), intent(in) :: aero_data
978  !> Array of aerosol states.
979  type(aero_state_t), dimension(nz), intent(in) :: aero_states
980  !> Gas data.
981  type(gas_data_t), intent(in) :: gas_data
982  !> Array of gas states.
983  type(gas_state_t), dimension(nz), intent(in) :: gas_states
984  !> Array of environment states.
985  type(env_state_t), dimension(nz), intent(in) :: env_states
986  !> Number of vertical levels.
987  integer, intent(in) :: nz
988  !> Filename index.
989  integer, intent(in) :: index
990  !> Current time (s).
991  real(kind=dp), intent(in) :: time
992  !> Current timestep (s).
993  real(kind=dp), intent(in) :: del_t
994  !> Current repeat number.
995  integer, intent(in) :: i_repeat
996  !> Whether to output particle removal info.
997  logical, intent(in) :: record_removals
998  !> Whether to output aerosol optical properties.
999  logical, intent(in) :: record_optical
1000  !> UUID of the simulation.
1001  character(len=PMC_UUID_LEN), intent(in) :: uuid
1002  !> Rank to write into file.
1003  integer, intent(in), optional :: write_rank
1004  !> Number of processes to write into file.
1005  integer, intent(in), optional :: write_n_proc
1006 
1007  character(len=len(prefix)+100) :: filename
1008  integer :: ncid
1009  character(len=50) :: group_name
1010  integer :: ncid_group
1011  integer :: k
1012 
1013 #ifdef PMC_USE_WRF
1014  write(filename,'(a,a,i3.3,a,i3.3,a,i8.8,a)') trim(prefix), '_', &
1015  env_states(1)%cell_ix, '_', env_states(1)%cell_iy, '_', index, '.nc'
1016  call pmc_nc_open_write(filename, ncid)
1017  call pmc_nc_write_info(ncid, uuid, &
1018  "WRF-PartMC version " // trim(partmc_version), write_rank, &
1019  write_n_proc)
1020  call write_time(ncid, time, del_t, index)
1021 
1022  call gas_data_output_netcdf(gas_data, ncid)
1023  call aero_data_output_netcdf(aero_data, ncid)
1024 
1025  do k = 1,nz
1026  call pmc_nc_check(nf90_redef(ncid))
1027  write(group_name,'(a,i2.2)') 'level_', env_states(k)%cell_iz
1028  call pmc_nc_check(nf90_def_grp(ncid, group_name, ncid_group))
1029  call pmc_nc_check(nf90_enddef(ncid))
1030  call env_state_output_netcdf(env_states(k), ncid_group)
1031  call gas_state_output_netcdf(gas_states(k), ncid_group, gas_data)
1032  call aero_state_output_netcdf(aero_states(k), ncid_group, aero_data, &
1033  record_removals, record_optical)
1034  end do
1035 
1036  call pmc_nc_check(nf90_close(ncid))
1037 #endif
1038 
1039  end subroutine output_column_to_file
1040 
1041 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1042 
1043  !> Reads in the current state of a column of a WRF-PartMC domain.
1044  subroutine input_column_to_file(filename, index, time, del_t, i_repeat, nz, &
1045  uuid, aero_data, aero_states, gas_data, gas_states, env_states)
1046 
1047  !> Prefix of state file.
1048  character(len=*), intent(in) :: filename
1049  !> Aerosol data.
1050  type(aero_data_t), intent(inout) :: aero_data
1051  !> Array of aerosol states.
1052  type(aero_state_t), dimension(nz), intent(inout) :: aero_states
1053  !> Gas data.
1054  type(gas_data_t), intent(inout) :: gas_data
1055  !> Array of gas states.
1056  type(gas_state_t), dimension(nz), intent(inout) :: gas_states
1057  !> Array of environment states.
1058  type(env_state_t), dimension(nz), intent(inout) :: env_states
1059  !> Number of vertical levels.
1060  integer, intent(in) :: nz
1061  !> Filename index.
1062  integer, intent(out) :: index
1063  !> Current time (s).
1064  real(kind=dp), intent(out) :: time
1065  !> Current timestep (s).
1066  real(kind=dp), intent(out) :: del_t
1067  !> Current repeat number.
1068  integer, intent(out) :: i_repeat
1069  !> UUID of the simulation.
1070  character(len=PMC_UUID_LEN), intent(out) :: uuid
1071 
1072  integer :: ncid
1073  character(len=50) :: group_name
1074  integer :: ncid_group
1075  integer :: n_groups
1076  integer, allocatable :: ncid_groups(:)
1077  integer :: k
1078 
1079 #ifdef PMC_USE_WRF
1080  call pmc_nc_open_read(filename, ncid)
1081 
1082  call pmc_nc_check(nf90_get_att(ncid, nf90_global, "UUID", uuid))
1083  call pmc_nc_read_real(ncid, time, "time")
1084  call pmc_nc_read_real(ncid, del_t, "timestep")
1085  call pmc_nc_read_integer(ncid, index, "timestep_index")
1086 
1087  call gas_data_input_netcdf(gas_data, ncid)
1088  call aero_data_input_netcdf(aero_data, ncid)
1089 
1090  call pmc_nc_check(nf90_inq_grps(ncid, n_groups, ncid_groups))
1091 
1092  call assert_msg(819739350, size(aero_states) == n_groups, &
1093  "number of levels in file do not match expected number of levels")
1094 
1095  do k = 1,nz
1096  write(group_name,'(a,i2.2)') 'level_', k
1097  call pmc_nc_check(nf90_inq_ncid(ncid, group_name, ncid_group))
1098  call env_state_input_netcdf(env_states(k), ncid_group)
1099  call gas_state_input_netcdf(gas_states(k), ncid_group, gas_data)
1100  call aero_state_input_netcdf(aero_states(k), ncid_group, aero_data)
1101  end do
1102 
1103  call pmc_nc_check(nf90_close(ncid))
1104 #endif
1105 
1106  end subroutine input_column_to_file
1107 
1108 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1109 
1110 end module pmc_output
pmc_output::partmc_version
character(len=100), parameter partmc_version
PartMC verson number.
Definition: output.F90:86
pmc_netcdf::pmc_nc_write_integer
subroutine pmc_nc_write_integer(ncid, var, name, unit, long_name, standard_name, description)
Write a single integer to a NetCDF file.
Definition: netcdf.F90:736
pmc_gas_data::gas_data_t
Constant gas data.
Definition: gas_data.F90:35
pmc_mpi::pmc_mpi_size
integer function pmc_mpi_size()
Returns the total number of processes.
Definition: mpi.F90:134
pmc_mpi
Wrapper functions for MPI.
Definition: mpi.F90:13
pmc_scenario::drydep_params_output_netcdf
subroutine drydep_params_output_netcdf(drydep_params, ncid)
Write dry deposition parameters to a NetCDF file.
Definition: scenario.F90:1452
pmc_output::input_state
subroutine input_state(filename, index, time, del_t, i_repeat, uuid, aero_data, aero_state, gas_data, gas_state, env_state)
Read the current state.
Definition: output.F90:499
pmc_util::get_unit
integer function get_unit()
Returns an available unit number. This should be freed by free_unit().
Definition: util.F90:149
pmc_env_state::env_state_input_netcdf
subroutine env_state_input_netcdf(env_state, ncid)
Read full state.
Definition: env_state.F90:613
pmc_scenario
The scenario_t structure and associated subroutines.
Definition: scenario.F90:9
pmc_scenario::scenario_t
Scenario data.
Definition: scenario.F90:86
pmc_gas_data
The gas_data_t structure and associated subroutines.
Definition: gas_data.F90:9
pmc_env_state::pmc_mpi_unpack_env_state
subroutine pmc_mpi_unpack_env_state(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: env_state.F90:468
pmc_output::output_sectional
subroutine output_sectional(prefix, bin_grid, aero_data, aero_binned, gas_data, gas_state, env_state, index, time, del_t, uuid)
Write the current sectional data.
Definition: output.F90:666
pmc_util::die_msg
subroutine die_msg(code, error_msg)
Error immediately.
Definition: util.F90:135
pmc_mpi::pmc_mpi_rank
integer function pmc_mpi_rank()
Returns the rank of the current process.
Definition: mpi.F90:117
pmc_netcdf
Wrapper functions for NetCDF. These all take a NetCDF ncid in data mode and return with it again in d...
Definition: netcdf.F90:11
pmc_output::output_type_central
integer, parameter output_type_central
Type code for centralized output (one file per process, all written by process 0).
Definition: output.F90:92
pmc_constants::dp
integer, parameter dp
Kind of a double precision real number.
Definition: constants.F90:12
pmc_output::output_state
subroutine output_state(prefix, output_type, aero_data, aero_state, gas_data, gas_state, env_state, index, time, del_t, i_repeat, record_removals, record_optical, uuid)
Write the current state.
Definition: output.F90:113
pmc_output::input_n_files
subroutine input_n_files(prefix, n_repeat, n_index)
Find the number of repeats and indices for the given prefix.
Definition: output.F90:610
pmc_env_state::env_state_t
Current environment state.
Definition: env_state.F90:29
pmc_util::assert
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
Definition: util.F90:104
pmc_output::tag_output_state_central
integer, parameter tag_output_state_central
Internal-use variable only.
Definition: output.F90:101
pmc_aero_state
The aero_state_t structure and assocated subroutines.
Definition: aero_state.F90:9
pmc_netcdf::pmc_nc_read_integer
subroutine pmc_nc_read_integer(ncid, var, name, must_be_present)
Read a single integer from a NetCDF file.
Definition: netcdf.F90:185
pmc_output::send_output_state_central
subroutine send_output_state_central(aero_state, gas_state, env_state)
Send the state for the "central" output method to the root process.
Definition: output.F90:388
pmc_output::make_filename
subroutine make_filename(filename, prefix, suffix, index, i_repeat, write_rank, write_n_proc)
Make a filename from a given prefix and other information.
Definition: output.F90:210
pmc_spec_file::spec_file_t
An input file with extra data for printing messages.
Definition: spec_file.F90:59
pmc_netcdf::pmc_nc_open_read
subroutine pmc_nc_open_read(filename, ncid)
Open a NetCDF file for reading.
Definition: netcdf.F90:55
pmc_output::input_column_to_file
subroutine input_column_to_file(filename, index, time, del_t, i_repeat, nz, uuid, aero_data, aero_states, gas_data, gas_states, env_states)
Reads in the current state of a column of a WRF-PartMC domain.
Definition: output.F90:1046
pmc_env_state::env_state_reduce_avg
subroutine env_state_reduce_avg(val)
Average val over all processes, with the result only on the root process.
Definition: env_state.F90:361
pmc_netcdf::pmc_nc_write_info
subroutine pmc_nc_write_info(ncid, uuid, source, write_rank, write_n_proc)
Write basic information to a NetCDF file.
Definition: netcdf.F90:99
pmc_gas_state
The gas_state_t structure and associated subroutines.
Definition: gas_state.F90:9
pmc_aero_data::aero_data_input_netcdf
subroutine aero_data_input_netcdf(aero_data, ncid)
Read full state.
Definition: aero_data.F90:955
pmc_netcdf::pmc_nc_open_write
subroutine pmc_nc_open_write(filename, ncid)
Open a NetCDF file for writing.
Definition: netcdf.F90:70
pmc_gas_state::pmc_mpi_unpack_gas_state
subroutine pmc_mpi_unpack_gas_state(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: gas_state.F90:547
pmc_env_state::pmc_mpi_pack_env_state
subroutine pmc_mpi_pack_env_state(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: env_state.F90:421
pmc_gas_state::gas_state_reduce_avg
subroutine gas_state_reduce_avg(val)
Average val over all processes, with the result only on the root process.
Definition: gas_state.F90:491
pmc_scenario::drydep_params_input_netcdf
subroutine drydep_params_input_netcdf(drydep_params, ncid)
Read dry deposition parameters from a NetCDF file.
Definition: scenario.F90:1480
pmc_output::input_modal
subroutine input_modal(filename, index, time, del_t, uuid, aero_dist, aero_binned, aero_data, env_state, gas_data, gas_state, bin_grid, scenario)
Input modal data.
Definition: output.F90:849
pmc_util::integer_to_string
character(len=pmc_util_convert_string_len) function integer_to_string(val)
Convert an integer to a string format.
Definition: util.F90:767
pmc_util::assert_msg
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
Definition: util.F90:78
pmc_output::output_type_single
integer, parameter output_type_single
Type code for single output (one file for all processes, written by process 0).
Definition: output.F90:98
pmc_netcdf::pmc_nc_write_real
subroutine pmc_nc_write_real(ncid, var, name, unit, long_name, standard_name, description)
Write a single real to a NetCDF file.
Definition: netcdf.F90:703
pmc_bin_grid::bin_grid_output_netcdf
subroutine bin_grid_output_netcdf(bin_grid, ncid, dim_name, unit, long_name, scale)
Write a bin grid to the given NetCDF file.
Definition: bin_grid.F90:554
pmc_bin_grid::bin_grid_input_netcdf
subroutine bin_grid_input_netcdf(bin_grid, ncid, dim_name, scale)
Read full state.
Definition: bin_grid.F90:579
pmc_output::write_time
subroutine write_time(ncid, time, del_t, index)
Helper routine to write time variables. Do not call directly.
Definition: output.F90:255
pmc_env_state
The env_state_t structure and associated subroutines.
Definition: env_state.F90:9
pmc_gas_state::gas_state_t
Current state of the gas mixing ratios in the system.
Definition: gas_state.F90:33
pmc_aero_state::aero_state_input_netcdf
subroutine aero_state_input_netcdf(aero_state, ncid, aero_data)
Read full state.
Definition: aero_state.F90:3087
pmc_util::ensure_string_array_size
subroutine ensure_string_array_size(x, n)
Allocate or reallocate the given array to ensure it is of the given size, without preserving data.
Definition: util.F90:1470
pmc_gas_data::gas_data_input_netcdf
subroutine gas_data_input_netcdf(gas_data, ncid)
Read full state.
Definition: gas_data.F90:417
pmc_aero_data::aero_data_t
Aerosol material properties and associated data.
Definition: aero_data.F90:55
pmc_output
Write data in NetCDF format.
Definition: output.F90:68
pmc_aero_state::aero_state_mpi_gather
subroutine aero_state_mpi_gather(aero_state, aero_state_total, aero_data)
Gathers data from all processes into one aero_state on process 0.
Definition: aero_state.F90:2445
pmc_aero_state::pmc_mpi_unpack_aero_state
subroutine pmc_mpi_unpack_aero_state(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: aero_state.F90:2418
pmc_mpi::pmc_mpi_check_ierr
subroutine pmc_mpi_check_ierr(ierr)
Dies if ierr is not ok.
Definition: mpi.F90:40
pmc_aero_state::pmc_mpi_pack_aero_state
subroutine pmc_mpi_pack_aero_state(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: aero_state.F90:2392
pmc_aero_state::pmc_mpi_pack_size_aero_state
integer function pmc_mpi_pack_size_aero_state(val)
Determines the number of bytes required to pack the given value.
Definition: aero_state.F90:2373
pmc_netcdf::pmc_nc_close
subroutine pmc_nc_close(ncid)
Close a NetCDF file.
Definition: netcdf.F90:87
pmc_netcdf::pmc_nc_check
subroutine pmc_nc_check(status)
Check the status of a NetCDF function call.
Definition: netcdf.F90:23
pmc_util
Common utility subroutines.
Definition: util.F90:9
pmc_output::input_sectional
subroutine input_sectional(filename, index, time, del_t, uuid, bin_grid, aero_data, aero_binned, gas_data, gas_state, env_state)
Input sectional data.
Definition: output.F90:717
pmc_gas_state::pmc_mpi_pack_gas_state
subroutine pmc_mpi_pack_gas_state(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: gas_state.F90:524
pmc_spec_file::spec_file_die_msg
subroutine spec_file_die_msg(code, file, msg)
Exit with an error message containing filename and line number.
Definition: spec_file.F90:74
pmc_aero_binned
The aero_binned_t structure and associated subroutines.
Definition: aero_binned.F90:9
pmc_spec_file::spec_file_read_string
subroutine spec_file_read_string(file, name, var)
Read a string from a spec file that must have a given name.
Definition: spec_file.F90:624
pmc_aero_binned::aero_binned_input_netcdf
subroutine aero_binned_input_netcdf(aero_binned, ncid, bin_grid, aero_data)
Read full state.
Definition: aero_binned.F90:467
pmc_output::tag_output_state_single
integer, parameter tag_output_state_single
Internal-use variable only.
Definition: output.F90:103
pmc_util::free_unit
subroutine free_unit(unit)
Frees a unit number returned by get_unit().
Definition: util.F90:173
pmc_aero_binned::aero_binned_t
Aerosol number and volume distributions stored per bin.
Definition: aero_binned.F90:37
pmc_bin_grid
The bin_grid_t structure and associated subroutines.
Definition: bin_grid.F90:9
pmc_netcdf::pmc_nc_read_real
subroutine pmc_nc_read_real(ncid, var, name, must_be_present)
Read a single real from a NetCDF file.
Definition: netcdf.F90:150
pmc_aero_data
The aero_data_t structure and associated subroutines.
Definition: aero_data.F90:9
pmc_bin_grid::bin_grid_t
1D grid, either logarithmic or linear.
Definition: bin_grid.F90:33
pmc_env_state::pmc_mpi_pack_size_env_state
integer function pmc_mpi_pack_size_env_state(val)
Determines the number of bytes required to pack the given value.
Definition: env_state.F90:384
pmc_gas_state::pmc_mpi_pack_size_gas_state
integer function pmc_mpi_pack_size_gas_state(val)
Determines the number of bytes required to pack the given value.
Definition: gas_state.F90:511
pmc_output::output_type_invalid
integer, parameter output_type_invalid
Type code for undefined or invalid output.
Definition: output.F90:89
pmc_aero_state::aero_state_t
The current collection of aerosol particles.
Definition: aero_state.F90:69
pmc_output::recv_output_state_central
subroutine recv_output_state_central(prefix, aero_data, gas_data, index, time, del_t, i_repeat, record_removals, record_optical, uuid, remote_proc)
Receive the state for the "central" output method on the root process.
Definition: output.F90:431
pmc_output::output_type_dist
integer, parameter output_type_dist
Type code for distributed output (one file per process, written by each process).
Definition: output.F90:95
pmc_output::input_filename_list
subroutine input_filename_list(prefix, filename_list)
Find all NetCDF (.nc) filenames that match the given prefix.
Definition: output.F90:569
pmc_output::output_column_to_file
subroutine output_column_to_file(prefix, aero_data, aero_states, gas_data, gas_states, env_states, nz, index, time, del_t, i_repeat, record_removals, record_optical, uuid, write_rank, write_n_proc)
Writes the current state of a column of a WRF-PartMC domain.
Definition: output.F90:973
pmc_output::output_modal
subroutine output_modal(prefix, aero_binned, aero_dist, aero_data, env_state, gas_data, gas_state, bin_grid, scenario, index, time, del_t, uuid)
Write the current modal data.
Definition: output.F90:792
pmc_gas_state::gas_state_input_netcdf
subroutine gas_state_input_netcdf(gas_state, ncid, gas_data)
Read full state.
Definition: gas_state.F90:622