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