CAMP 1.0.0
Chemistry Across Multiple Phases
rxn_troe.c
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 * Troe reaction solver functions
6 *
7 */
8/** \file
9 * \brief Troe reaction solver functions
10 */
11#include <math.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include "../rxns.h"
15
16// TODO Lookup environmental indicies during initialization
17#define TEMPERATURE_K_ env_data[0]
18#define PRESSURE_PA_ env_data[1]
19
20#define NUM_REACT_ int_data[0]
21#define NUM_PROD_ int_data[1]
22#define K0_A_ float_data[0]
23#define K0_B_ float_data[1]
24#define K0_C_ float_data[2]
25#define KINF_A_ float_data[3]
26#define KINF_B_ float_data[4]
27#define KINF_C_ float_data[5]
28#define FC_ float_data[6]
29#define N_ float_data[7]
30#define SCALING_ float_data[8]
31#define CONV_ float_data[9]
32#define RATE_CONSTANT_ (rxn_env_data[0])
33#define NUM_INT_PROP_ 2
34#define NUM_FLOAT_PROP_ 10
35#define REACT_(x) (int_data[NUM_INT_PROP_ + x] - 1)
36#define PROD_(x) (int_data[NUM_INT_PROP_ + NUM_REACT_ + x] - 1)
37#define DERIV_ID_(x) int_data[NUM_INT_PROP_ + NUM_REACT_ + NUM_PROD_ + x]
38#define JAC_ID_(x) int_data[NUM_INT_PROP_ + 2 * (NUM_REACT_ + NUM_PROD_) + x]
39#define YIELD_(x) float_data[NUM_FLOAT_PROP_ + x]
40
41/** \brief Flag Jacobian elements used by this reaction
42 *
43 * \param rxn_int_data Pointer to the reaction integer data
44 * \param rxn_float_data Pointer to the reaction floating-point data
45 * \param jac Jacobian
46 */
47void rxn_troe_get_used_jac_elem(int *rxn_int_data, double *rxn_float_data,
48 Jacobian *jac) {
49 int *int_data = rxn_int_data;
50 double *float_data = rxn_float_data;
51
52 for (int i_ind = 0; i_ind < NUM_REACT_; i_ind++) {
53 for (int i_dep = 0; i_dep < NUM_REACT_; i_dep++) {
54 jacobian_register_element(jac, REACT_(i_dep), REACT_(i_ind));
55 }
56 for (int i_dep = 0; i_dep < NUM_PROD_; i_dep++) {
57 jacobian_register_element(jac, PROD_(i_dep), REACT_(i_ind));
58 }
59 }
60
61 return;
62}
63
64/** \brief Update the time derivative and Jacbobian array indices
65 *
66 * \param model_data Pointer to the model data
67 * \param deriv_ids Id of each state variable in the derivative array
68 * \param jac Jacobian
69 * \param rxn_int_data Pointer to the reaction integer data
70 * \param rxn_float_data Pointer to the reaction floating-point data
71 */
72void rxn_troe_update_ids(ModelData *model_data, int *deriv_ids, Jacobian jac,
73 int *rxn_int_data, double *rxn_float_data) {
74 int *int_data = rxn_int_data;
75 double *float_data = rxn_float_data;
76
77 // Update the time derivative ids
78 for (int i = 0; i < NUM_REACT_; i++) DERIV_ID_(i) = deriv_ids[REACT_(i)];
79 for (int i = 0; i < NUM_PROD_; i++)
80 DERIV_ID_(i + NUM_REACT_) = deriv_ids[PROD_(i)];
81
82 // Update the Jacobian ids
83 int i_jac = 0;
84 for (int i_ind = 0; i_ind < NUM_REACT_; i_ind++) {
85 for (int i_dep = 0; i_dep < NUM_REACT_; i_dep++) {
86 JAC_ID_(i_jac++) =
87 jacobian_get_element_id(jac, REACT_(i_dep), REACT_(i_ind));
88 }
89 for (int i_dep = 0; i_dep < NUM_PROD_; i_dep++) {
90 JAC_ID_(i_jac++) =
91 jacobian_get_element_id(jac, PROD_(i_dep), REACT_(i_ind));
92 }
93 }
94 return;
95}
96
97/** \brief Update reaction data for new environmental conditions
98 *
99 * For Troe reaction this only involves recalculating the rate
100 * constant.
101 *
102 * \param model_data Pointer to the model data
103 * \param rxn_int_data Pointer to the reaction integer data
104 * \param rxn_float_data Pointer to the reaction floating-point data
105 * \param rxn_env_data Pointer to the environment-dependent parameters
106 */
107void rxn_troe_update_env_state(ModelData *model_data, int *rxn_int_data,
108 double *rxn_float_data, double *rxn_env_data) {
109 int *int_data = rxn_int_data;
110 double *float_data = rxn_float_data;
111 double *env_data = model_data->grid_cell_env;
112
113 // Calculate the rate constant in (#/cc)
114 // k = (k0[M] / (1 + k0[M]/kinf)) * Fc^(1/(1+(1/N*log(k0[M]/kinf))^2))
115 double conv = CONV_ * PRESSURE_PA_ / TEMPERATURE_K_;
116 double k0 =
117 K0_A_ // [M] is included in K0_A_
118 * (K0_C_ == 0.0 ? 1.0 : exp(K0_C_ / TEMPERATURE_K_)) *
119 (K0_B_ == 0.0 ? 1.0 : pow(TEMPERATURE_K_ / ((double)300.0), K0_B_)) *
120 conv;
121 double kinf =
122 k0 /
123 (KINF_A_ * (KINF_C_ == 0.0 ? 1.0 : exp(KINF_C_ / TEMPERATURE_K_)) *
124 (KINF_B_ == 0.0 ? 1.0 : pow(TEMPERATURE_K_ / ((double)300.0), KINF_B_)));
125 RATE_CONSTANT_ = (k0 / (1.0 + kinf)) *
126 pow(FC_, (1.0 / (1.0 + pow(log10(kinf) / N_, 2)))) *
127 pow(conv, NUM_REACT_ - 1) * SCALING_;
128
129 return;
130}
131
132/** \brief Calculate contributions to the time derivative \f$f(t,y)\f$ from
133 * this reaction.
134 *
135 * \param model_data Pointer to the model data, including the state array
136 * \param time_deriv TimeDerivative object
137 * \param rxn_int_data Pointer to the reaction integer data
138 * \param rxn_float_data Pointer to the reaction floating-point data
139 * \param rxn_env_data Pointer to the environment-dependent parameters
140 * \param time_step Current time step being computed (s)
141 */
142#ifdef CAMP_USE_SUNDIALS
144 TimeDerivative time_deriv, int *rxn_int_data,
145 double *rxn_float_data, double *rxn_env_data,
146 realtype time_step) {
147 int *int_data = rxn_int_data;
148 double *float_data = rxn_float_data;
149 double *state = model_data->grid_cell_state;
150 double *env_data = model_data->grid_cell_env;
151
152 // Calculate the reaction rate
153 long double rate = RATE_CONSTANT_;
154 for (int i_spec = 0; i_spec < NUM_REACT_; i_spec++)
155 rate *= state[REACT_(i_spec)];
156
157 // Add contributions to the time derivative
158 if (rate != ZERO) {
159 int i_dep_var = 0;
160 for (int i_spec = 0; i_spec < NUM_REACT_; i_spec++, i_dep_var++) {
161 if (DERIV_ID_(i_dep_var) < 0) continue;
162 time_derivative_add_value(time_deriv, DERIV_ID_(i_dep_var), -rate);
163 }
164 for (int i_spec = 0; i_spec < NUM_PROD_; i_spec++, i_dep_var++) {
165 if (DERIV_ID_(i_dep_var) < 0) continue;
166 // Negative yields are allowed, but prevented from causing negative
167 // concentrations that lead to solver failures
168 if (-rate * YIELD_(i_spec) * time_step <= state[PROD_(i_spec)]) {
169 time_derivative_add_value(time_deriv, DERIV_ID_(i_dep_var),
170 rate * YIELD_(i_spec));
171 }
172 }
173 }
174
175 return;
176}
177#endif
178
179/** \brief Calculate contributions to the Jacobian from this reaction
180 *
181 * \param model_data Pointer to the model data
182 * \param jac Reaction Jacobian
183 * \param rxn_int_data Pointer to the reaction integer data
184 * \param rxn_float_data Pointer to the reaction floating-point data
185 * \param rxn_env_data Pointer to the environment-dependent parameters
186 * \param time_step Current time step being calculated (s)
187 */
188#ifdef CAMP_USE_SUNDIALS
190 int *rxn_int_data, double *rxn_float_data,
191 double *rxn_env_data, realtype time_step) {
192 int *int_data = rxn_int_data;
193 double *float_data = rxn_float_data;
194 double *state = model_data->grid_cell_state;
195 double *env_data = model_data->grid_cell_env;
196
197 // Add contributions to the Jacobian
198 int i_elem = 0;
199 for (int i_ind = 0; i_ind < NUM_REACT_; i_ind++) {
200 // Calculate d_rate / d_i_ind
201 realtype rate = RATE_CONSTANT_;
202 for (int i_spec = 0; i_spec < NUM_REACT_; i_spec++)
203 if (i_ind != i_spec) rate *= state[REACT_(i_spec)];
204
205 for (int i_dep = 0; i_dep < NUM_REACT_; i_dep++, i_elem++) {
206 if (JAC_ID_(i_elem) < 0) continue;
207 jacobian_add_value(jac, (unsigned int)JAC_ID_(i_elem), JACOBIAN_LOSS,
208 rate);
209 }
210 for (int i_dep = 0; i_dep < NUM_PROD_; i_dep++, i_elem++) {
211 if (JAC_ID_(i_elem) < 0) continue;
212 // Negative yields are allowed, but prevented from causing negative
213 // concentrations that lead to solver failures
214 if (-rate * state[REACT_(i_ind)] * YIELD_(i_dep) * time_step <=
215 state[PROD_(i_dep)]) {
216 jacobian_add_value(jac, (unsigned int)JAC_ID_(i_elem),
217 JACOBIAN_PRODUCTION, YIELD_(i_dep) * rate);
218 }
219 }
220 }
221
222 return;
223}
224#endif
225
226/** \brief Print the Troe reaction parameters
227 *
228 * \param rxn_int_data Pointer to the reaction integer data
229 * \param rxn_float_data Pointer to the reaction floating-point data
230 */
231void rxn_troe_print(int *rxn_int_data, double *rxn_float_data) {
232 int *int_data = rxn_int_data;
233 double *float_data = rxn_float_data;
234
235 printf("\n\nTroe reaction\n");
236
237 return;
238}
unsigned int jacobian_get_element_id(Jacobian jac, unsigned int dep_id, unsigned int ind_id)
Get an element id in the Jacobian data arrays.
Definition Jacobian.c:200
void jacobian_add_value(Jacobian jac, unsigned int elem_id, unsigned int prod_or_loss, long double jac_contribution)
Add a contribution to the Jacobian.
Definition Jacobian.c:234
void jacobian_register_element(Jacobian *jac, unsigned int dep_id, unsigned int ind_id)
Adds an element to the sparse matrix.
Definition Jacobian.c:105
#define JACOBIAN_LOSS
Definition Jacobian.h:19
#define JACOBIAN_PRODUCTION
Definition Jacobian.h:18
#define ZERO
Definition camp_common.h:42
#define NUM_REACT_
Definition rxn_troe.c:20
#define SCALING_
Definition rxn_troe.c:30
#define PRESSURE_PA_
Definition rxn_troe.c:18
void rxn_troe_calc_jac_contrib(ModelData *model_data, Jacobian jac, int *rxn_int_data, double *rxn_float_data, double *rxn_env_data, realtype time_step)
Calculate contributions to the Jacobian from this reaction.
Definition rxn_troe.c:189
#define FC_
Definition rxn_troe.c:28
#define RATE_CONSTANT_
Definition rxn_troe.c:32
#define KINF_A_
Definition rxn_troe.c:25
void rxn_troe_print(int *rxn_int_data, double *rxn_float_data)
Print the Troe reaction parameters.
Definition rxn_troe.c:231
void rxn_troe_get_used_jac_elem(int *rxn_int_data, double *rxn_float_data, Jacobian *jac)
Flag Jacobian elements used by this reaction.
Definition rxn_troe.c:47
#define CONV_
Definition rxn_troe.c:31
#define YIELD_(x)
Definition rxn_troe.c:39
#define PROD_(x)
Definition rxn_troe.c:36
#define TEMPERATURE_K_
Definition rxn_troe.c:17
void rxn_troe_update_ids(ModelData *model_data, int *deriv_ids, Jacobian jac, int *rxn_int_data, double *rxn_float_data)
Update the time derivative and Jacbobian array indices.
Definition rxn_troe.c:72
#define JAC_ID_(x)
Definition rxn_troe.c:38
#define KINF_C_
Definition rxn_troe.c:27
#define NUM_PROD_
Definition rxn_troe.c:21
void rxn_troe_update_env_state(ModelData *model_data, int *rxn_int_data, double *rxn_float_data, double *rxn_env_data)
Update reaction data for new environmental conditions.
Definition rxn_troe.c:107
#define KINF_B_
Definition rxn_troe.c:26
#define K0_C_
Definition rxn_troe.c:24
void rxn_troe_calc_deriv_contrib(ModelData *model_data, TimeDerivative time_deriv, int *rxn_int_data, double *rxn_float_data, double *rxn_env_data, realtype time_step)
Calculate contributions to the time derivative from this reaction.
Definition rxn_troe.c:143
#define REACT_(x)
Definition rxn_troe.c:35
#define K0_B_
Definition rxn_troe.c:23
#define DERIV_ID_(x)
Definition rxn_troe.c:37
#define N_
Definition rxn_troe.c:29
#define K0_A_
Definition rxn_troe.c:22
double * grid_cell_env
double * grid_cell_state
void time_derivative_add_value(TimeDerivative time_deriv, unsigned int spec_id, long double rate_contribution)
Add a contribution to the time derivative.