CAMP 1.0.0
Chemistry Across Multiple Phases
rxn_ternary_chemical_activation.F90
Go to the documentation of this file.
1! Copyright (C) 2021 Barcelona Supercomputing Center,
2! University of Illinois at Urbana-Champaign, and
3! National Center for Atmospheric Research
4! SPDX-License-Identifier: MIT
5
6!> \file
7!> The camp_rxn_ternary_chemical_activation module.
8
9!> \page camp_rxn_ternary_chemical_activation CAMP: Ternary Chemical Activation Reaction
10!!
11!! Ternary Chemical Activation reaction rate constant equations take the form:
12!!
13!! \f[
14!! \frac{k_0}{1+k_0[\mbox{M}]/k_{\inf}}F_C^{(1+1/N[log_{10}(k_0[\mbox{M}]/k_{\inf})]^2)^{-1}}
15!! \f]
16!!
17!! where \f$k_0\f$ is the low-pressure limiting rate constant, \f$k_{\inf}\f$
18!! is the high-pressure limiting rate constant, \f$[\mbox{M}]\f$ is the
19!! density of air, and \f$F_C\f$ and \f$N\f$ are parameters
20!! that determine the shape of the fall-off curve, and are typically 0.6 and
21!! 1.0, respectively \cite JPL15. \f$k_0\f$ and
22!! \f$k_{\inf}\f$ are calculated as \ref camp_rxn_arrhenius "Arrhenius" rate
23!! constants with \f$D=300\f$ and \f$E=0\f$.
24!!
25!! Input data for Ternary Chemical Activation reactions have the following format :
26!! \code{.json}
27!! {
28!! "type" : "TERNARY_CHEMICAL_ACTIVATION",
29!! "k0_A" : 5.6E-12,
30!! "k0_B" : -1.8,
31!! "k0_C" : 180.0,
32!! "kinf_A" : 3.4E-12,
33!! "kinf_B" : -1.6,
34!! "kinf_C" : 104.1,
35!! "Fc" : 0.7,
36!! "N" : 0.9,
37!! "time unit" : "MIN",
38!! "reactants" : {
39!! "spec1" : {},
40!! "spec2" : { "qty" : 2 },
41!! ...
42!! },
43!! "products" : {
44!! "spec3" : {},
45!! "spec4" : { "yield" : 0.65 },
46!! ...
47!! }
48!! }
49!! \endcode
50!! The key-value pairs \b reactants, and \b products are required. Reactants
51!! without a \b qty value are assumed to appear once in the reaction equation.
52!! Products without a specified \b yield are assumed to have a \b yield of
53!! 1.0.
54!!
55!! The two sets of parameters beginning with \b k0_ and \b kinf_ are the
56!! \ref camp_rxn_arrhenius "Arrhenius" parameters for the \f$k_0\f$ and
57!! \f$k_{\inf}\f$ rate constants, respectively. When not present, \b _A
58!! parameters are assumed to be 1.0, \b _B to be 0.0, \b _C to be 0.0, \b Fc
59!! to be 0.6 and \b N to be 1.0.
60!!
61!! The unit for time is assumed to be s, but inclusion of the optional
62!! key-value pair \b time \b unit = \b MIN can be used to indicate a rate
63!! with min as the time unit.
64
65!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
66
67!> The rxn_ternary_chemical_activation_t type and associated functions.
69
73 use camp_constants, only: const
77 use camp_util, only: i_kind, dp, to_string, &
79
80 implicit none
81 private
82
83#define NUM_REACT_ this%condensed_data_int(1)
84#define NUM_PROD_ this%condensed_data_int(2)
85#define K0_A_ this%condensed_data_real(1)
86#define K0_B_ this%condensed_data_real(2)
87#define K0_C_ this%condensed_data_real(3)
88#define KINF_A_ this%condensed_data_real(4)
89#define KINF_B_ this%condensed_data_real(5)
90#define KINF_C_ this%condensed_data_real(6)
91#define FC_ this%condensed_data_real(7)
92#define N_ this%condensed_data_real(8)
93#define SCALING_ this%condensed_data_real(9)
94#define CONV_ this%condensed_data_real(10)
95#define NUM_INT_PROP_ 2
96#define NUM_REAL_PROP_ 10
97#define NUM_ENV_PARAM_ 1
98#define REACT_(x) this%condensed_data_int(NUM_INT_PROP_ + x)
99#define PROD_(x) this%condensed_data_int(NUM_INT_PROP_ + NUM_REACT_ + x)
100#define DERIV_ID_(x) this%condensed_data_int(NUM_INT_PROP_ + NUM_REACT_ + NUM_PROD_ + x)
101#define JAC_ID_(x) this%condensed_data_int(NUM_INT_PROP_ + 2*(NUM_REACT_+NUM_PROD_) + x)
102#define YIELD_(x) this%condensed_data_real(NUM_REAL_PROP_ + x)
103
105
106 !> Generic test reaction data type
108 contains
109 !> Reaction initialization
110 procedure :: initialize
111 !> Finalize the reaction
114
115 !> Constructor for rxn_ternary_chemical_activation_t
117 procedure :: constructor
119
120contains
121
122!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
123
124 !> Constructor for Ternary Chemical Activation reaction
125 function constructor() result(new_obj)
126
127 !> A new reaction instance
128 type(rxn_ternary_chemical_activation_t), pointer :: new_obj
129
130 allocate(new_obj)
131 new_obj%rxn_phase = gas_rxn
132
133 end function constructor
134
135!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
136
137 !> Initialize the reaction data, validating component data and loading
138 !! any required information into the condensed data arrays for use during
139 !! solving
140 subroutine initialize(this, chem_spec_data, aero_phase, aero_rep, n_cells)
141
142 !> Reaction data
143 class(rxn_ternary_chemical_activation_t), intent(inout) :: this
144 !> Chemical species data
145 type(chem_spec_data_t), intent(in) :: chem_spec_data
146 !> Aerosol phase data
147 type(aero_phase_data_ptr), intent(in) :: aero_phase(:)
148 !> Aerosol representations
149 type(aero_rep_data_ptr), pointer, intent(in) :: aero_rep(:)
150 !> Number of grid cells to solve simultaneously
151 integer(kind=i_kind), intent(in) :: n_cells
152
153 type(property_t), pointer :: spec_props, reactants, products
154 character(len=:), allocatable :: key_name, spec_name, string_val
155 integer(kind=i_kind) :: i_spec, i_qty
156
157 integer(kind=i_kind) :: temp_int
158 real(kind=dp) :: temp_real
159
160 ! Get the species involved
161 if (.not. associated(this%property_set)) call die_msg(138420387, &
162 "Missing property set needed to initialize reaction")
163 key_name = "reactants"
164 call assert_msg(250738732, &
165 this%property_set%get_property_t(key_name, reactants), &
166 "Ternary Chemical Activation reaction is missing reactants")
167 key_name = "products"
168 call assert_msg(980581827, &
169 this%property_set%get_property_t(key_name, products), &
170 "Ternary Chemical Activation reaction is missing products")
171
172 ! Count the number of reactants (including those with a qty specified)
173 call reactants%iter_reset()
174 i_spec = 0
175 do while (reactants%get_key(spec_name))
176 ! Get properties included with this reactant in the reaction data
177 call assert(475375422, reactants%get_property_t(val=spec_props))
178 key_name = "qty"
179 if (spec_props%get_int(key_name, temp_int)) i_spec = i_spec+temp_int-1
180 call reactants%iter_next()
181 i_spec = i_spec + 1
182 end do
183
184 ! Allocate space in the condensed data arrays
185 ! Space in this example is allocated for two sets of inidices for the
186 ! reactants and products, one molecular property for each reactant,
187 ! yields for the products and three reaction parameters.
188 allocate(this%condensed_data_int(num_int_prop_ + &
189 (i_spec + 2) * (i_spec + products%size())))
190 allocate(this%condensed_data_real(num_real_prop_ + products%size()))
191 this%condensed_data_int(:) = int(0, kind=i_kind)
192 this%condensed_data_real(:) = real(0.0, kind=dp)
193
194 ! Save space for the environment-dependent parameters
195 this%num_env_params = num_env_param_
196
197 ! Save the size of the reactant and product arrays (for reactions where
198 ! these can vary)
199 num_react_ = i_spec
200 num_prod_ = products%size()
201
202 ! Set the #/cc -> ppm conversion prefactor
203 conv_ = const%avagadro / const%univ_gas_const * 10.0d0**(-12.0d0)
204
205 ! Get reaction parameters (it might be easiest to keep these at the
206 ! beginning of the condensed data array, so they can be accessed using
207 ! compliler flags)
208 key_name = "k0_A"
209 if (.not. this%property_set%get_real(key_name, k0_a_)) then
210 k0_a_ = 1.0
211 end if
212 key_name = "k0_B"
213 if (.not. this%property_set%get_real(key_name, k0_b_)) then
214 k0_b_ = 0.0
215 end if
216 key_name = "k0_C"
217 if (.not. this%property_set%get_real(key_name, k0_c_)) then
218 k0_c_ = 0.0
219 end if
220 key_name = "kinf_A"
221 if (.not. this%property_set%get_real(key_name, kinf_a_)) then
222 kinf_a_ = 1.0
223 end if
224 key_name = "kinf_B"
225 if (.not. this%property_set%get_real(key_name, kinf_b_)) then
226 kinf_b_ = 0.0
227 end if
228 key_name = "kinf_C"
229 if (.not. this%property_set%get_real(key_name, kinf_c_)) then
230 kinf_c_ = 0.0
231 end if
232 key_name = "Fc"
233 if (.not. this%property_set%get_real(key_name, fc_)) then
234 fc_ = 0.6
235 end if
236 key_name = "N"
237 if (.not. this%property_set%get_real(key_name, n_)) then
238 n_ = 1.0
239 end if
240 key_name = "time unit"
241 scaling_ = real(1.0, kind=dp)
242 if (this%property_set%get_string(key_name, string_val)) then
243 if (trim(string_val).eq."MIN") then
244 scaling_ = real(1.0d0/60.0d0, kind=dp)
245 end if
246 endif
247
248 ! Include [M] in k0_A
249 k0_a_ = k0_a_ * real(1.0d6, kind=dp)
250
251 ! Get the indices and chemical properties for the reactants
252 call reactants%iter_reset()
253 i_spec = 1
254 do while (reactants%get_key(spec_name))
255
256 ! Save the index of this species in the state variable array
257 react_(i_spec) = chem_spec_data%gas_state_id(spec_name)
258
259 ! Make sure the species exists
260 call assert_msg(194805707, react_(i_spec).gt.0, &
261 "Missing Ternary Chemical Activation reactant: "//spec_name)
262
263 ! Get properties included with this reactant in the reaction data
264 call assert(524590901, reactants%get_property_t(val=spec_props))
265 key_name = "qty"
266 if (spec_props%get_int(key_name, temp_int)) then
267 do i_qty = 1, temp_int - 1
268 react_(i_spec + i_qty) = react_(i_spec)
269 end do
270 i_spec = i_spec + temp_int - 1
271 end if
272
273 call reactants%iter_next()
274 i_spec = i_spec + 1
275 end do
276
277 ! Get the indices and chemical properties for the products
278 call products%iter_reset()
279 i_spec = 1
280 do while (products%get_key(spec_name))
281
282 ! Save the index of this species in the state variable array
283 prod_(i_spec) = chem_spec_data%gas_state_id(spec_name)
284
285 ! Make sure the species exists
286 call assert_msg(249285493, prod_(i_spec).gt.0, &
287 "Missing Ternary Chemical Activation product: "//spec_name)
288
289 ! Get properties included with this product in the reaction data
290 call assert(296595438, products%get_property_t(val=spec_props))
291 key_name = "yield"
292 if (spec_props%get_real(key_name, temp_real)) then
293 yield_(i_spec) = temp_real
294 else
295 yield_(i_spec) = 1.0
296 end if
297
298 call products%iter_next()
299 i_spec = i_spec + 1
300 end do
301
302 end subroutine initialize
303
304!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
305
306 !> Finalize the reaction
307 subroutine finalize(this)
308
309 !> Reaction data
310 type(rxn_ternary_chemical_activation_t), intent(inout) :: this
311
312 if (associated(this%property_set)) &
313 deallocate(this%property_set)
314 if (allocated(this%condensed_data_real)) &
315 deallocate(this%condensed_data_real)
316 if (allocated(this%condensed_data_int)) &
317 deallocate(this%condensed_data_int)
318
319 end subroutine finalize
320
321!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
322
323 !> Finalize an array of reactions
324 subroutine finalize_array(this)
325
326 !> Array of reaction data
327 type(rxn_ternary_chemical_activation_t), intent(inout) :: this(:)
328
329 integer(kind=i_kind) :: i
330
331 do i = 1, size(this)
332 call finalize(this(i))
333 end do
334
335 end subroutine finalize_array
336
337!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
338
Initialize the aerosol representation data, validating component data and loading any required inform...
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.
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.
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
The property_t structure and associated subroutines.
Definition property.F90:9
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_ternary_chemical_activation_t type and associated functions.
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
#define n_
Pointer type for building arrays.
Pointer to aero_rep_data_t extending types.
Abstract reaction data type.
Definition rxn_data.F90:99