CAMP 1.0.0
Chemistry Across Multiple Phases
env_state.F90
Go to the documentation of this file.
1! Copyright (C) 2005-2021 Barcelona Supercomputing Center and University of
2! Illinois at Urbana-Champaign
3! SPDX-License-Identifier: MIT
4
5!> \file
6!> The camp_env_state module.
7
8!> The env_state_t structure and associated subroutines.
10
12 use camp_util
13 use camp_mpi
14#ifdef CAMP_USE_MPI
15 use mpi
16#endif
17
18 !> Current environment state.
19 !!
20 !! All quantities are instantaneous, describing the state at a
21 !! particular instant of time. Constant data and other data not
22 !! associated with the current environment state is stored in
23 !! scenario_t.
25 !> Temperature (K).
26 real(kind=dp) :: temp
27 !> Relative humidity (1).
28 real(kind=dp) :: rel_humid
29 !> Ambient pressure (Pa).
30 real(kind=dp) :: pressure
31 !> Longitude (degrees).
32 real(kind=dp) :: longitude
33 !> Latitude (degrees).
34 real(kind=dp) :: latitude
35 !> Altitude (m).
36 real(kind=dp) :: altitude
37 !> Start time (s since 00:00 UTC on \c start_day).
38 real(kind=dp) :: start_time
39 !> Start day of year (UTC).
40 integer :: start_day
41 !> Time since \c start_time (s).
42 real(kind=dp) :: elapsed_time
43 !> Solar zenith angle (radians from zenith).
44 real(kind=dp) :: solar_zenith_angle
45 !> Box height (m).
46 real(kind=dp) :: height
47 contains
48 !> Determine the number of bytes required to pack the given value
49 procedure, pass(val) :: pack_size => camp_mpi_pack_size_env_state
50 !> Pack the given value to a buffer, advancing position
51 procedure, pass(val) :: bin_pack => camp_mpi_pack_env_state
52 !> Unpack the given value from a buffer, advancing position
53 procedure, pass(val) :: bin_unpack => camp_mpi_unpack_env_state
54 end type env_state_t
55
56 !> Pointer for env_state_t
58 type(env_state_t), pointer :: val => null()
59 contains
60 !> Set the temperature (K)
61 procedure :: set_temperature_k
62 !> Set the pressure (Pa)
63 procedure :: set_pressure_pa
64 end type env_state_ptr
65
66contains
67
68!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
69
70 !> env_state += env_state_delta
71 subroutine env_state_add(env_state, env_state_delta)
72
73 !> Environment.
74 type(env_state_t), intent(inout) :: env_state
75 !> Increment.
76 type(env_state_t), intent(in) :: env_state_delta
77
78 env_state%temp = env_state%temp + env_state_delta%temp
79 env_state%rel_humid = env_state%rel_humid + env_state_delta%rel_humid
80 env_state%pressure = env_state%pressure + env_state_delta%pressure
81 env_state%longitude = env_state%longitude + env_state_delta%longitude
82 env_state%latitude = env_state%latitude + env_state_delta%latitude
83 env_state%altitude = env_state%altitude + env_state_delta%altitude
84 env_state%start_time = env_state%start_time + env_state_delta%start_time
85 env_state%start_day = env_state%start_day + env_state_delta%start_day
86 env_state%elapsed_time = env_state%elapsed_time &
87 + env_state_delta%elapsed_time
88 env_state%solar_zenith_angle = env_state%solar_zenith_angle &
89 + env_state_delta%solar_zenith_angle
90 env_state%height = env_state%height + env_state_delta%height
91
92 end subroutine env_state_add
93
94!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
95
96 !> env_state *= alpha
97 subroutine env_state_scale(env_state, alpha)
98
99 !> Environment.
100 type(env_state_t), intent(inout) :: env_state
101 !> Scale factor.
102 real(kind=dp), intent(in) :: alpha
103
104 env_state%temp = env_state%temp * alpha
105 env_state%rel_humid = env_state%rel_humid * alpha
106 env_state%pressure = env_state%pressure * alpha
107 env_state%longitude = env_state%longitude * alpha
108 env_state%latitude = env_state%latitude * alpha
109 env_state%altitude = env_state%altitude * alpha
110 env_state%start_time = env_state%start_time * alpha
111 env_state%start_day = nint(real(env_state%start_day, kind=dp) * alpha)
112 env_state%elapsed_time = env_state%elapsed_time * alpha
113 env_state%solar_zenith_angle = env_state%solar_zenith_angle * alpha
114 env_state%height = env_state%height * alpha
115
116 end subroutine env_state_scale
117
118!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
119
120 !> Adds the given water volume to the water vapor and updates all
121 !> environment quantities.
122 subroutine env_state_change_water_volume(env_state, dv)
123
124 !> Environment state to update.
125 type(env_state_t), intent(inout) :: env_state
126 !> Volume concentration of water added (m^3/m^3).
127 real(kind=dp), intent(in) :: dv
128
129 real(kind=dp) pmv ! ambient water vapor pressure (Pa)
130 real(kind=dp) mv ! ambient water vapor density (kg m^{-3})
131 ! pmv and mv are related by the factor molec_weight/(R*T)
132 real(kind=dp) dmv ! change of water density (kg m^{-3})
133
134 dmv = dv * const%water_density
135 pmv = env_state_sat_vapor_pressure(env_state) * env_state%rel_humid
136 mv = const%water_molec_weight / (const%univ_gas_const*env_state%temp) * pmv
137 mv = mv - dmv
138 if (mv < 0d0) then
139 call warn_msg(980320483, "relative humidity tried to go negative")
140 mv = 0d0
141 end if
142 env_state%rel_humid = const%univ_gas_const * env_state%temp &
143 / const%water_molec_weight * mv &
145
146 end subroutine env_state_change_water_volume
147
148!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
149
150 !> Computes the current saturation vapor pressure (Pa).
151 real(kind=dp) function env_state_sat_vapor_pressure(env_state)
152
153 !> Environment state.
154 type(env_state_t), intent(in) :: env_state
155
156 env_state_sat_vapor_pressure = const%water_eq_vap_press &
157 * 10d0**(7.45d0 * (env_state%temp - const%water_freeze_temp) &
158 / (env_state%temp - 38d0))
159
161
162!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
163
164 !> Air density (kg m^{-3}).
165 real(kind=dp) function env_state_air_den(env_state)
166
167 !> Environment state.
168 type(env_state_t), intent(in) :: env_state
169
170 env_state_air_den = const%air_molec_weight &
171 * env_state_air_molar_den(env_state)
172
173 end function env_state_air_den
174
175!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
176
177 !> Air molar density (mol m^{-3}).
178 real(kind=dp) function env_state_air_molar_den(env_state)
179
180 !> Environment state.
181 type(env_state_t), intent(in) :: env_state
182
183 env_state_air_molar_den = env_state%pressure &
184 / (const%univ_gas_const * env_state%temp)
185
186 end function env_state_air_molar_den
187
188!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
189
190 !> Condensation \f$A\f$ parameter.
191 real(kind=dp) function env_state_a(env_state)
192
193 !> Environment state.
194 type(env_state_t), intent(in) :: env_state
195
196 env_state_a = 4d0 * const%water_surf_eng * const%water_molec_weight &
197 / (const%univ_gas_const * env_state%temp * const%water_density)
198
199 end function env_state_a
200
201!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
202
203 !> Convert (ppb) to (molecules m^{-3}).
204 real(kind=dp) function env_state_ppb_to_conc(env_state, ppb)
205
206 !> Environment state.
207 type(env_state_t), intent(in) :: env_state
208 !> Mixing ratio (ppb).
209 real(kind=dp), intent(in) :: ppb
210
211 env_state_ppb_to_conc = ppb / 1d9 * env_state_air_molar_den(env_state) &
212 * const%avagadro
213
214 end function env_state_ppb_to_conc
215
216!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
217
218 !> Convert (molecules m^{-3}) to (ppb).
219 real(kind=dp) function env_state_conc_to_ppb(env_state, conc)
220
221 !> Environment state.
222 type(env_state_t), intent(in) :: env_state
223 !> Concentration (molecules m^{-3}).
224 real(kind=dp), intent(in) :: conc
225
226 env_state_conc_to_ppb = conc * 1d9 / env_state_air_molar_den(env_state) &
227 / const%avagadro
228
229 end function env_state_conc_to_ppb
230
231!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
232
233 !> Average val over all processes.
234 subroutine env_state_mix(val)
235
236 !> Value to average.
237 type(env_state_t), intent(inout) :: val
238
239#ifdef CAMP_USE_MPI
240 type(env_state_t) :: val_avg
241
242 call camp_mpi_allreduce_average_real(val%temp, val_avg%temp)
243 call camp_mpi_allreduce_average_real(val%rel_humid, val_avg%rel_humid)
244 call camp_mpi_allreduce_average_real(val%pressure, val_avg%pressure)
245 val%temp = val_avg%temp
246 val%rel_humid = val_avg%rel_humid
247 val%pressure = val_avg%pressure
248#endif
249
250 end subroutine env_state_mix
251
252!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
253
254 !> Average val over all processes, with the result only on the root
255 !> process.
256 subroutine env_state_reduce_avg(val)
257
258 !> Value to average.
259 type(env_state_t), intent(inout) :: val
260
261#ifdef CAMP_USE_MPI
262 type(env_state_t) :: val_avg
263
264 call camp_mpi_reduce_avg_real(val%temp, val_avg%temp)
265 call camp_mpi_reduce_avg_real(val%rel_humid, val_avg%rel_humid)
266 call camp_mpi_reduce_avg_real(val%pressure, val_avg%pressure)
267 if (camp_mpi_rank() == 0) then
268 val%temp = val_avg%temp
269 val%rel_humid = val_avg%rel_humid
270 val%pressure = val_avg%pressure
271 end if
272#endif
273
274 end subroutine env_state_reduce_avg
275
276!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
277
278 !> Determines the number of bytes required to pack the given value.
279 integer function camp_mpi_pack_size_env_state(val)
280
281 !> Value to pack.
282 class(env_state_t), intent(in) :: val
283
285 camp_mpi_pack_size_real(val%temp) &
286 + camp_mpi_pack_size_real(val%rel_humid) &
287 + camp_mpi_pack_size_real(val%pressure) &
288 + camp_mpi_pack_size_real(val%longitude) &
289 + camp_mpi_pack_size_real(val%latitude) &
290 + camp_mpi_pack_size_real(val%altitude) &
291 + camp_mpi_pack_size_real(val%start_time) &
292 + camp_mpi_pack_size_integer(val%start_day) &
293 + camp_mpi_pack_size_real(val%elapsed_time) &
294 + camp_mpi_pack_size_real(val%solar_zenith_angle) &
295 + camp_mpi_pack_size_real(val%height)
296
298
299!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
300
301 !> Packs the given value into the buffer, advancing position.
302 subroutine camp_mpi_pack_env_state(buffer, position, val)
303
304 !> Memory buffer.
305 character, intent(inout) :: buffer(:)
306 !> Current buffer position.
307 integer, intent(inout) :: position
308 !> Value to pack.
309 class(env_state_t), intent(in) :: val
310
311#ifdef CAMP_USE_MPI
312 integer :: prev_position
313
314 prev_position = position
315 call camp_mpi_pack_real(buffer, position, val%temp)
316 call camp_mpi_pack_real(buffer, position, val%rel_humid)
317 call camp_mpi_pack_real(buffer, position, val%pressure)
318 call camp_mpi_pack_real(buffer, position, val%longitude)
319 call camp_mpi_pack_real(buffer, position, val%latitude)
320 call camp_mpi_pack_real(buffer, position, val%altitude)
321 call camp_mpi_pack_real(buffer, position, val%start_time)
322 call camp_mpi_pack_integer(buffer, position, val%start_day)
323 call camp_mpi_pack_real(buffer, position, val%elapsed_time)
324 call camp_mpi_pack_real(buffer, position, val%solar_zenith_angle)
325 call camp_mpi_pack_real(buffer, position, val%height)
326 call assert(464101191, &
327 position - prev_position <= camp_mpi_pack_size_env_state(val))
328#endif
329
330 end subroutine camp_mpi_pack_env_state
331
332!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
333
334 !> Unpacks the given value from the buffer, advancing position.
335 subroutine camp_mpi_unpack_env_state(buffer, position, val)
336
337 !> Memory buffer.
338 character, intent(inout) :: buffer(:)
339 !> Current buffer position.
340 integer, intent(inout) :: position
341 !> Value to pack.
342 class(env_state_t), intent(inout) :: val
343
344#ifdef CAMP_USE_MPI
345 integer :: prev_position
346
347 prev_position = position
348 call camp_mpi_unpack_real(buffer, position, val%temp)
349 call camp_mpi_unpack_real(buffer, position, val%rel_humid)
350 call camp_mpi_unpack_real(buffer, position, val%pressure)
351 call camp_mpi_unpack_real(buffer, position, val%longitude)
352 call camp_mpi_unpack_real(buffer, position, val%latitude)
353 call camp_mpi_unpack_real(buffer, position, val%altitude)
354 call camp_mpi_unpack_real(buffer, position, val%start_time)
355 call camp_mpi_unpack_integer(buffer, position, val%start_day)
356 call camp_mpi_unpack_real(buffer, position, val%elapsed_time)
357 call camp_mpi_unpack_real(buffer, position, val%solar_zenith_angle)
358 call camp_mpi_unpack_real(buffer, position, val%height)
359 call assert(205696745, &
360 position - prev_position <= camp_mpi_pack_size_env_state(val))
361#endif
362
363 end subroutine camp_mpi_unpack_env_state
364
365!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
366
367 !> Computes the average of val across all processes, storing the
368 !> result in val_avg on the root process.
369 subroutine camp_mpi_reduce_avg_env_state(val, val_avg)
370
371 !> Value to average.
372 type(env_state_t), intent(in) :: val
373 !> Result.
374 type(env_state_t), intent(inout) :: val_avg
375
376 val_avg = val
377 call camp_mpi_reduce_avg_real(val%temp, val_avg%temp)
378 call camp_mpi_reduce_avg_real(val%rel_humid, val_avg%rel_humid)
379 call camp_mpi_reduce_avg_real(val%pressure, val_avg%pressure)
380
381 end subroutine camp_mpi_reduce_avg_env_state
382
383!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
384
385 !> Set the temperature (K)
386 subroutine set_temperature_k( this, temperature )
387
388 !> Environmental state pointer
389 class(env_state_ptr), intent(inout) :: this
390 !> New temperature (K)
391 real(kind=dp), intent(in) :: temperature
392
393 this%val%temp = temperature
394
395 end subroutine set_temperature_k
396
397!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
398
399 !> Set the pressure (Pa)
400 subroutine set_pressure_pa( this, pressure )
401
402 !> Environmental state pointer
403 class(env_state_ptr), intent(inout) :: this
404 !> New pressure (Pa)
405 real(kind=dp), intent(in) :: pressure
406
407 this%val%pressure = pressure
408
409 end subroutine set_pressure_pa
410
411!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
412
413end module camp_env_state
Physical constants.
Definition constants.F90:9
integer, parameter dp
Kind of a double precision real number.
Definition constants.F90:16
type(const_t), save const
Fixed variable for accessing the constant's values.
Definition constants.F90:77
The env_state_t structure and associated subroutines.
Definition env_state.F90:9
subroutine camp_mpi_pack_env_state(buffer, position, val)
Packs the given value into the buffer, advancing position.
real(kind=dp) function env_state_air_molar_den(env_state)
Air molar density (mol m^{-3}).
real(kind=dp) function env_state_ppb_to_conc(env_state, ppb)
Convert (ppb) to (molecules m^{-3}).
real(kind=dp) function env_state_a(env_state)
Condensation parameter.
real(kind=dp) function env_state_sat_vapor_pressure(env_state)
Computes the current saturation vapor pressure (Pa).
integer function camp_mpi_pack_size_env_state(val)
Determines the number of bytes required to pack the given value.
real(kind=dp) function env_state_conc_to_ppb(env_state, conc)
Convert (molecules m^{-3}) to (ppb).
subroutine camp_mpi_unpack_env_state(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
subroutine env_state_scale(env_state, alpha)
env_state *= alpha
Definition env_state.F90:98
subroutine set_pressure_pa(this, pressure)
Set the pressure (Pa)
subroutine set_temperature_k(this, temperature)
Set the temperature (K)
subroutine env_state_reduce_avg(val)
Average val over all processes, with the result only on the root process.
subroutine env_state_add(env_state, env_state_delta)
env_state += env_state_delta
Definition env_state.F90:72
subroutine env_state_mix(val)
Average val over all processes.
subroutine env_state_change_water_volume(env_state, dv)
Adds the given water volume to the water vapor and updates all environment quantities.
subroutine camp_mpi_reduce_avg_env_state(val, val_avg)
Computes the average of val across all processes, storing the result in val_avg on the root process.
real(kind=dp) function env_state_air_den(env_state)
Air density (kg m^{-3}).
Wrapper functions for MPI.
Definition mpi.F90:13
integer function camp_mpi_rank(comm)
Returns the rank of the current process.
Definition mpi.F90:128
subroutine camp_mpi_pack_real(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
Definition mpi.F90:724
subroutine camp_mpi_unpack_integer(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
Definition mpi.F90:1023
subroutine camp_mpi_reduce_avg_real(val, val_avg)
Computes the average of val across all processes, storing the result in val_avg on the root process.
Definition mpi.F90:1366
subroutine camp_mpi_pack_integer(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
Definition mpi.F90:691
integer function camp_mpi_pack_size_integer(val, comm)
Determines the number of bytes required to pack the given value.
Definition mpi.F90:398
subroutine camp_mpi_allreduce_average_real(val, val_avg)
Computes the average of val across all processes, storing the result in val_avg on all processes.
Definition mpi.F90:1571
subroutine camp_mpi_unpack_real(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
Definition mpi.F90:1058
integer function camp_mpi_pack_size_real(val, comm)
Determines the number of bytes required to pack the given value.
Definition mpi.F90:426
Common utility subroutines.
Definition util.F90:9
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
Definition util.F90:165
subroutine warn_msg(code, warning_msg, already_warned)
Prints a warning message.
Definition util.F90:90
Pointer for env_state_t.
Definition env_state.F90:57
Current environment state.
Definition env_state.F90:24