CAMP 1.0.0
Chemistry Across Multiple Phases
rxn_first_order_loss.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_first_order_loss module.
7!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
8!> \page camp_rxn_first_order_loss CAMP: First-Order Loss
9!!
10!! First-Order Loss reactions take the form:
11!!
12!! \f[
13!! \mbox{X} \rightarrow
14!! \f]
15!!
16!! where \f$\ce{X}\f$ is the species being lost.
17!!
18!! First-Order loss rate constants can be constant or set from an external
19!! module using the
20!! \c camp_rxn_first_order_loss::rxn_update_data_first_order_loss_t object.
21!! External modules can use the
22!! \c camp_rxn_first_order_loss::rxn_first_order_loss_t::get_property_set()
23!! function during initilialization to access any needed reaction parameters
24!! to identify certain first-order loss reactions.
25!! An \c camp_rxn_first_order_loss::update_data_first_order_loss_t object
26!! should be initialized for each reaction. These objects can then
27!! be used during solving to update the first order loss rate from an
28!! external module.
29!!
30!! Input data for first-order loss reactions have the following format :
31!! \code{.json}
32!! {
33!! "type" : "FIRST_ORDER_LOSS",
34!! "species" : "species_name",
35!! "scaling factor" : 1.2,
36!! ...
37!! }
38!! \endcode
39!! The key-value pairs \b species is required and its value must be the name
40!! of the species being removed by the reaction. The \b scaling \b factor is
41!! optional, and
42!! can be used to set a constant scaling factor for the rate constant. When a
43!! \b scaling \b factor is not provided, it is assumed to be 1.0. All other
44!! data is optional and will be available to external modules during
45!! initialization. Rate constants are in units of \f$s^{-1}\f$, and must be
46!! set using a \c rxn_first_order_loss_update_data_t object.
47!!
48!!
49
50!> The rxn_first_order_loss_t type and associated functions.
52
56 use camp_constants, only: const
58 use camp_mpi
61 use camp_util, only: i_kind, dp, to_string, &
63
64 use iso_c_binding
65
66 implicit none
67 private
68
69#define RXN_ID_ this%condensed_data_int(1)
70#define REACT_ this%condensed_data_int(2)
71#define DERIV_ID_ this%condensed_data_int(3)
72#define JAC_ID_ this%condensed_data_int(4)
73#define SCALING_ this%condensed_data_real(1)
74#define NUM_INT_PROP_ 4
75#define NUM_REAL_PROP_ 1
76#define NUM_ENV_PARAM_ 2
77
79
80 !> Generic test reaction data type
81 type, extends(rxn_data_t) :: rxn_first_order_loss_t
82 contains
83 !> Reaction initialization
84 procedure :: initialize
85 !> Get the reaction property set
86 procedure :: get_property_set
87 !> Initialize update data
89 !> Finalize the reaction
92
93 !> Constructor for rxn_first_order_loss_t
95 procedure :: constructor
96 end interface rxn_first_order_loss_t
97
98 !> First-Order Loss rate update object
100 private
101 !> Flag indicating whether the update data as been allocated
102 logical :: is_malloced = .false.
103 !> Unique id for finding reactions during model initialization
104 integer(kind=i_kind) :: rxn_unique_id = 0
105 contains
106 !> Update the rate data
107 procedure :: set_rate => update_data_rate_set
108 !> Determine the pack size of the local update data
110 !> Pack the local update data to a binary
111 procedure :: internal_bin_pack
112 !> Unpack the local update data from a binary
114 !> Finalize the rate update data
117
118 !> Interface to c reaction functions
119 interface
120
121 !> Allocate space for a rate update
123 result(update_data) bind (c)
124 use iso_c_binding
125 !> Allocated update_data object
126 type(c_ptr) :: update_data
128
129 !> Set a new first_order_loss rate
131 rxn_unique_id, base_rate) bind (c)
132 use iso_c_binding
133 !> Update data
134 type(c_ptr), value :: update_data
135 !> Reaction id
136 integer(kind=c_int), value :: rxn_unique_id
137 !> New pre-scaling base first_order_loss rate
138 real(kind=c_double), value :: base_rate
140
141 !> Free an update rate data object
142 pure subroutine rxn_free_update_data(update_data) bind (c)
143 use iso_c_binding
144 !> Update data
145 type(c_ptr), value, intent(in) :: update_data
146 end subroutine rxn_free_update_data
147
148 end interface
149
150contains
151
152!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
153
154 !> Constructor for First-Order Loss reaction
155 function constructor() result(new_obj)
156
157 !> A new reaction instance
158 type(rxn_first_order_loss_t), pointer :: new_obj
159
160 allocate(new_obj)
161 new_obj%rxn_phase = gas_rxn
162
163 end function constructor
164
165!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
166
167 !> Initialize the reaction data, validating component data and loading
168 !! any required information into the condensed data arrays for use during
169 !! solving
170 subroutine initialize(this, chem_spec_data, aero_phase, aero_rep, n_cells)
171
172 !> Reaction data
173 class(rxn_first_order_loss_t), intent(inout) :: this
174 !> Chemical species data
175 type(chem_spec_data_t), intent(in) :: chem_spec_data
176 !> Aerosol phase data
177 type(aero_phase_data_ptr), intent(in) :: aero_phase(:)
178 !> Aerosol representations
179 type(aero_rep_data_ptr), pointer, intent(in) :: aero_rep(:)
180 !> Number of grid cells to solve simultaneously
181 integer(kind=i_kind), intent(in) :: n_cells
182
183 type(property_t), pointer :: spec_props
184 character(len=:), allocatable :: key_name, spec_name
185 integer(kind=i_kind) :: i_spec, i_qty
186
187 integer(kind=i_kind) :: temp_int
188 real(kind=dp) :: temp_real
189
190 ! Get the species involved
191 call assert_msg(128411383, associated(this%property_set), &
192 "Missing property set needed to initialize reaction")
193 key_name = "species"
194 call assert_msg(164644065, &
195 this%property_set%get_string(key_name, spec_name), &
196 "First-Order Loss reaction is missing species name")
197
198 ! Allocate space in the condensed data arrays
199 allocate(this%condensed_data_int(num_int_prop_))
200 allocate(this%condensed_data_real(num_real_prop_))
201 this%condensed_data_int(:) = int(0, kind=i_kind)
202 this%condensed_data_real(:) = real(0.0, kind=dp)
203
204 ! Save space for the environment-dependent parameters
205 this%num_env_params = num_env_param_
206
207 ! Get reaction parameters
208 key_name = "scaling factor"
209 if (.not. this%property_set%get_real(key_name, scaling_)) then
210 scaling_ = real(1.0, kind=dp)
211 end if
212
213 ! Save the index of this species in the state variable array
214 react_ = chem_spec_data%gas_state_id(spec_name)
215
216 ! Make sure the species exists
217 call assert_msg(331442196, react_.gt.0, &
218 "Missing first-order loss species: "//spec_name)
219
220 ! Initialize the reaction id
221 rxn_id_ = -1
222
223 end subroutine initialize
224
225!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
226
227 !> Get the reaction properties. (For use by external modules.)
228 function get_property_set(this) result(prop_set)
229
230 !> Reaction properties
231 type(property_t), pointer :: prop_set
232 !> Reaction data
233 class(rxn_first_order_loss_t), intent(in) :: this
234
235 prop_set => this%property_set
236
237 end function get_property_set
238
239!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
240
241 !> Finalize the reaction
242 subroutine finalize(this)
243
244 !> Reaction data
245 type(rxn_first_order_loss_t), intent(inout) :: this
246
247 if (associated(this%property_set)) &
248 deallocate(this%property_set)
249 if (allocated(this%condensed_data_real)) &
250 deallocate(this%condensed_data_real)
251 if (allocated(this%condensed_data_int)) &
252 deallocate(this%condensed_data_int)
253
254 end subroutine finalize
255
256!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
257
258 !> Finalize an array of reactions
259 subroutine finalize_array(this)
260
261 !> Array of reaction data
262 type(rxn_first_order_loss_t), intent(inout) :: this(:)
263
264 integer(kind=i_kind) :: i
265
266 do i = 1, size(this)
267 call finalize(this(i))
268 end do
269
270 end subroutine finalize_array
271
272!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
273
274 !> Set packed update data for first_order_loss rate constants
275 subroutine update_data_rate_set(this, base_rate)
276
277 !> Update data
278 class(rxn_update_data_first_order_loss_t), intent(inout) :: this
279 !> Updated pre-scaling first_order_loss rate
280 real(kind=dp), intent(in) :: base_rate
281
282 call rxn_first_order_loss_set_rate_update_data(this%get_data(), &
283 this%rxn_unique_id, base_rate)
284
285 end subroutine update_data_rate_set
286
287!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
288
289 !> Initialize update data
290 subroutine update_data_initialize(this, update_data, rxn_type)
291
292 use camp_rand, only : generate_int_id
293
294 !> The reaction to update
295 class(rxn_first_order_loss_t), intent(inout) :: this
296 !> Update data object
297 class(rxn_update_data_first_order_loss_t), intent(out) :: update_data
298 !> Reaction type id
299 integer(kind=i_kind), intent(in) :: rxn_type
300
301 ! If a reaction id has not yet been generated, do it now
302 if (rxn_id_.eq.-1) then
303 rxn_id_ = generate_int_id()
304 endif
305
306 update_data%rxn_unique_id = rxn_id_
307 update_data%rxn_type = int(rxn_type, kind=c_int)
308 update_data%update_data = rxn_first_order_loss_create_rate_update_data()
309 update_data%is_malloced = .true.
310
311 end subroutine update_data_initialize
312
313!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
314
315 !> Determine the size of a binary required to pack the reaction data
316 integer(kind=i_kind) function internal_pack_size(this, comm) &
317 result(pack_size)
318
319 !> Reaction update data
320 class(rxn_update_data_first_order_loss_t), intent(in) :: this
321 !> MPI communicator
322 integer, intent(in) :: comm
323
324 pack_size = &
325 camp_mpi_pack_size_logical(this%is_malloced, comm) + &
326 camp_mpi_pack_size_integer(this%rxn_unique_id, comm)
327
328 end function internal_pack_size
329
330!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
331
332 !> Pack the given value to the buffer, advancing position
333 subroutine internal_bin_pack(this, buffer, pos, comm)
334
335 !> Reaction update data
336 class(rxn_update_data_first_order_loss_t), intent(in) :: this
337 !> Memory buffer
338 character, intent(inout) :: buffer(:)
339 !> Current buffer position
340 integer, intent(inout) :: pos
341 !> MPI communicator
342 integer, intent(in) :: comm
343
344#ifdef CAMP_USE_MPI
345 integer :: prev_position
346
347 prev_position = pos
348 call camp_mpi_pack_logical(buffer, pos, this%is_malloced, comm)
349 call camp_mpi_pack_integer(buffer, pos, this%rxn_unique_id, comm)
350 call assert(373785697, &
351 pos - prev_position <= this%pack_size(comm))
352#endif
353
354 end subroutine internal_bin_pack
355
356!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
357
358 !> Unpack the given value from the buffer, advancing position
359 subroutine internal_bin_unpack(this, buffer, pos, comm)
360
361 !> Reaction update data
362 class(rxn_update_data_first_order_loss_t), intent(inout) :: this
363 !> Memory buffer
364 character, intent(inout) :: buffer(:)
365 !> Current buffer position
366 integer, intent(inout) :: pos
367 !> MPI communicator
368 integer, intent(in) :: comm
369
370#ifdef CAMP_USE_MPI
371 integer :: prev_position
372
373 prev_position = pos
374 call camp_mpi_unpack_logical(buffer, pos, this%is_malloced, comm)
375 call camp_mpi_unpack_integer(buffer, pos, this%rxn_unique_id, comm)
376 call assert(368521390, &
377 pos - prev_position <= this%pack_size(comm))
379#endif
380
381 end subroutine internal_bin_unpack
382
383!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
384
385 !> Finalize an update data object
386 subroutine update_data_finalize(this)
387
388 !> Update data object to free
389 type(rxn_update_data_first_order_loss_t), intent(inout) :: this
390
391 if (this%is_malloced) call rxn_free_update_data(this%update_data)
392
393 end subroutine update_data_finalize
394
395!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
396
397 !> Finalize an array of update data objects
399
400 !> Array of update data objects to free
401 type(rxn_update_data_first_order_loss_t), intent(inout) :: this(:)
402
403 integer(kind=i_kind) :: i
404
405 do i = 1, size(this)
406 call update_data_finalize(this(i))
407 end do
408
409 end subroutine update_data_finalize_array
410
411!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
412
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 the non-unique name of a chemical species by its unique name.
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 gas_rxn
Gas-phase reaction.
Definition rxn_data.F90:85
The rxn_first_order_loss_t type and associated functions.
subroutine update_data_finalize_array(this)
Finalize an array of update data objects.
subroutine update_data_initialize(this, update_data, rxn_type)
Initialize update data.
subroutine update_data_finalize(this)
Finalize an update data object.
subroutine update_data_rate_set(this, base_rate)
Set packed update data for first_order_loss rate constants.
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