PartMC  2.8.0
gas_state.F90
Go to the documentation of this file.
1 ! Copyright (C) 2007-2012 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_gas_state module.
7 
8 !> The gas_state_t structure and associated subroutines.
10 
11  use pmc_util
12  use pmc_spec_file
13  use pmc_gas_data
14  use pmc_env_state
15  use pmc_mpi
16  use pmc_netcdf
17 #ifdef PMC_USE_CAMP
18  use camp_camp_state
19 #endif
20 #ifdef PMC_USE_MPI
21  use mpi
22 #endif
23 
24  !> Current state of the gas mixing ratios in the system.
25  !!
26  !! The gas species are defined by the gas_data_t structure, so that
27  !! \c gas_state%%mix_rat(i) is the current mixing ratio of the gas
28  !! with name \c gas_data%%name(i), etc.
29  !!
30  !! By convention, if gas_state_is_allocated() return \c .false.,
31  !! then the gas_state is treated as zero for all operations on
32  !! it. This will be the case for new \c gas_state_t structures.
34  !> Length n_spec, mixing ratio (ppb).
35  real(kind=dp), allocatable :: mix_rat(:)
36  end type gas_state_t
37 
38 contains
39 
40 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
41 
42  !> Determine whether the \c gas_state is correctly allocated.
43  logical function gas_state_is_allocated(gas_state)
44 
45  !> Gas state to check.
46  type(gas_state_t), intent(in) :: gas_state
47 
48  gas_state_is_allocated = allocated(gas_state%mix_rat)
49 
50  end function gas_state_is_allocated
51 
52 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
53 
54  !> Sets the sizes of the gas state.
55  subroutine gas_state_set_size(gas_state, n_spec)
56 
57  !> Gas state to be allocated.
58  type(gas_state_t), intent(inout) :: gas_state
59  !> Number of species.
60  integer, intent(in) :: n_spec
61 
62  if (allocated(gas_state%mix_rat)) deallocate(gas_state%mix_rat)
63  allocate(gas_state%mix_rat(n_spec))
64  call gas_state_zero(gas_state)
65 
66  end subroutine gas_state_set_size
67 
68 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
69 
70  !> Zeros the state.
71  subroutine gas_state_zero(gas_state)
72 
73  !> Gas state.
74  type(gas_state_t), intent(inout) :: gas_state
75 
76  if (gas_state_is_allocated(gas_state)) then
77  gas_state%mix_rat = 0d0
78  end if
79 
80  end subroutine gas_state_zero
81 
82 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
83 
84  !> Scale a gas state.
85  subroutine gas_state_scale(gas_state, alpha)
86 
87  !> Existing gas state.
88  type(gas_state_t), intent(inout) :: gas_state
89  !> Scale factor.
90  real(kind=dp), intent(in) :: alpha
91 
92  if (gas_state_is_allocated(gas_state)) then
93  gas_state%mix_rat = gas_state%mix_rat * alpha
94  end if
95 
96  end subroutine gas_state_scale
97 
98 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
99 
100  !> Adds the given gas_state_delta.
101  subroutine gas_state_add(gas_state, gas_state_delta)
102 
103  !> Existing gas state.
104  type(gas_state_t), intent(inout) :: gas_state
105  !> Incremental state.
106  type(gas_state_t), intent(in) :: gas_state_delta
107 
108  if (gas_state_is_allocated(gas_state_delta)) then
109  if (gas_state_is_allocated(gas_state)) then
110  gas_state%mix_rat = gas_state%mix_rat + gas_state_delta%mix_rat
111  else
112  gas_state%mix_rat = gas_state_delta%mix_rat
113  end if
114  end if
115 
116  end subroutine gas_state_add
117 
118 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
119 
120  !> Adds the given \c gas_state_delta scaled by \c alpha.
121  !!
122  !! Does gas_state += alpha * gas_state_delta.
123  subroutine gas_state_add_scaled(gas_state, gas_state_delta, alpha)
124 
125  !> Existing gas state.
126  type(gas_state_t), intent(inout) :: gas_state
127  !> Incremental state.
128  type(gas_state_t), intent(in) :: gas_state_delta
129  !> Scale factor.
130  real(kind=dp), intent(in) :: alpha
131 
132  if (gas_state_is_allocated(gas_state_delta)) then
133  if (gas_state_is_allocated(gas_state)) then
134  gas_state%mix_rat = gas_state%mix_rat &
135  + alpha * gas_state_delta%mix_rat
136  else
137  gas_state%mix_rat = alpha * gas_state_delta%mix_rat
138  end if
139  end if
140 
141  end subroutine gas_state_add_scaled
142 
143 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
144 
145  !> Subtracts the given gas_state_delta.
146  subroutine gas_state_sub(gas_state, gas_state_delta)
147 
148  !> Existing gas state.
149  type(gas_state_t), intent(inout) :: gas_state
150  !> Incremental state.
151  type(gas_state_t), intent(in) :: gas_state_delta
152 
153  if (gas_state_is_allocated(gas_state_delta)) then
154  if (gas_state_is_allocated(gas_state)) then
155  gas_state%mix_rat = gas_state%mix_rat - gas_state_delta%mix_rat
156  else
157  gas_state%mix_rat = - gas_state_delta%mix_rat
158  end if
159  end if
160 
161  end subroutine gas_state_sub
162 
163 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
164 
165  !> Set any negative values to zero.
166  subroutine gas_state_ensure_nonnegative(gas_state)
167 
168  !> Gas state.
169  type(gas_state_t) :: gas_state
170 
171  if (gas_state_is_allocated(gas_state)) then
172  gas_state%mix_rat = max(gas_state%mix_rat, 0d0)
173  end if
174 
175  end subroutine gas_state_ensure_nonnegative
176 
177 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
178 
179  !> Convert (mol m^{-3}) to (ppb).
180  subroutine gas_state_molar_conc_to_ppb(gas_state, env_state)
181 
182  !> Gas state.
183  type(gas_state_t), intent(inout) :: gas_state
184  !> Environment state.
185  type(env_state_t), intent(in) :: env_state
186 
187  call gas_state_scale(gas_state, 1d9 / env_state_air_molar_den(env_state))
188 
189  end subroutine gas_state_molar_conc_to_ppb
190 
191 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
192 
193 #ifdef PMC_USE_CAMP
194  !> Set CAMP gas-phase species concentrations
195  subroutine gas_state_set_camp_conc(gas_state, env_state, camp_state, &
196  gas_data)
197 
198  !> Gas state
199  class(gas_state_t), intent(in) :: gas_state
200  ! Environmental state.
201  type(env_state_t), intent(in) :: env_state
202  !> CAMP state
203  type(camp_state_t), intent(inout) :: camp_state
204  !> Gas data
205  type(gas_data_t), intent(in) :: gas_data
206 
207  ! Convert relative humidity (1) to [H2O] (ppb)
208  camp_state%state_var(gas_data%i_camp_water) = &
210 
211  ! Convert from ppb to ppm
212  camp_state%state_var(1:size(gas_state%mix_rat)) = gas_state%mix_rat(:) &
213  / 1000.0d0
214 
215  end subroutine gas_state_set_camp_conc
216 
217 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
218 
219  !> Get CAMP gas-phase species concentrations
220  subroutine gas_state_get_camp_conc(gas_state, camp_state)
221 
222  !> Gas state
223  class(gas_state_t), intent(inout) :: gas_state
224  !> CAMP state
225  type(camp_state_t), intent(in) :: camp_state
226 
227  gas_state%mix_rat(:) = camp_state%state_var(1:size(gas_state%mix_rat)) &
228  * 1000.0d0
229 
230  end subroutine gas_state_get_camp_conc
231 #endif
232 
233 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
234 
235  !> Determine the current gas_state and rate by interpolating at the
236  !> current time with the lists of gas_states and rates.
237  subroutine gas_state_interp_1d(gas_state_list, time_list, &
238  rate_list, time, gas_state, rate)
239 
240  !> Gas states.
241  type(gas_state_t), intent(in) :: gas_state_list(:)
242  !> Times (s).
243  real(kind=dp), intent(in) :: time_list(size(gas_state_list))
244  !> Rates (s^{-1}).
245  real(kind=dp), intent(in) :: rate_list(size(gas_state_list))
246  !> Current time (s).
247  real(kind=dp), intent(in) :: time
248  !> Current gas state.
249  type(gas_state_t), intent(inout) :: gas_state
250  !> Current rate (s^{-1}).
251  real(kind=dp), intent(out) :: rate
252 
253  integer :: n, p
254  real(kind=dp) :: y, alpha
255 
256  n = size(gas_state_list)
257  p = find_1d(n, time_list, time)
258  if (p == 0) then
259  ! before the start, just use the first state and rate
260  gas_state = gas_state_list(1)
261  rate = rate_list(1)
262  elseif (p == n) then
263  ! after the end, just use the last state and rate
264  gas_state = gas_state_list(n)
265  rate = rate_list(n)
266  else
267  ! in the middle, use the previous state
268  gas_state = gas_state_list(p)
269  rate = rate_list(p)
270  end if
271 
272  end subroutine gas_state_interp_1d
273 
274 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
275 
276  !> Read gas state from the file named on the line read from file.
277  subroutine spec_file_read_gas_state(file, gas_data, gas_state)
278 
279  !> File to read gas state from.
280  type(spec_file_t), intent(inout) :: file
281  !> Gas data.
282  type(gas_data_t), intent(in) :: gas_data
283  !> Gas data to read.
284  type(gas_state_t), intent(inout) :: gas_state
285 
286  integer :: n_species, species, i
287  character(len=SPEC_LINE_MAX_VAR_LEN), allocatable :: species_name(:)
288  real(kind=dp), allocatable :: species_data(:,:)
289 
290  !> \page input_format_gas_state Input File Format: Gas State
291  !!
292  !! A gas state input file must consist of one line per gas
293  !! species, with each line having the species name followed by the
294  !! species mixing ratio in ppb (parts per billion). The valid
295  !! species names are those specfied by the \ref
296  !! input_format_gas_data file, but not all species have to be
297  !! listed. Any missing species will have mixing ratios of
298  !! zero. For example, a gas state file could contain:
299  !! <pre>
300  !! # gas mixing ratio (ppb)
301  !! H2SO4 0
302  !! HNO3 1
303  !! HCl 0.7
304  !! NH3 0.5
305  !! </pre>
306  !!
307  !! See also:
308  !! - \ref spec_file_format --- the input file text format
309  !! - \ref output_format_gas_state --- the corresponding output format
310  !! - \ref input_format_gas_data --- the gas species list and
311  !! material data
312 
313  call spec_file_read_real_named_array(file, 0, species_name, &
314  species_data)
315 
316  ! check the data size
317  n_species = size(species_data, 1)
318  if (.not. ((size(species_data, 2) == 1) .or. (n_species == 0))) then
319  call die_msg(686719840, 'each line in ' // trim(file%name) &
320  // ' must contain exactly one data value')
321  end if
322 
323  ! copy over the data
324  call gas_state_set_size(gas_state, gas_data_n_spec(gas_data))
325  do i = 1,n_species
326  species = gas_data_spec_by_name(gas_data, species_name(i))
327  if (species == 0) then
328  call die_msg(129794076, 'unknown species ' // &
329  trim(species_name(i)) // ' in file ' // trim(file%name))
330  end if
331  gas_state%mix_rat(species) = species_data(i,1)
332  end do
333 
334  end subroutine spec_file_read_gas_state
335 
336 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
337 
338  !> Read an array of gas states with associated times and rates from
339  !> the file named on the line read from the given file.
340  subroutine spec_file_read_gas_states_times_rates(file, gas_data, &
341  times, rates, gas_states)
342 
343  !> Spec file.
344  type(spec_file_t), intent(inout) :: file
345  !> Gas data.
346  type(gas_data_t), intent(in) :: gas_data
347  !> Times (s).
348  real(kind=dp), allocatable :: times(:)
349  !> Rates (s^{-1}).
350  real(kind=dp), allocatable :: rates(:)
351  !> Gas states.
352  type(gas_state_t), allocatable :: gas_states(:)
353 
354  integer :: n_lines, species, i, n_time, i_time
355  character(len=SPEC_LINE_MAX_VAR_LEN), allocatable :: species_name(:)
356  real(kind=dp), allocatable :: species_data(:,:)
357 
358  !> \page input_format_gas_profile Input File Format: Gas Profile
359  !!
360  !! A gas profile input file must consist of three or more
361  !! lines, consisting of:
362  !! - the first line must begin with \c time and should be followed
363  !! by \f$N\f$ space-separated real scalars, giving the times (in
364  !! s after the start of the simulation) of the gas set
365  !! points --- the times must be in increasing order
366  !! - the second line must begin with \c rate and should be
367  !! followed by \f$N\f$ space-separated real scalars, giving the
368  !! values at the corresponding times
369  !! - the third and subsequent lines specify gas species, one
370  !! species per line, with each line beginning with the species
371  !! name and followed by \f$N\f$ space-separated scalars giving
372  !! the gas state of that species at the corresponding times
373  !!
374  !! The units and meanings of the rate and species lines depends on
375  !! the type of gas profile:
376  !! - emissions gas profiles have dimensionless rates that are used
377  !! to scale the species rates and species giving emission rates
378  !! with units of mol/(m^2 s) --- the emission rate is divided by
379  !! the current mixing layer height to give a per-volume emission
380  !! rate
381  !! - background gas profiles have rates with units s^{-1} that are
382  !! dilution rates and species with units of ppb (parts per
383  !! billion) that are the background mixing ratios
384  !!
385  !! The species names must be those specified by the \ref
386  !! input_format_gas_data. Any species not listed are taken to be
387  !! zero.
388  !!
389  !! Between the specified times the gas profile is interpolated
390  !! step-wise and kept constant at its last value. That is, if the
391  !! times are \f$t_i\f$, the rates are \f$r_i\f$, and the gas
392  !! states are \f$g_i\f$ (all with \f$i = 1,\ldots,n\f$), then
393  !! between times \f$t_i\f$ and \f$t_{i+1}\f$ the gas state is
394  !! constant at \f$r_i g_i\f$. Before time \f$t_1\f$ the gas state
395  !! is \f$r_1 g_1\f$, while after time \f$t_n\f$ it is \f$r_n
396  !! g_n\f$.
397  !!
398  !! Example: an emissions gas profile could be:
399  !! <pre>
400  !! time 0 600 1800 # time (in s) after simulation start
401  !! rate 1 0.5 1 # scaling factor
402  !! H2SO4 0 0 0 # emission rate in mol/(m^2 s)
403  !! SO2 4e-9 5.6e-9 5e-9 # emission rate in mol/(m^2 s)
404  !! </pre>
405  !! Here there are no emissions of \f$\rm H_2SO_4\f$, while \f$\rm
406  !! SO_2\f$ starts out being emitted at \f$4\times
407  !! 10^{-9}\rm\ mol\ m^{-2}\ s^{-1}\f$ at the start of the simulation,
408  !! before falling to a rate of \f$2.8\times
409  !! 10^{-9}\rm\ mol\ m^{-2}\ s^{-1}\f$ at 10&nbsp;min (note the scaling
410  !! of 0.5), and then rising again to \f$5\times
411  !! 10^{-9}\rm\ mol\ m^{-2}\ s^{-1}\f$ after 30&nbsp;min. Between
412  !! 0&nbsp;min and 10&nbsp;min the emissions are the same as at
413  !! 0&nbsp;min, while between 10&nbsp;min and 30&nbsp;min they are
414  !! the same as at 10&nbsp;min. After 30&nbsp;min they are held
415  !! constant at their final value.
416  !!
417  !! See also:
418  !! - \ref spec_file_format --- the input file text format
419  !! - \ref input_format_gas_data --- the gas species list and
420  !! material data
421 
422  ! read the data from the file
423  call spec_file_read_real_named_array(file, 0, species_name, &
424  species_data)
425 
426  ! check the data size
427  n_lines = size(species_data, 1)
428  if (n_lines < 2) then
429  call die_msg(291542946, 'insufficient data lines in file ' &
430  // trim(file%name))
431  end if
432  if (trim(species_name(1)) /= 'time') then
433  call die_msg(525127793, 'row 1 in file ' &
434  // trim(file%name) // ' must start with: time')
435  end if
436  if (trim(species_name(2)) /= 'rate') then
437  call die_msg(506981322, 'row 2 in file ' &
438  // trim(file%name) // ' must start with: rate')
439  end if
440  n_time = size(species_data, 2)
441  if (n_time < 1) then
442  call die_msg(398532628, 'each line in file ' &
443  // trim(file%name) // ' must contain at least one data value')
444  end if
445 
446  ! copy over the data
447  times = species_data(1,:)
448  rates = species_data(2,:)
449  if (allocated(gas_states)) deallocate(gas_states)
450  allocate(gas_states(n_time))
451  do i_time = 1,n_time
452  call gas_state_set_size(gas_states(i_time), gas_data_n_spec(gas_data))
453  end do
454  do i = 3,n_lines
455  species = gas_data_spec_by_name(gas_data, species_name(i))
456  if (species == 0) then
457  call die_msg(806500079, 'unknown species ' &
458  // trim(species_name(i)) // ' in file ' &
459  // trim(file%name))
460  end if
461  do i_time = 1,n_time
462  gas_states(i_time)%mix_rat(species) = species_data(i,i_time)
463  end do
464  end do
465 
466  end subroutine spec_file_read_gas_states_times_rates
467 
468 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
469 
470  !> Average val over all processes.
471  subroutine gas_state_mix(val)
472 
473  !> Value to average.
474  type(gas_state_t), intent(inout) :: val
475 
476 #ifdef PMC_USE_MPI
477  type(gas_state_t) :: val_avg
478 
479  call gas_state_set_size(val_avg, size(val%mix_rat))
480  call pmc_mpi_allreduce_average_real_array(val%mix_rat, val_avg%mix_rat)
481  val%mix_rat = val_avg%mix_rat
482 #endif
483 
484  end subroutine gas_state_mix
485 
486 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
487 
488  !> Average val over all processes, with the result only on the root
489  !> process.
490  subroutine gas_state_reduce_avg(val)
491 
492  !> Value to average.
493  type(gas_state_t), intent(inout) :: val
494 
495 #ifdef PMC_USE_MPI
496  type(gas_state_t) :: val_avg
497 
498  call gas_state_set_size(val_avg, size(val%mix_rat))
499  call pmc_mpi_reduce_avg_real_array(val%mix_rat, val_avg%mix_rat)
500  if (pmc_mpi_rank() == 0) then
501  val%mix_rat = val_avg%mix_rat
502  end if
503 #endif
504 
505  end subroutine gas_state_reduce_avg
506 
507 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
508 
509  !> Determines the number of bytes required to pack the given value.
510  integer function pmc_mpi_pack_size_gas_state(val)
511 
512  !> Value to pack.
513  type(gas_state_t), intent(in) :: val
514 
516  + pmc_mpi_pack_size_real_array(val%mix_rat)
517 
518  end function pmc_mpi_pack_size_gas_state
519 
520 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
521 
522  !> Packs the given value into the buffer, advancing position.
523  subroutine pmc_mpi_pack_gas_state(buffer, position, val)
524 
525  !> Memory buffer.
526  character, intent(inout) :: buffer(:)
527  !> Current buffer position.
528  integer, intent(inout) :: position
529  !> Value to pack.
530  type(gas_state_t), intent(in) :: val
531 
532 #ifdef PMC_USE_MPI
533  integer :: prev_position
534 
535  prev_position = position
536  call pmc_mpi_pack_real_array(buffer, position, val%mix_rat)
537  call assert(655827004, &
538  position - prev_position <= pmc_mpi_pack_size_gas_state(val))
539 #endif
540 
541  end subroutine pmc_mpi_pack_gas_state
542 
543 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
544 
545  !> Unpacks the given value from the buffer, advancing position.
546  subroutine pmc_mpi_unpack_gas_state(buffer, position, val)
547 
548  !> Memory buffer.
549  character, intent(inout) :: buffer(:)
550  !> Current buffer position.
551  integer, intent(inout) :: position
552  !> Value to pack.
553  type(gas_state_t), intent(inout) :: val
554 
555 #ifdef PMC_USE_MPI
556  integer :: prev_position
557 
558  prev_position = position
559  call pmc_mpi_unpack_real_array(buffer, position, val%mix_rat)
560  call assert(520815247, &
561  position - prev_position <= pmc_mpi_pack_size_gas_state(val))
562 #endif
563 
564  end subroutine pmc_mpi_unpack_gas_state
565 
566 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
567 
568  !> Computes the average of val across all processes, storing the
569  !> result in val_avg on the root process.
570  subroutine pmc_mpi_reduce_avg_gas_state(val, val_avg)
571 
572  !> Value to average.
573  type(gas_state_t), intent(in) :: val
574  !> Result.
575  type(gas_state_t), intent(inout) :: val_avg
576 
577  call pmc_mpi_reduce_avg_real_array(val%mix_rat, val_avg%mix_rat)
578 
579  end subroutine pmc_mpi_reduce_avg_gas_state
580 
581 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
582 
583  !> Write full state.
584  subroutine gas_state_output_netcdf(gas_state, ncid, gas_data)
585 
586  !> Gas state to write.
587  type(gas_state_t), intent(in) :: gas_state
588  !> NetCDF file ID, in data mode.
589  integer, intent(in) :: ncid
590  !> Gas data.
591  type(gas_data_t), intent(in) :: gas_data
592 
593  integer :: dimid_gas_species
594 
595  !> \page output_format_gas_state Output File Format: Gas State
596  !!
597  !! The gas state uses the \c gas_species NetCDF dimension as specified
598  !! in the \ref output_format_gas_data section.
599  !!
600  !! The gas state NetCDF variables are:
601  !! - \b gas_mixing_ratio (unit ppb, dim \c gas_species): current mixing
602  !! ratios of each gas species
603  !!
604  !! See also:
605  !! - \ref output_format_gas_data --- the gas species list and material
606  !! data output format
607  !! - \ref input_format_gas_state --- the corresponding input format
608 
609  call gas_data_netcdf_dim_gas_species(gas_data, ncid, &
610  dimid_gas_species)
611 
612  call pmc_nc_write_real_1d(ncid, gas_state%mix_rat, &
613  "gas_mixing_ratio", (/ dimid_gas_species /), unit="ppb", &
614  long_name="mixing ratios of gas species")
615 
616  end subroutine gas_state_output_netcdf
617 
618 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
619 
620  !> Read full state.
621  subroutine gas_state_input_netcdf(gas_state, ncid, gas_data)
622 
623  !> Gas state to read.
624  type(gas_state_t), intent(inout) :: gas_state
625  !> NetCDF file ID, in data mode.
626  integer, intent(in) :: ncid
627  !> Gas data.
628  type(gas_data_t), intent(in) :: gas_data
629 
630  call pmc_nc_read_real_1d(ncid, gas_state%mix_rat, "gas_mixing_ratio")
631 
632  end subroutine gas_state_input_netcdf
633 
634 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
635 
636 end module pmc_gas_state
pmc_mpi::pmc_mpi_allreduce_average_real_array
subroutine pmc_mpi_allreduce_average_real_array(val, val_avg)
Computes the average of val across all processes, storing the result in val_avg on all processes.
Definition: mpi.F90:1788
pmc_gas_data::gas_data_t
Constant gas data.
Definition: gas_data.F90:35
pmc_netcdf::pmc_nc_write_real_1d
subroutine pmc_nc_write_real_1d(ncid, var, name, dimids, dim_name, unit, long_name, standard_name, description)
Write a simple real array to a NetCDF file.
Definition: netcdf.F90:846
pmc_mpi
Wrapper functions for MPI.
Definition: mpi.F90:13
pmc_gas_state::gas_state_mix
subroutine gas_state_mix(val)
Average val over all processes.
Definition: gas_state.F90:472
pmc_gas_state::gas_state_ensure_nonnegative
subroutine gas_state_ensure_nonnegative(gas_state)
Set any negative values to zero.
Definition: gas_state.F90:167
pmc_gas_data::gas_data_netcdf_dim_gas_species
subroutine gas_data_netcdf_dim_gas_species(gas_data, ncid, dimid_gas_species)
Write the gas species dimension to the given NetCDF file if it is not already present and in any case...
Definition: gas_data.F90:327
pmc_gas_state::pmc_mpi_reduce_avg_gas_state
subroutine pmc_mpi_reduce_avg_gas_state(val, val_avg)
Computes the average of val across all processes, storing the result in val_avg on the root process.
Definition: gas_state.F90:571
pmc_gas_state::gas_state_set_size
subroutine gas_state_set_size(gas_state, n_spec)
Sets the sizes of the gas state.
Definition: gas_state.F90:56
pmc_gas_data
The gas_data_t structure and associated subroutines.
Definition: gas_data.F90:9
pmc_netcdf::pmc_nc_read_real_1d
subroutine pmc_nc_read_real_1d(ncid, var, name, must_be_present)
Read a simple real array from a NetCDF file.
Definition: netcdf.F90:255
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_constants::dp
integer, parameter dp
Kind of a double precision real number.
Definition: constants.F90:12
pmc_spec_file
Reading formatted text input.
Definition: spec_file.F90:43
pmc_gas_state::gas_state_add_scaled
subroutine gas_state_add_scaled(gas_state, gas_state_delta, alpha)
Adds the given gas_state_delta scaled by alpha.
Definition: gas_state.F90:124
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_mpi::pmc_mpi_pack_size_real_array
integer function pmc_mpi_pack_size_real_array(val)
Determines the number of bytes required to pack the given value.
Definition: mpi.F90:527
pmc_spec_file::spec_file_t
An input file with extra data for printing messages.
Definition: spec_file.F90:59
pmc_gas_state
The gas_state_t structure and associated subroutines.
Definition: gas_state.F90:9
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_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_env_state::env_state_rel_humid_to_mix_rat
real(kind=dp) function env_state_rel_humid_to_mix_rat(env_state)
Converts relative humidity (1) to water vapor mixing ratio (ppb).
Definition: env_state.F90:209
pmc_env_state::env_state_air_molar_den
real(kind=dp) function env_state_air_molar_den(env_state)
Air molar density (mol m^{-3}).
Definition: env_state.F90:193
pmc_gas_state::gas_state_sub
subroutine gas_state_sub(gas_state, gas_state_delta)
Subtracts the given gas_state_delta.
Definition: gas_state.F90:147
pmc_gas_state::gas_state_scale
subroutine gas_state_scale(gas_state, alpha)
Scale a gas state.
Definition: gas_state.F90:86
pmc_spec_file::spec_file_read_real_named_array
subroutine spec_file_read_real_named_array(file, max_lines, names, vals)
Read an array of named lines with real data. All lines must have the same number of data elements.
Definition: spec_file.F90:650
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_gas_data::gas_data_spec_by_name
integer function gas_data_spec_by_name(gas_data, name)
Returns the number of the species in gas with the given name, or returns 0 if there is no such specie...
Definition: gas_data.F90:126
pmc_util
Common utility subroutines.
Definition: util.F90:9
pmc_gas_data::gas_data_n_spec
elemental integer function gas_data_n_spec(gas_data)
Return the number of gas species.
Definition: gas_data.F90:109
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_gas_state::gas_state_is_allocated
logical function gas_state_is_allocated(gas_state)
Determine whether the gas_state is correctly allocated.
Definition: gas_state.F90:44
pmc_gas_state::gas_state_interp_1d
subroutine gas_state_interp_1d(gas_state_list, time_list, rate_list, time, gas_state, rate)
Determine the current gas_state and rate by interpolating at the current time with the lists of gas_s...
Definition: gas_state.F90:239
pmc_gas_state::gas_state_add
subroutine gas_state_add(gas_state, gas_state_delta)
Adds the given gas_state_delta.
Definition: gas_state.F90:102
pmc_mpi::pmc_mpi_pack_real_array
subroutine pmc_mpi_pack_real_array(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: mpi.F90:927
pmc_mpi::pmc_mpi_reduce_avg_real_array
subroutine pmc_mpi_reduce_avg_real_array(val, val_avg)
Computes the average of val across all processes, storing the result in val_avg on the root process.
Definition: mpi.F90:1709
pmc_gas_state::gas_state_molar_conc_to_ppb
subroutine gas_state_molar_conc_to_ppb(gas_state, env_state)
Convert (mol m^{-3}) to (ppb).
Definition: gas_state.F90:181
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_mpi::pmc_mpi_unpack_real_array
subroutine pmc_mpi_unpack_real_array(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: mpi.F90:1356
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_util::find_1d
integer function find_1d(n, x_vals, x)
Find the position of a real number in an arbitrary 1D array.
Definition: util.F90:593
pmc_gas_state::gas_state_zero
subroutine gas_state_zero(gas_state)
Zeros the state.
Definition: gas_state.F90:72