CAMP 1.0.0
Chemistry Across Multiple Phases
rxn_condensed_phase_diffusion.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 * Condensed phase diffusion reaction solver functions
6 *
7 */
8/** \file
9 * \brief Condensed phase diffusion reaction solver functions
10 */
11#include <math.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <camp/aero_rep_solver.h>
15#include <camp/aero_phase_solver.h>
16#include <camp/rxns.h>
17#include <camp/sub_model_solver.h>
18#include <camp/util.h>
19
20// TODO Lookup environmental indices during initialization
21//#define TEMPERATURE_K_ env_data[0]
22//#define PRESSURE_PA_ env_data[1]
23
24#define NUM_ADJACENT_PAIRS_ int_data[0]
25
26#define NUM_INT_PROP_ 1
27#define NUM_FLOAT_PROP_ 0
28#define NUM_ENV_PARAM_ 0
29
30#define DIFF_COEFF_INNER_(x) (float_data[(NUM_FLOAT_PROP_) + (x)])
31#define DIFF_COEFF_OUTER_(x) (float_data[(NUM_FLOAT_PROP_) + (NUM_ADJACENT_PAIRS_) + (x)])
32#define PHASE_ID_INNER_(x) (int_data[(NUM_INT_PROP_) + (x)]-1)
33#define PHASE_ID_OUTER_(x) (int_data[(NUM_INT_PROP_) + (NUM_ADJACENT_PAIRS_) + (x)]-1)
34#define AERO_SPEC_INNER_(x) (int_data[(NUM_INT_PROP_) + (2*NUM_ADJACENT_PAIRS_) + (x)]-1)
35#define AERO_SPEC_OUTER_(x) (int_data[(NUM_INT_PROP_) + (3*NUM_ADJACENT_PAIRS_) + (x)]-1)
36#define AERO_REP_ID_(x) (int_data[(NUM_INT_PROP_) + (4*NUM_ADJACENT_PAIRS_) + (x)]-1)
37
38#define DERIV_ID_INNER_(x) (int_data[(NUM_INT_PROP_) + (5*NUM_ADJACENT_PAIRS_) + (x)])
39#define DERIV_ID_OUTER_(x) (int_data[(NUM_INT_PROP_) + (6*NUM_ADJACENT_PAIRS_) + (x)])
40//#define JAC_ID_(x) (int_data[4*BLOCK_SIZE_ + x]-1)
41//#define PHASE_INT_LOC_(x) (int_data[5*BLOCK_SIZE_ + x]-1)
42//#define PHASE_FLOAT_LOC_(x) (int_data[9*BLOCK_SIZE_ + x]-1)
43//#define NUM_AERO_PHASE_JAC_ELEM_INNER_(x) (int_data[10*BLOCK_SIZE + x]-1)
44//#define NUM_AERO_PHASE_JAC_ELEM_OUTER_(x) (int_data[11*BLOCK_SIZE + x]-1)
45//#define PHASE_JAC_ID_(x) (int_data[12*BLOCK_SIZE + x]-1)
46//#define NUM_CONC_JAC_ELEM_(x) (int_data[13*BLOCK_SIZE + x]-1)
47//#define MASS_JAC_ELEM_(x) (int_data[14*BLOCK_SIZE + x]-1)
48
49/** \brief Flag Jacobian elements used by this reaction
50 *
51 * \param model_data Pointer to the model data
52 * \param rxn_int_data Pointer to the reaction integer data
53 * \param rxn_float_data Pointer to the reaction floating-point data
54 * \param jac Jacobian
55 */
57 int *rxn_int_data,
58 double *rxn_float_data,
59 Jacobian *jac) {
60 int *int_data = rxn_int_data;
61 double *float_data = rxn_float_data;
62
63 bool *aero_jac_elem =
64 (bool *)malloc(sizeof(bool) * model_data->n_per_cell_state_var);
65 if (aero_jac_elem == NULL) {
66 printf(
67 "\n\nERROR allocating space for 1D Jacobian structure array for "
68 "condensed phase diffusion reaction\n\n");
69 exit(1);
70 }
71
72 for (int i_adj_pairs = 0; i_adj_pairs < NUM_ADJACENT_PAIRS_; ++i_adj_pairs) {
74 AERO_SPEC_INNER_(i_adj_pairs));
76 AERO_SPEC_OUTER_(i_adj_pairs));
78 AERO_SPEC_INNER_(i_adj_pairs));
80 AERO_SPEC_OUTER_(i_adj_pairs));
81 }
82 free(aero_jac_elem);
83
84}
85
86/** \brief Update the time derivative and Jacbobian array indices
87 *
88 * \param model_data Pointer to the model data for finding sub model ids
89 * \param deriv_ids Id of each state variable in the derivative array
90 * \param jac Jacobian
91 * \param rxn_int_data Pointer to the reaction integer data
92 * \param rxn_float_data Pointer to the reaction floating-point data
93 */
94void rxn_condensed_phase_diffusion_update_ids(ModelData *model_data, int *deriv_ids,
95 Jacobian jac, int *rxn_int_data,
96 double *rxn_float_data) {
97 int *int_data = rxn_int_data;
98 double *float_data = rxn_float_data;
99
100 for (int i_adj_pairs = 0; i_adj_pairs < NUM_ADJACENT_PAIRS_; ++i_adj_pairs) {
101 DERIV_ID_INNER_(i_adj_pairs) = deriv_ids[AERO_SPEC_INNER_(i_adj_pairs)];
102 DERIV_ID_OUTER_(i_adj_pairs) = deriv_ids[AERO_SPEC_OUTER_(i_adj_pairs)];
103 }
104}
105
106/** \brief Update reaction data for new environmental conditions
107 *
108 *
109 * \param model_data Pointer to the model data
110 * \param rxn_int_data Pointer to the reaction integer data
111 * \param rxn_float_data Pointer to the reaction floating-point data
112 * \param rxn_env_data Pointer to the environment-dependent parameters
113 */
115 int *rxn_int_data,
116 double *rxn_float_data,
117 double *rxn_env_data) {
118 int *int_data = rxn_int_data;
119 double *float_data = rxn_float_data;
120 double *env_data = model_data->grid_cell_env;
121
122 return;
123}
124
125/** \brief Calculate contributions to the time derivative \f$f(t,y)\f$ from
126 * this reaction.
127 *
128 * \param model_data Pointer to the model data, including the state array
129 * \param time_deriv TimeDerivative object
130 * \param rxn_int_data Pointer to the reaction integer data
131 * \param rxn_float_data Pointer to the reaction floating-point data
132 * \param rxn_env_data Pointer to the environment-dependent parameters
133 * \param time_step Current time step being computed (s)
134 */
135#ifdef CAMP_USE_SUNDIALS
137 ModelData *model_data, TimeDerivative time_deriv, int *rxn_int_data,
138 double *rxn_float_data, double *rxn_env_data, realtype time_step) {
139 int *int_data = rxn_int_data;
140 double *float_data = rxn_float_data;
141 double *state = model_data->grid_cell_state;
142 double *env_data = model_data->grid_cell_env;
143
144 // Calculate derivative contributions for each aerosol phase
145 for (int i_adj_pairs = 0, i_deriv = 0; i_adj_pairs < NUM_ADJACENT_PAIRS_; i_adj_pairs++) {
146
147 /* Get the layer thickness for inner phase id (m) */
148 realtype layer_thickness_inner;
150 model_data, //model data
151 AERO_REP_ID_(i_adj_pairs), // aerosol representation index
152 PHASE_ID_INNER_(i_adj_pairs), // inner phase id
153 &layer_thickness_inner, // layer thickness
154 NULL); // partial derivative
155
156 // Get the layer thickness for outer phase id (m)
157 realtype layer_thickness_outer;
159 model_data, //model data
160 AERO_REP_ID_(i_adj_pairs), // aerosol representation index
161 PHASE_ID_OUTER_(i_adj_pairs), // outer phase id
162 &layer_thickness_outer, // layer thickness
163 NULL); // partial derivative
164
165 // Get the interface surface area (m2)
166 realtype eff_sa;
168 model_data, //model data
169 AERO_REP_ID_(i_adj_pairs), // aerosol representation index
170 PHASE_ID_INNER_(i_adj_pairs), // inner phase id
171 PHASE_ID_OUTER_(i_adj_pairs), // outer phase id
172 &eff_sa, // interface surface area
173 NULL); // partial derivative
174
175 // Get the volume of the inner phase
176 realtype volume_phase_inner;
178 model_data, //model data
179 AERO_REP_ID_(i_adj_pairs), // aerosol representation index
180 PHASE_ID_INNER_(i_adj_pairs), // inner phase id
181 &volume_phase_inner, // volume of inner phase
182 NULL); // partial derivative
183
184 // Get the volume of the outer phase
185 realtype volume_phase_outer;
187 model_data, //model data
188 AERO_REP_ID_(i_adj_pairs), // aerosol representation index
189 PHASE_ID_OUTER_(i_adj_pairs), // outer phase id
190 &volume_phase_outer, // volume of outer phase
191 NULL); // partial derivative
192
193 // Calculate the rate constant for diffusion limited mass transfer between
194 // particle layers
195 double rate_inner = (double)(eff_sa / volume_phase_inner);
196 double rate_outer = (double)(eff_sa / volume_phase_outer);
197
198 rate_inner *= ((-DIFF_COEFF_INNER_(i_adj_pairs) / layer_thickness_inner)
199 * state[AERO_SPEC_INNER_(i_adj_pairs)] +
200 (DIFF_COEFF_OUTER_(i_adj_pairs) / layer_thickness_outer)
201 * state[AERO_SPEC_OUTER_(i_adj_pairs)]);
202 rate_outer *= ((DIFF_COEFF_INNER_(i_adj_pairs) / layer_thickness_inner)
203 * state[AERO_SPEC_INNER_(i_adj_pairs)] -
204 (DIFF_COEFF_OUTER_(i_adj_pairs) / layer_thickness_outer)
205 * state[AERO_SPEC_OUTER_(i_adj_pairs)]);
206 }
207 return;
208}
209#endif
210
211/** \brief Calculate contributions to the Jacobian from this reaction
212 *
213 * \param model_data Pointer to the model data
214 * \param jac Reaction Jacobian
215 * \param rxn_int_data Pointer to the reaction integer data
216 * \param rxn_float_data Pointer to the reaction floating-point data
217 * \param rxn_env_data Pointer to the environment-dependent parameters
218 * \param time_step Current time step being calculated (s)
219 */
220#ifdef CAMP_USE_SUNDIALS
222 Jacobian jac, int *rxn_int_data,
223 double *rxn_float_data,
224 double *rxn_env_data,
225 realtype time_step) {
226 //int *int_data = rxn_int_data;
227 //double *float_data = rxn_float_data;
228 //double *state = model_data->grid_cell_state;
229 //double *env_data = model_data->grid_cell_env;
230}
231#endif
232
233/** \brief Print the Phase Transfer reaction parameters
234 *
235 * \param rxn_int_data Pointer to the reaction integer data
236 * \param rxn_float_data Pointer to the reaction floating-point data
237 */
239 double *rxn_float_data) {
240 int *int_data = rxn_int_data;
241 double *float_data = rxn_float_data;
242
243 printf("\n\nCondensed Phase Diffusion reaction\n");
244 for (int i = 0; i < NUM_ADJACENT_PAIRS_; ++i) {
245 printf("\n Diffusion coefficient inner: %g", DIFF_COEFF_INNER_(i));
246 printf("\n Diffusion coefficient outer: %g", DIFF_COEFF_OUTER_(i));
247 printf("\n Aerosol phase id inner: %d", PHASE_ID_INNER_(i));
248 printf("\n Aerosol phase id outer: %d", PHASE_ID_OUTER_(i));
249 printf("\n Aerosol species id inner: %d", AERO_SPEC_INNER_(i));
250 printf("\n Aerosol species id outer: %d", AERO_SPEC_OUTER_(i));
251 printf("\n Aerosol representation id: %d", AERO_REP_ID_(i));
252}
253
254 return;
255}
void jacobian_register_element(Jacobian *jac, unsigned int dep_id, unsigned int ind_id)
Definition: Jacobian.c:105
void aero_rep_get_interface_surface_area__m2(ModelData *model_data, int aero_rep_idx, int aero_phase_idx_first, int aero_phase_idx_second, double *surface_area, double *partial_deriv)
Get the surface area of interfacial layer between two phases (m^2)
void aero_rep_get_layer_thickness__m(ModelData *model_data, int aero_rep_idx, int aero_phase_idx, double *layer_thickness, double *partial_deriv)
Get the thickness of a particle layer (m)
void aero_rep_get_phase_volume__m3_m3(ModelData *model_data, int aero_rep_idx, int aero_phase_idx, double *phase_volume, double *partial_deriv)
Get the volume of a specified phase in the corresponding layer.
#define PHASE_ID_OUTER_(x)
#define PHASE_ID_INNER_(x)
#define DIFF_COEFF_INNER_(x)
void rxn_condensed_phase_diffusion_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.
void rxn_condensed_phase_diffusion_print(int *rxn_int_data, double *rxn_float_data)
Print the Phase Transfer reaction parameters.
#define DERIV_ID_INNER_(x)
void rxn_condensed_phase_diffusion_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.
#define DERIV_ID_OUTER_(x)
#define NUM_ADJACENT_PAIRS_
#define AERO_SPEC_OUTER_(x)
void rxn_condensed_phase_diffusion_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.
void rxn_condensed_phase_diffusion_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.
#define DIFF_COEFF_OUTER_(x)
#define AERO_SPEC_INNER_(x)
void rxn_condensed_phase_diffusion_get_used_jac_elem(ModelData *model_data, int *rxn_int_data, double *rxn_float_data, Jacobian *jac)
Flag Jacobian elements used by this reaction.
#define AERO_REP_ID_(x)