CAMP 1.0.0
Chemistry Across Multiple Phases
rxn_wet_deposition.F90
Go to the documentation of this file.
1! Copyright (C) 2021 Barcelona Supercomputing Center and University of
2! Illinois at Urbana-Champaign
3! SPDX-License-Identifier: MIT
4
5!> \file
6!> The camp_rxn_wet_deposition module.
7
8!> \page camp_rxn_wet_deposition CAMP: Wet Deposition
9!!
10!! Wet Deposition reactions take the form:
11!!
12!! \f[
13!! \mbox{X} \rightarrow
14!! \f]
15!!
16!! where \f$\ce{X}\f$ is a set of species in an aerosol phase
17!! undergoing wet deposition at a given rate.
18!!
19!! Wet deposition rate constants can be constant or set from an external
20!! module using the
21!! \c camp_rxn_wet_deposition::rxn_update_data_wet_deposition_t object.
22!! External modules should use the
23!! \c camp_rxn_wet_deposition::rxn_wet_deposition_t::get_property_set()
24!! function during initilialization to access any needed reaction parameters
25!! to identify certain wet deposition reactions.
26!! An \c camp_rxn_wet_deposition::update_data_wet_deposition_t object should be
27!! initialized for each wet deposition reaction. These objects can then be used
28!! during solving to update the wet deposition rate from an external module.
29!!
30!! Input data for wet deposition reactions have the following format :
31!! \code{.json}
32!! {
33!! "type" : "WET_DEPOSITION",
34!! "aerosol phase" : "my aero phase",
35!! "scaling factor" : 1.2,
36!! ...
37!! }
38!! \endcode
39!! The key-value pair \b aerosol \b phase is required and its value must be
40!! the name of the aerosol phase undergoing wet deposition. All species within
41!! the aerosol phase in all instances of the aerosol phase will be removed
42!! according the first-order loss rate constant. The \b scaling \b factor is
43!! optional, and can be used to set a constant scaling factor for the rate
44!! constant. When a \b scaling \b factor is not provided, it is assumed to be
45!! 1.0. All other data is optional and will be available to external modules
46!! during initialization. Rate constants are in units of \f$s^{-1}\f$, and
47!! must be set using a \c rxn_wet_deposition_update_data_t object.
48
49!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
50
51!> The rxn_wet_deposition_t type and associated functions.
53
57 use camp_constants, only: const
59 use camp_mpi
62 use camp_util, only: i_kind, dp, string_t, &
65
66 use iso_c_binding
67
68 implicit none
69 private
70
71#define RXN_ID_ this%condensed_data_int(1)
72#define NUM_SPEC_ this%condensed_data_int(2)
73#define SCALING_ this%condensed_data_real(1)
74#define NUM_INT_PROP_ 2
75#define NUM_REAL_PROP_ 1
76#define NUM_ENV_PARAM_ 2
77#define REACT_(s) this%condensed_data_int(NUM_INT_PROP_+s)
78#define DERIV_ID_(s) this%condensed_data_int(NUM_INT_PROP_+NUM_SPEC_+s)
79#define JAC_ID_(s) this%condensed_data_int(NUM_INT_PROP_+2*NUM_SPEC_+s))
80
82
83 !> Generic test reaction data type
84 type, extends(rxn_data_t) :: rxn_wet_deposition_t
85 contains
86 !> Reaction initialization
87 procedure :: initialize
88 !> Get the reaction property set
89 procedure :: get_property_set
90 !> Initialize update data
92 !> Finalize the reaction
95
96 !> Constructor for rxn_wet_deposition_t
98 procedure :: constructor
99 end interface rxn_wet_deposition_t
100
101 !> Wet Deposition rate update object
103 private
104 !> Flag indicating whether the update data as been allocated
105 logical :: is_malloced = .false.
106 !> Unique id for finding reactions during model initialization
107 integer(kind=i_kind) :: rxn_unique_id = 0
108 contains
109 !> Update the rate data
110 procedure :: set_rate => update_data_rate_set
111 !> Determine the pack size of the local update data
113 !> Pack the local update data to a binary
114 procedure :: internal_bin_pack
115 !> Unpack the local update data from a binary
117 !> Finalize the rate update data
120
121 !> Interface to c reaction functions
122 interface
123
124 !> Allocate space for a rate update
126 result(update_data) bind (c)
127 use iso_c_binding
128 !> Allocated update_data object
129 type(c_ptr) :: update_data
131
132 !> Set a new wet_deposition rate
134 rxn_unique_id, base_rate) bind (c)
135 use iso_c_binding
136 !> Update data
137 type(c_ptr), value :: update_data
138 !> Reaction id
139 integer(kind=c_int), value :: rxn_unique_id
140 !> New pre-scaling base wet_deposition rate
141 real(kind=c_double), value :: base_rate
143
144 !> Free an update rate data object
145 pure subroutine rxn_free_update_data(update_data) bind (c)
146 use iso_c_binding
147 !> Update data
148 type(c_ptr), value, intent(in) :: update_data
149 end subroutine rxn_free_update_data
150
151 end interface
152
153contains
154
155!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
156
157 !> Constructor for Wet Deposition reaction
158 function constructor() result(new_obj)
159
160 !> A new reaction instance
161 type(rxn_wet_deposition_t), pointer :: new_obj
162
163 allocate(new_obj)
164 new_obj%rxn_phase = aero_rxn
165
166 end function constructor
167
168!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
169
170 !> Initialize the reaction data, validating component data and loading
171 !! any required information into the condensed data arrays for use during
172 !! solving
173 subroutine initialize(this, chem_spec_data, aero_phase, aero_rep, n_cells)
174
175 !> Reaction data
176 class(rxn_wet_deposition_t), intent(inout) :: this
177 !> Chemical species data
178 type(chem_spec_data_t), intent(in) :: chem_spec_data
179 !> Aerosol phase data
180 type(aero_phase_data_ptr), intent(in) :: aero_phase(:)
181 !> Aerosol representations
182 type(aero_rep_data_ptr), pointer, intent(in) :: aero_rep(:)
183 !> Number of grid cells to solve simultaneously
184 integer(kind=i_kind), intent(in) :: n_cells
185
186 type(property_t), pointer :: spec_props
187 type(string_t), allocatable :: unique_names(:)
188 character(len=:), allocatable :: key_name, phase_name
189 integer(kind=i_kind) :: i_rep, i_spec, i_rep_spec, num_spec
190
191 integer(kind=i_kind) :: temp_int
192 real(kind=dp) :: temp_real
193
194 ! Get the reaction property set
195 call assert_msg(368664748, associated(this%property_set), &
196 "Missing property set needed to initialize reaction")
197
198 ! Get the aerosol phase name
199 key_name = "aerosol phase"
200 call assert_msg(133499444, &
201 this%property_set%get_string(key_name, phase_name), &
202 "Wet Deposition reaction is missing aerosol phase name")
203
204 ! Check for aerosol representations
205 call assert_msg(674938531, associated(aero_rep), &
206 "Missing aerosol representation for wet deposition reaction")
207 call assert_msg(731323851, size(aero_rep).gt.0, &
208 "Missing aerosol representation for wet deposition reaction")
209
210 ! Count the total number of species in the specified phase in each
211 ! aerosol representation
212 num_spec = 0
213 do i_rep = 1, size(aero_rep)
214 unique_names = aero_rep(i_rep)%val%unique_names( phase_name = &
215 phase_name )
216 num_spec = num_spec + size( unique_names )
217 end do
218 call assert_msg(332795980, num_spec.gt.0, &
219 "No species found for wet deposition aerosol phase "// &
220 phase_name)
221
222 ! Allocate space in the condensed data arrays
223 allocate(this%condensed_data_int(num_int_prop_+3*num_spec))
224 allocate(this%condensed_data_real(num_real_prop_))
225 this%condensed_data_int(:) = int(0, kind=i_kind)
226 this%condensed_data_real(:) = real(0.0, kind=dp)
227
228 ! Save space for the environment-dependent parameters
229 this%num_env_params = num_env_param_
230
231 ! Save the number of species
232 num_spec_ = num_spec
233
234 ! Get reaction parameters
235 key_name = "scaling factor"
236 if (.not. this%property_set%get_real(key_name, scaling_)) then
237 scaling_ = real(1.0, kind=dp)
238 end if
239
240 ! Save the indices of each species undergoing wet deposition
241 i_spec = 0
242 do i_rep = 1, size(aero_rep)
243 unique_names = aero_rep(i_rep)%val%unique_names( phase_name = &
244 phase_name )
245 do i_rep_spec = 1, size(unique_names)
246 i_spec = i_spec + 1
247 react_(i_spec) = aero_rep(i_rep)%val%spec_state_id( &
248 unique_names( i_rep_spec )%string )
249 call assert( 702159475, react_(i_spec) .gt. 0 )
250 end do
251 end do
252 call assert(312643342, i_spec .eq. num_spec_)
253
254 ! Initialize the reaction id
255 rxn_id_ = -1
256
257 end subroutine initialize
258
259!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
260
261 !> Get the reaction properties. (For use by external modules.)
262 function get_property_set(this) result(prop_set)
263
264 !> Reaction properties
265 type(property_t), pointer :: prop_set
266 !> Reaction data
267 class(rxn_wet_deposition_t), intent(in) :: this
268
269 prop_set => this%property_set
270
271 end function get_property_set
272
273!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
274
275 !> Finalize the reaction
276 subroutine finalize(this)
277
278 !> Reaction data
279 type(rxn_wet_deposition_t), intent(inout) :: this
280
281 if (associated(this%property_set)) &
282 deallocate(this%property_set)
283 if (allocated(this%condensed_data_real)) &
284 deallocate(this%condensed_data_real)
285 if (allocated(this%condensed_data_int)) &
286 deallocate(this%condensed_data_int)
287
288 end subroutine finalize
289
290!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
291
292 !> Finalize an array of reactions
293 subroutine finalize_array(this)
294
295 !> Array of reaction data
296 type(rxn_wet_deposition_t), intent(inout) :: this(:)
297
298 integer(kind=i_kind) :: i_rxn
299
300 do i_rxn = 1, size(this)
301 call finalize(this(i_rxn))
302 end do
303
304 end subroutine finalize_array
305
306!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
307
308 !> Set packed update data for wet_deposition rate constants
309 subroutine update_data_rate_set(this, base_rate)
310
311 !> Update data
312 class(rxn_update_data_wet_deposition_t), intent(inout) :: this
313 !> Updated pre-scaling wet_deposition rate
314 real(kind=dp), intent(in) :: base_rate
315
316 call rxn_wet_deposition_set_rate_update_data(this%get_data(), &
317 this%rxn_unique_id, base_rate)
318
319 end subroutine update_data_rate_set
320
321!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
322
323 !> Initialize update data
324 subroutine update_data_initialize(this, update_data, rxn_type)
325
326 use camp_rand, only : generate_int_id
327
328 !> The reaction to update
329 class(rxn_wet_deposition_t), intent(inout) :: this
330 !> Update data object
331 class(rxn_update_data_wet_deposition_t), intent(out) :: update_data
332 !> Reaction type id
333 integer(kind=i_kind), intent(in) :: rxn_type
334
335 ! If a reaction id has not yet been generated, do it now
336 if (rxn_id_.eq.-1) then
337 rxn_id_ = generate_int_id()
338 endif
339
340 update_data%rxn_unique_id = rxn_id_
341 update_data%rxn_type = int(rxn_type, kind=c_int)
342 update_data%update_data = rxn_wet_deposition_create_rate_update_data()
343 update_data%is_malloced = .true.
344
345 end subroutine update_data_initialize
346
347!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
348
349 !> Determine the size of a binary required to pack the reaction data
350 integer(kind=i_kind) function internal_pack_size(this, comm) &
351 result(pack_size)
352
353 !> Reaction update data
354 class(rxn_update_data_wet_deposition_t), intent(in) :: this
355 !> MPI communicator
356 integer, intent(in) :: comm
357
358 pack_size = &
359 camp_mpi_pack_size_logical(this%is_malloced, comm) + &
360 camp_mpi_pack_size_integer(this%rxn_unique_id, comm)
361
362 end function internal_pack_size
363
364!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
365
366 !> Pack the given value to the buffer, advancing position
367 subroutine internal_bin_pack(this, buffer, pos, comm)
368
369 !> Reaction update data
370 class(rxn_update_data_wet_deposition_t), intent(in) :: this
371 !> Memory buffer
372 character, intent(inout) :: buffer(:)
373 !> Current buffer position
374 integer, intent(inout) :: pos
375 !> MPI communicator
376 integer, intent(in) :: comm
377
378#ifdef CAMP_USE_MPI
379 integer :: prev_position
380
381 prev_position = pos
382 call camp_mpi_pack_logical(buffer, pos, this%is_malloced, comm)
383 call camp_mpi_pack_integer(buffer, pos, this%rxn_unique_id, comm)
384 call assert(865557010, &
385 pos - prev_position <= this%pack_size(comm))
386#endif
387
388 end subroutine internal_bin_pack
389
390!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
391
392 !> Unpack the given value from the buffer, advancing position
393 subroutine internal_bin_unpack(this, buffer, pos, comm)
394
395 !> Reaction update data
396 class(rxn_update_data_wet_deposition_t), intent(inout) :: this
397 !> Memory buffer
398 character, intent(inout) :: buffer(:)
399 !> Current buffer position
400 integer, intent(inout) :: pos
401 !> MPI communicator
402 integer, intent(in) :: comm
403
404#ifdef CAMP_USE_MPI
405 integer :: prev_position
406
407 prev_position = pos
408 call camp_mpi_unpack_logical(buffer, pos, this%is_malloced, comm)
409 call camp_mpi_unpack_integer(buffer, pos, this%rxn_unique_id, comm)
410 call assert(135713915, &
411 pos - prev_position <= this%pack_size(comm))
413#endif
414
415 end subroutine internal_bin_unpack
416
417!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
418
419 !> Finalize an update data object
420 subroutine update_data_finalize(this)
421
422 !> Update data object to free
423 type(rxn_update_data_wet_deposition_t), intent(inout) :: this
424
425 if (this%is_malloced) call rxn_free_update_data(this%update_data)
426
427 end subroutine update_data_finalize
428
429!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
430
431 !> Finalize an array of reactions
433
434 !> Array of update data objects
435 type(rxn_update_data_wet_deposition_t), intent(inout) :: this(:)
436
437 integer(kind=i_kind) :: i_rxn
438
439 do i_rxn = 1, size(this)
440 call update_data_finalize(this(i_rxn))
441 end do
442
443 end subroutine update_data_finalize_array
444
445!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
446
Initialize the aerosol representation data, validating component data and loading any required inform...
Extending-type binary pack function (Internal use only)
Extending-type binary unpack function (Internal use only)
Extending-type binary pack size (internal use only)
Get a list of unique names for each element on the camp_camp_state::camp_state_t::state_var array for...
Interface for to_string functions.
Definition util.F90:32
The abstract aero_phase_data_t structure and associated subroutines.
subroutine finalize_array(this)
Finalize the aerosol phase data.
class(property_t) function, pointer get_property_set(this)
Get the aerosol phase property set.
type(aero_phase_data_t) function, pointer constructor(phase_name, init_size)
Constructor for aero_phase_data_t.
subroutine finalize(this)
Finalize the aerosol phase data.
integer(kind=i_kind) function pack_size(this, comm)
Determine the size of a binary required to pack the aerosol representation data.
The abstract aero_rep_data_t structure and associated subroutines.
The camp_state_t structure and associated subroutines.
Definition camp_state.F90:9
The chem_spec_data_t structure and associated subroutines.
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
integer, parameter i_kind
Kind of an integer.
Definition constants.F90:21
Wrapper functions for MPI.
Definition mpi.F90:13
subroutine camp_mpi_pack_logical(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
Definition mpi.F90:792
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_unpack_logical(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
Definition mpi.F90:1131
integer function camp_mpi_pack_size_logical(val, comm)
Determines the number of bytes required to pack the given value.
Definition mpi.F90:484
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
The property_t structure and associated subroutines.
Definition property.F90:9
Random number generators.
Definition rand.F90:9
integer(kind=i_kind) function generate_int_id()
Generate an integer id Ids will be sequential, and can only be generated by the primary process.
Definition rand.F90:435
The rxn_data_t structure and associated subroutines.
Definition rxn_data.F90:60
integer(kind=i_kind), parameter, public aero_rxn
Aerosol-phase reaction.
Definition rxn_data.F90:89
The rxn_wet_deposition_t type and associated functions.
subroutine update_data_finalize(this)
Finalize an update data object.
subroutine update_data_initialize(this, update_data, rxn_type)
Initialize update data.
subroutine update_data_rate_set(this, base_rate)
Set packed update data for wet_deposition rate constants.
subroutine update_data_finalize_array(this)
Finalize an array of reactions.
Common utility subroutines.
Definition util.F90:9
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
Definition util.F90:165
subroutine die_msg(code, error_msg)
Error immediately.
Definition util.F90:196
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
Definition util.F90:130
Pointer type for building arrays.
Pointer to aero_rep_data_t extending types.
Abstract reaction data type.
Definition rxn_data.F90:99
String type for building arrays of string of various size.
Definition util.F90:53