14#include "../aero_rep_solver.h"
19#define TEMPERATURE_K_ env_data[0]
20#define PRESSURE_PA_ env_data[1]
22#define DIFF_COEFF_ float_data[0]
23#define GAMMA_ float_data[1]
24#define MW_ float_data[2]
25#define NUM_AERO_PHASE_ int_data[0]
26#define REACT_ID_ (int_data[1] - 1)
27#define NUM_PROD_ int_data[2]
28#define MEAN_SPEED_MS_ rxn_env_data[0]
29#define NUM_INT_PROP_ 3
30#define NUM_FLOAT_PROP_ 3
31#define NUM_ENV_PARAM_ 1
32#define PROD_ID_(x) (int_data[NUM_INT_PROP_ + x] - 1)
33#define DERIV_ID_(x) int_data[NUM_INT_PROP_ + NUM_PROD_ + x]
34#define JAC_ID_(x) int_data[NUM_INT_PROP_ + 1 + 2 * NUM_PROD_ + x]
35#define PHASE_INT_LOC_(x) \
36 (int_data[NUM_INT_PROP_ + 2 + 3 * NUM_PROD_ + x] - 1)
37#define PHASE_FLOAT_LOC_(x) \
38 (int_data[NUM_INT_PROP_ + 2 + 3 * NUM_PROD_ + NUM_AERO_PHASE_ + x] - 1)
39#define AERO_PHASE_ID_(x) (int_data[PHASE_INT_LOC_(x)] - 1)
40#define AERO_REP_ID_(x) (int_data[PHASE_INT_LOC_(x) + 1] - 1)
41#define NUM_AERO_PHASE_JAC_ELEM_(x) (int_data[PHASE_INT_LOC_(x) + 2])
42#define PHASE_JAC_ID_(x, s, e) \
43 int_data[PHASE_INT_LOC_(x) + 3 + (s) * NUM_AERO_PHASE_JAC_ELEM_(x) + e]
44#define YIELD_(x) float_data[NUM_FLOAT_PROP_ + x]
45#define EFF_RAD_JAC_ELEM_(x, e) float_data[PHASE_FLOAT_LOC_(x) + e]
46#define NUM_CONC_JAC_ELEM_(x, e) \
47 float_data[PHASE_FLOAT_LOC_(x) + NUM_AERO_PHASE_JAC_ELEM_(x) + e]
58 double *rxn_float_data,
60 int *int_data = rxn_int_data;
61 double *float_data = rxn_float_data;
65 if (aero_jac_elem == NULL) {
67 "\n\nERROR allocating space for 1D jacobian structure array for "
68 "surface reaction\n\n");
73 for (
int i_prod = 0; i_prod <
NUM_PROD_; ++i_prod) {
77 for (
int i_aero_phase = 0; i_aero_phase <
NUM_AERO_PHASE_; ++i_aero_phase) {
79 aero_jac_elem[i_elem] =
false;
86 "\n\nERROR Received more Jacobian elements than expected for surface "
87 "reaction. Got %d, expected <= %d",
93 if (aero_jac_elem[i_elem] ==
true) {
96 for (
int i_prod = 0; i_prod <
NUM_PROD_; ++i_prod) {
98 PHASE_JAC_ID_(i_aero_phase, i_prod + 1, i_used_elem) = i_elem;
105 for (
int i_spec = 0; i_spec <
NUM_PROD_ + 1; ++i_spec) {
109 if (i_used_elem != n_jac_elem) {
111 "\n\nERROR Error setting used Jacobian elements in surface "
112 "reaction %d %d\n\n",
113 i_used_elem, n_jac_elem);
134 double *rxn_float_data) {
135 int *int_data = rxn_int_data;
136 double *float_data = rxn_float_data;
140 for (
int i_prod = 0; i_prod <
NUM_PROD_; ++i_prod) {
147 for (
int i_prod = 0; i_prod <
NUM_PROD_; ++i_prod) {
150 for (
int i_aero_phase = 0; i_aero_phase <
NUM_AERO_PHASE_; ++i_aero_phase) {
156 for (
int i_prod = 0; i_prod <
NUM_PROD_; ++i_prod) {
180 double *rxn_float_data,
181 double *rxn_env_data) {
182 int *int_data = rxn_int_data;
183 double *float_data = rxn_float_data;
202#ifdef CAMP_USE_SUNDIALS
205 double *rxn_float_data,
double *rxn_env_data, realtype time_step) {
206 int *int_data = rxn_int_data;
207 double *float_data = rxn_float_data;
223 realtype number_conc;
234 double cond_rate = state[
REACT_ID_] * number_conc *
243 for (
int i_prod = 0; i_prod <
NUM_PROD_; ++i_prod) {
246 YIELD_(i_prod) * cond_rate);
263#ifdef CAMP_USE_SUNDIALS
266 double *rxn_float_data,
267 double *rxn_env_data,
268 realtype time_step) {
269 int *int_data = rxn_int_data;
270 double *float_data = rxn_float_data;
286 realtype number_conc;
300 double cond_rate = state[
REACT_ID_] * number_conc * rate_const;
305 number_conc * rate_const);
307 for (
int i_prod = 0; i_prod <
NUM_PROD_; ++i_prod) {
308 if (
JAC_ID_(i_prod + 1) >= 0) {
310 YIELD_(i_prod) * number_conc * rate_const);
315 double d_rate_d_radius = state[
REACT_ID_] * number_conc *
318 double d_rate_d_number = state[
REACT_ID_] * rate_const;
336 for (
int i_prod = 0; i_prod <
NUM_PROD_; ++i_prod) {
340 jac, (
unsigned int)
PHASE_JAC_ID_(i_phase, i_prod + 1, i_elem),
342 YIELD_(i_prod) * d_rate_d_radius *
346 jac, (
unsigned int)
PHASE_JAC_ID_(i_phase, i_prod + 1, i_elem),
348 YIELD_(i_prod) * d_rate_d_number *
364 int *int_data = rxn_int_data;
365 double *float_data = rxn_float_data;
367 printf(
"\n\nSurface reaction\n");
368 printf(
"\ndiffusion coefficient: %lg gamma: %lg, MW: %lg",
DIFF_COEFF_,
371 printf(
"\nreactant state id: %d",
REACT_ID_);
372 printf(
"\nnumber of products: %d",
NUM_PROD_);
373 for (
int i_prod = 0; i_prod <
NUM_PROD_; ++i_prod) {
374 printf(
"\n product %d id: %d", i_prod,
PROD_ID_(i_prod));
376 printf(
"\nreactant derivative id: %d",
DERIV_ID_(0));
377 printf(
"\nd_reactant/d_reactant Jacobian id %d",
JAC_ID_(0));
378 for (
int i_prod = 0; i_prod <
NUM_PROD_; ++i_prod) {
379 printf(
"\n product %d derivative id: %d", i_prod,
DERIV_ID_(i_prod+1));
380 printf(
"\n d_product_%d/d_reactant Jacobian id: %d", i_prod,
384 printf(
"\nPhase %d start indices int: %d float: %d", i_phase,
386 printf(
"\n phase id %d; aerosol representation id %d",
388 printf(
"\n number of Jacobian elements: %d",
391 printf(
"\n - d_reactant/d_phase_species_%d Jacobian id %d",
393 for (
int i_prod = 0; i_prod <
NUM_PROD_; ++i_prod) {
394 printf(
"\n - d_product_%d/d_phase_species_%d Jacobian id %d",
397 printf(
"\n - d_radius/d_phase_species_%d = %le",
399 printf(
"\n - d_number/d_phase_species_%d = %le",
403 printf(
"\n *** end surface reaction ***\n\n");
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.
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.
void jacobian_register_element(Jacobian *jac, unsigned int dep_id, unsigned int ind_id)
Adds an element to the sparse matrix.
#define JACOBIAN_PRODUCTION
int aero_rep_get_used_jac_elem(ModelData *model_data, int aero_rep_idx, int aero_phase_idx, bool *jac_struct)
Flag Jacobian elements used to calculated mass, volume, etc.
void aero_rep_get_number_conc__n_m3(ModelData *model_data, int aero_rep_idx, int aero_phase_idx, double *number_conc, double *partial_deriv)
Get the particle number concentration ( )
void aero_rep_get_effective_radius__m(ModelData *model_data, int aero_rep_idx, int aero_phase_idx, double *radius, double *partial_deriv)
Get the effective particle radius, (m)
#define PHASE_INT_LOC_(x)
void rxn_surface_get_used_jac_elem(ModelData *model_data, int *rxn_int_data, double *rxn_float_data, Jacobian *jac)
Flag Jacobian elements used by this reaction.
void rxn_surface_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.
#define AERO_PHASE_ID_(x)
void rxn_surface_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.
void rxn_surface_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_surface_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 PHASE_JAC_ID_(x, s, e)
#define NUM_AERO_PHASE_JAC_ELEM_(x)
#define EFF_RAD_JAC_ELEM_(x, e)
#define NUM_CONC_JAC_ELEM_(x, e)
void rxn_surface_print(int *rxn_int_data, double *rxn_float_data)
Print the surface reaction parameters.
#define PHASE_FLOAT_LOC_(x)
void time_derivative_add_value(TimeDerivative time_deriv, unsigned int spec_id, long double rate_contribution)
Add a contribution to the time derivative.
static double mean_speed__m_s(double temperature__K, double mw__kg_mol)
static double d_gas_aerosol_continuum_rxn_rate_constant_d_radius(double diffusion_coeff__m2_s, double mean_speed__m_s, double radius__m, double alpha)
static double gas_aerosol_continuum_rxn_rate_constant(double diffusion_coeff__m2_s, double mean_speed__m_s, double radius__m, double alpha)