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, scenario, 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  !> Scenario data.
682  type(scenario_t), intent(in) :: scenario
683  !> Filename index.
684  integer, intent(in) :: index
685  !> Current time (s).
686  real(kind=dp), intent(in) :: time
687  !> Current output time-step (s).
688  real(kind=dp), intent(in) :: del_t
689  !> UUID of the simulation.
690  character(len=PMC_UUID_LEN), intent(in) :: uuid
691 
692  integer :: ncid
693  character(len=len(prefix)+100) :: filename
694 
695  write(filename, '(a,a,i8.8,a)') trim(prefix), &
696  '_', index, '.nc'
697  call pmc_nc_open_write(filename, ncid)
698  call pmc_nc_write_info(ncid, uuid, &
699  "PartMC version " // trim(partmc_version))
700  call write_time(ncid, time, del_t, index)
701 
702  ! write data
703  call env_state_output_netcdf(env_state, ncid)
704  call gas_data_output_netcdf(gas_data, ncid)
705  call gas_state_output_netcdf(gas_state, ncid, gas_data)
706  call aero_data_output_netcdf(aero_data, ncid)
707  call aero_binned_output_netcdf(aero_binned, ncid, bin_grid, &
708  aero_data)
709 
710  if (scenario%loss_function_type == scenario_loss_function_drydep) then
711  call drydep_params_output_netcdf(scenario%drydep, ncid)
712  end if
713 
714  call pmc_nc_check(nf90_close(ncid))
715 
716  end subroutine output_sectional
717 
718 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
719 
720  !> Input sectional data.
721  subroutine input_sectional(filename, index, time, del_t, uuid, bin_grid, &
722  aero_data, aero_binned, gas_data, gas_state, env_state, scenario)
723 
724  !> Filename to read.
725  character(len=*), intent(in) :: filename
726  !> Filename index.
727  integer, intent(out) :: index
728  !> Current time (s).
729  real(kind=dp), intent(out) :: time
730  !> Current output time-step (s).
731  real(kind=dp), intent(out) :: del_t
732  !> UUID of the simulation.
733  character(len=PMC_UUID_LEN), intent(out) :: uuid
734  !> Bin grid.
735  type(bin_grid_t), optional, intent(inout) :: bin_grid
736  !> Aerosol data.
737  type(aero_data_t), optional, intent(inout) :: aero_data
738  !> Binned aerosol data.
739  type(aero_binned_t), optional, intent(inout) :: aero_binned
740  !> Gas data.
741  type(gas_data_t), optional, intent(inout) :: gas_data
742  !> Gas state.
743  type(gas_state_t), optional, intent(inout) :: gas_state
744  !> Environment state.
745  type(env_state_t), optional, intent(inout) :: env_state
746  !> Scenario data.
747  type(scenario_t), optional, intent(inout) :: scenario
748 
749  integer :: ncid
750 
751  call assert_msg(559676785, pmc_mpi_rank() == 0, &
752  "can only call from process 0")
753 
754  call pmc_nc_open_read(filename, ncid)
755 
756  call pmc_nc_check(nf90_get_att(ncid, nf90_global, "UUID", uuid))
757 
758  call pmc_nc_read_real(ncid, time, "time")
759  call pmc_nc_read_real(ncid, del_t, "timestep")
760  call pmc_nc_read_integer(ncid, index, "timestep_index")
761 
762  if (present(bin_grid)) then
763  call bin_grid_input_netcdf(bin_grid, ncid, "aero_diam", scale=0.5d0)
764  end if
765  if (present(aero_data)) then
766  call aero_data_input_netcdf(aero_data, ncid)
767  end if
768  if (present(aero_binned)) then
769  call assert_msg(585353528, &
770  present(bin_grid) .and. present(aero_data), &
771  "cannot input aero_binned without bin_grid and aero_data")
772  call aero_binned_input_netcdf(aero_binned, ncid, bin_grid, &
773  aero_data)
774  end if
775 
776  if (present(gas_data)) then
777  call gas_data_input_netcdf(gas_data, ncid)
778  if (present(gas_state)) then
779  call gas_state_input_netcdf(gas_state, ncid, gas_data)
780  end if
781  else
782  call assert_msg(214545112, present(gas_state) .eqv. .false., &
783  "cannot input gas_state without gas_data")
784  end if
785 
786  if (present(env_state)) then
787  call env_state_input_netcdf(env_state, ncid)
788  end if
789 
790  if (present(scenario)) then
791  call drydep_params_input_netcdf(scenario%drydep, ncid, &
792  must_be_present=.false.)
793  end if
794 
795  call pmc_nc_close(ncid)
796 
797  end subroutine input_sectional
798 
799 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
800 
801  !> Write the current modal data.
802  subroutine output_modal(prefix, aero_binned, aero_dist, aero_data, &
803  env_state, gas_data, gas_state, bin_grid, &
804  scenario, index, time, del_t, uuid)
805 
806  !> Prefix of filename to write.
807  character(len=*), intent(in) :: prefix
808  !> Binned aerosol distribution.
809  type(aero_binned_t), intent(in) :: aero_binned
810  !> Aerosol distribution.
811  type(aero_dist_t), intent(in) :: aero_dist
812  !> Aerosol data.
813  type(aero_data_t), intent(in) :: aero_data
814  !> Environment state.
815  type(env_state_t), intent(in) :: env_state
816  !> Gas data.
817  type(gas_data_t), intent(in) :: gas_data
818  !> Gas state.
819  type(gas_state_t), intent(in) :: gas_state
820  !> Bin grid.
821  type(bin_grid_t), intent(in) :: bin_grid
822  !> Scenario data.
823  type(scenario_t), intent(in) :: scenario
824  !> Filename index.
825  integer, intent(in) :: index
826  !> Current time (s).
827  real(kind=dp), intent(in) :: time
828  !> Current output timestep (s).
829  real(kind=dp), intent(in) :: del_t
830  !> UUID of the simulation.
831  character(len=PMC_UUID_LEN), intent(in) :: uuid
832 
833  integer :: ncid
834  character(len=len(prefix)+100) :: filename
835 
836  write(filename, '(a,a,i8.8,a)') trim(prefix), '_', index, '.nc'
837  call pmc_nc_open_write(filename, ncid)
838  call pmc_nc_write_info(ncid, uuid, &
839  "PartMC version " // trim(partmc_version))
840  call write_time(ncid, time, del_t, index)
841 
842  ! Write data.
843  call aero_binned_output_netcdf(aero_binned, ncid, bin_grid, aero_data)
844  call aero_dist_output_netcdf(aero_dist, ncid)
845  call env_state_output_netcdf(env_state, ncid)
846  call gas_data_output_netcdf(gas_data, ncid)
847  call gas_state_output_netcdf(gas_state, ncid, gas_data)
848  call aero_data_output_netcdf(aero_data, ncid)
849  call bin_grid_output_netcdf(bin_grid, ncid, "diam", unit="m")
850 
851  if (scenario%loss_function_type == scenario_loss_function_drydep) then
852  call drydep_params_output_netcdf(scenario%drydep, ncid)
853  end if
854 
855  call pmc_nc_check(nf90_close(ncid))
856 
857  end subroutine output_modal
858 
859 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
860 
861  !> Input modal data.
862  subroutine input_modal(filename, index, time, del_t, uuid, aero_dist, &
863  aero_binned, aero_data, env_state, gas_data, gas_state, bin_grid, &
864  scenario)
865 
866  !> Filename to read.
867  character(len=*), intent(in) :: filename
868  !> Filename index.
869  integer, intent(out) :: index
870  !> Current time (s).
871  real(kind=dp), intent(out) :: time
872  !> Current output timestep.
873  real(kind=dp), intent(out) :: del_t
874  !> UUID of the simulation.
875  character(len=PMC_UUID_LEN), intent(out) :: uuid
876  !> Aerosol distribution
877  type(aero_dist_t), optional, intent(inout) :: aero_dist
878  !> Binned aerosol distribution.
879  type(aero_binned_t), optional, intent(inout) :: aero_binned
880  !> Aerosol data.
881  type(aero_data_t), optional, intent(inout) :: aero_data
882  !> Environment state.
883  type(env_state_t), optional, intent(inout) :: env_state
884  !> Gas data.
885  type(gas_data_t), optional, intent(inout) :: gas_data
886  !> Gas state.
887  type(gas_state_t), optional, intent(inout) :: gas_state
888  !> Bin grid.
889  type(bin_grid_t), optional, intent(inout) :: bin_grid
890  !> Scenario data.
891  type(scenario_t), optional, intent(inout) :: scenario
892 
893  integer :: ncid
894 
895  call assert_msg(348927561, pmc_mpi_rank() == 0, &
896  "can only call from process 0")
897 
898  call pmc_nc_open_read(filename, ncid)
899 
900  call pmc_nc_check(nf90_get_att(ncid, nf90_global, "UUID", uuid))
901 
902  call pmc_nc_read_real(ncid, time, "time")
903  call pmc_nc_read_real(ncid, del_t, "timestep")
904  call pmc_nc_read_integer(ncid, index, "timestep_index")
905 
906  if (present(aero_data)) then
907  call aero_data_input_netcdf(aero_data, ncid)
908  end if
909 
910  if (present(aero_dist)) then
911  call aero_dist_input_netcdf(aero_dist, ncid)
912  end if
913 
914  if (present(env_state)) then
915  call env_state_input_netcdf(env_state, ncid)
916  end if
917 
918  if (present(gas_data)) then
919  call gas_data_input_netcdf(gas_data, ncid)
920  if (present(gas_state)) then
921  call gas_state_input_netcdf(gas_state, ncid, gas_data)
922  end if
923  else
924  call assert_msg(739182654, present(gas_state) .eqv. .false., &
925  "cannot input gas_state without gas_data")
926  end if
927 
928  if (present(bin_grid)) then
929  call bin_grid_input_netcdf(bin_grid, ncid, "diam")
930  if (present(aero_binned)) then
931  call aero_binned_input_netcdf(aero_binned, ncid, bin_grid, aero_data)
932  end if
933  else
934  call assert_msg(582491376, present(aero_binned) .eqv. .false., &
935  "cannot input aero_binned without bin_grid")
936  end if
937 
938  if (present(scenario)) then
939  call drydep_params_input_netcdf(scenario%drydep, ncid, &
940  must_be_present=.false.)
941  end if
942 
943  end subroutine input_modal
944 
945 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
946 
947  !> Read the specification for an output type from a spec file and
948  !> generate it.
949  subroutine spec_file_read_output_type(file, output_type)
950 
951  !> Spec file.
952  type(spec_file_t), intent(inout) :: file
953  !> Kernel type.
954  integer, intent(out) :: output_type
955 
956  character(len=SPEC_LINE_MAX_VAR_LEN) :: output_type_name
957 
958  !> \page input_format_output Input File Format: Output Type
959  !!
960  !! The output type is specified by the parameter:
961  !! - \b output_type (string): type of disk output --- must be
962  !! one of: \c central to write one file per process, but all
963  !! written by process 0; \c dist for every process to
964  !! write its own state file; or \c single to transfer all data
965  !! to process 0 and write a single unified output file
966  !!
967  !! See also:
968  !! - \ref spec_file_format --- the input file text format
969 
970  call spec_file_read_string(file, 'output_type', output_type_name)
971  if (trim(output_type_name) == 'central') then
972  output_type = output_type_central
973  elseif (trim(output_type_name) == 'dist') then
974  output_type = output_type_dist
975  elseif (trim(output_type_name) == 'single') then
976  output_type = output_type_single
977  else
978  call spec_file_die_msg(392313600, file, &
979  "Unknown output type: " // trim(output_type_name))
980  end if
981 
982  end subroutine spec_file_read_output_type
983 
984 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
985 
986  !> Writes the current state of a column of a WRF-PartMC domain.
987  subroutine output_column_to_file(prefix, aero_data, aero_states, gas_data, &
988  gas_states, env_states, nz, index, time, del_t, i_repeat, &
989  record_removals, record_optical, uuid, write_rank, write_n_proc)
990 
991  !> Prefix of state file.
992  character(len=*), intent(in) :: prefix
993  !> Aerosol data.
994  type(aero_data_t), intent(in) :: aero_data
995  !> Array of aerosol states.
996  type(aero_state_t), dimension(nz), intent(in) :: aero_states
997  !> Gas data.
998  type(gas_data_t), intent(in) :: gas_data
999  !> Array of gas states.
1000  type(gas_state_t), dimension(nz), intent(in) :: gas_states
1001  !> Array of environment states.
1002  type(env_state_t), dimension(nz), intent(in) :: env_states
1003  !> Number of vertical levels.
1004  integer, intent(in) :: nz
1005  !> Filename index.
1006  integer, intent(in) :: index
1007  !> Current time (s).
1008  real(kind=dp), intent(in) :: time
1009  !> Current timestep (s).
1010  real(kind=dp), intent(in) :: del_t
1011  !> Current repeat number.
1012  integer, intent(in) :: i_repeat
1013  !> Whether to output particle removal info.
1014  logical, intent(in) :: record_removals
1015  !> Whether to output aerosol optical properties.
1016  logical, intent(in) :: record_optical
1017  !> UUID of the simulation.
1018  character(len=PMC_UUID_LEN), intent(in) :: uuid
1019  !> Rank to write into file.
1020  integer, intent(in), optional :: write_rank
1021  !> Number of processes to write into file.
1022  integer, intent(in), optional :: write_n_proc
1023 
1024  character(len=len(prefix)+100) :: filename
1025  integer :: ncid
1026  character(len=50) :: group_name
1027  integer :: ncid_group
1028  integer :: k
1029 
1030 #ifdef PMC_USE_WRF
1031  write(filename,'(a,a,i3.3,a,i3.3,a,i8.8,a)') trim(prefix), '_', &
1032  env_states(1)%cell_ix, '_', env_states(1)%cell_iy, '_', index, '.nc'
1033  call pmc_nc_open_write(filename, ncid)
1034  call pmc_nc_write_info(ncid, uuid, &
1035  "WRF-PartMC version " // trim(partmc_version), write_rank, &
1036  write_n_proc)
1037  call write_time(ncid, time, del_t, index)
1038 
1039  call gas_data_output_netcdf(gas_data, ncid)
1040  call aero_data_output_netcdf(aero_data, ncid)
1041 
1042  do k = 1,nz
1043  call pmc_nc_check(nf90_redef(ncid))
1044  write(group_name,'(a,i2.2)') 'level_', env_states(k)%cell_iz
1045  call pmc_nc_check(nf90_def_grp(ncid, group_name, ncid_group))
1046  call pmc_nc_check(nf90_enddef(ncid))
1047  call env_state_output_netcdf(env_states(k), ncid_group)
1048  call gas_state_output_netcdf(gas_states(k), ncid_group, gas_data)
1049  call aero_state_output_netcdf(aero_states(k), ncid_group, aero_data, &
1050  record_removals, record_optical)
1051  end do
1052 
1053  call pmc_nc_check(nf90_close(ncid))
1054 #endif
1055 
1056  end subroutine output_column_to_file
1057 
1058 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1059 
1060  !> Reads in the current state of a column of a WRF-PartMC domain.
1061  subroutine input_column_to_file(filename, index, time, del_t, i_repeat, nz, &
1062  uuid, aero_data, aero_states, gas_data, gas_states, env_states)
1063 
1064  !> Prefix of state file.
1065  character(len=*), intent(in) :: filename
1066  !> Aerosol data.
1067  type(aero_data_t), intent(inout) :: aero_data
1068  !> Array of aerosol states.
1069  type(aero_state_t), dimension(nz), intent(inout) :: aero_states
1070  !> Gas data.
1071  type(gas_data_t), intent(inout) :: gas_data
1072  !> Array of gas states.
1073  type(gas_state_t), dimension(nz), intent(inout) :: gas_states
1074  !> Array of environment states.
1075  type(env_state_t), dimension(nz), intent(inout) :: env_states
1076  !> Number of vertical levels.
1077  integer, intent(in) :: nz
1078  !> Filename index.
1079  integer, intent(out) :: index
1080  !> Current time (s).
1081  real(kind=dp), intent(out) :: time
1082  !> Current timestep (s).
1083  real(kind=dp), intent(out) :: del_t
1084  !> Current repeat number.
1085  integer, intent(out) :: i_repeat
1086  !> UUID of the simulation.
1087  character(len=PMC_UUID_LEN), intent(out) :: uuid
1088 
1089  integer :: ncid
1090  character(len=50) :: group_name
1091  integer :: ncid_group
1092  integer :: n_groups
1093  integer, allocatable :: ncid_groups(:)
1094  integer :: k
1095 
1096 #ifdef PMC_USE_WRF
1097  call pmc_nc_open_read(filename, ncid)
1098 
1099  call pmc_nc_check(nf90_get_att(ncid, nf90_global, "UUID", uuid))
1100  call pmc_nc_read_real(ncid, time, "time")
1101  call pmc_nc_read_real(ncid, del_t, "timestep")
1102  call pmc_nc_read_integer(ncid, index, "timestep_index")
1103 
1104  call gas_data_input_netcdf(gas_data, ncid)
1105  call aero_data_input_netcdf(aero_data, ncid)
1106 
1107  call pmc_nc_check(nf90_inq_grps(ncid, n_groups, ncid_groups))
1108 
1109  call assert_msg(819739350, size(aero_states) == n_groups, &
1110  "number of levels in file do not match expected number of levels")
1111 
1112  do k = 1,nz
1113  write(group_name,'(a,i2.2)') 'level_', k
1114  call pmc_nc_check(nf90_inq_ncid(ncid, group_name, ncid_group))
1115  call env_state_input_netcdf(env_states(k), ncid_group)
1116  call gas_state_input_netcdf(gas_states(k), ncid_group, gas_data)
1117  call aero_state_input_netcdf(aero_states(k), ncid_group, aero_data)
1118  end do
1119 
1120  call pmc_nc_check(nf90_close(ncid))
1121 #endif
1122 
1123  end subroutine input_column_to_file
1124 
1125 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1126 
1127 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:1522
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:87
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_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:1063
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_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:865
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_scenario::scenario_loss_function_drydep
integer, parameter scenario_loss_function_drydep
Type code for a loss rate function based on dry deposition.
Definition: scenario.F90:38
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_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_output::output_sectional
subroutine output_sectional(prefix, bin_grid, aero_data, aero_binned, gas_data, gas_state, env_state, scenario, index, time, del_t, uuid)
Write the current sectional data.
Definition: output.F90:666
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::input_sectional
subroutine input_sectional(filename, index, time, del_t, uuid, bin_grid, aero_data, aero_binned, gas_data, gas_state, env_state, scenario)
Input sectional data.
Definition: output.F90:723
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:990
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:805
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
pmc_scenario::drydep_params_input_netcdf
subroutine drydep_params_input_netcdf(drydep_params, ncid, must_be_present)
Read dry deposition parameters from a NetCDF file.
Definition: scenario.F90:1550