14#include <camp/Jacobian.h>
15#include <camp/sub_models.h>
18#define TEMPERATURE_K_ env_data[0]
19#define PRESSURE_PA_ env_data[1]
21#define NUM_PHASE_ (int_data[0])
22#define GAS_WATER_ID_ (int_data[1] - 1)
23#define NUM_ION_PAIRS_ (int_data[2])
24#define INT_DATA_SIZE_ (int_data[3])
25#define FLOAT_DATA_SIZE_ (int_data[4])
26#define PPM_TO_RH_ (sub_model_env_data[0])
27#define NUM_INT_PROP_ 5
28#define NUM_REAL_PROP_ 0
29#define NUM_ENV_PARAM_ 1
30#define PHASE_ID_(x) (int_data[NUM_INT_PROP_ + x] - 1)
31#define PAIR_INT_PARAM_LOC_(x) (int_data[NUM_INT_PROP_ + NUM_PHASE_ + x] - 1)
32#define PAIR_FLOAT_PARAM_LOC_(x) \
33 (int_data[NUM_INT_PROP_ + NUM_PHASE_ + NUM_ION_PAIRS_ + x] - 1)
34#define ION_PAIR_ACT_ID_(x) (int_data[PAIR_INT_PARAM_LOC_(x)])
35#define NUM_CATION_(x) (int_data[PAIR_INT_PARAM_LOC_(x) + 1])
36#define NUM_ANION_(x) (int_data[PAIR_INT_PARAM_LOC_(x) + 2])
37#define CATION_ID_(x) (int_data[PAIR_INT_PARAM_LOC_(x) + 3])
38#define ANION_ID_(x) (int_data[PAIR_INT_PARAM_LOC_(x) + 4])
39#define NUM_INTER_(x) (int_data[PAIR_INT_PARAM_LOC_(x) + 5])
40#define JAC_WATER_ID_(p, x) (int_data[PAIR_INT_PARAM_LOC_(x) + 6 + p])
41#define JAC_CATION_ID_(p, x, y) \
42 (int_data[PAIR_INT_PARAM_LOC_(x) + 6 + NUM_PHASE_ + p * NUM_ION_PAIRS_ + y])
43#define JAC_ANION_ID_(p, x, y) \
44 (int_data[PAIR_INT_PARAM_LOC_(x) + 6 + (1 + NUM_ION_PAIRS_) * NUM_PHASE_ + \
45 p * NUM_ION_PAIRS_ + y])
47 (int_data[PAIR_INT_PARAM_LOC_(x) + 6 + \
48 (1 + 2 * NUM_ION_PAIRS_) * NUM_PHASE_ + y])
49#define INTER_SPEC_ID_(x, y) \
50 (int_data[PAIR_INT_PARAM_LOC_(x) + 6 + \
51 (1 + 2 * NUM_ION_PAIRS_) * NUM_PHASE_ + NUM_INTER_(x) + y] - \
53#define INTER_SPEC_LOC_(x, y) \
54 (int_data[PAIR_INT_PARAM_LOC_(x) + 6 + \
55 (1 + 2 * NUM_ION_PAIRS_) * NUM_PHASE_ + 2 * (NUM_INTER_(x)) + y] - \
57#define CATION_MW_(x) (float_data[PAIR_FLOAT_PARAM_LOC_(x)])
58#define ANION_MW_(x) (float_data[PAIR_FLOAT_PARAM_LOC_(x) + 1])
59#define CATION_N_(x) (float_data[PAIR_FLOAT_PARAM_LOC_(x) + 2])
60#define ANION_N_(x) (float_data[PAIR_FLOAT_PARAM_LOC_(x) + 3])
61#define MIN_RH_(x, y) (float_data[INTER_SPEC_LOC_(x, y)])
62#define MAX_RH_(x, y) (float_data[INTER_SPEC_LOC_(x, y) + 1])
63#define B_Z_(x, y, z) (float_data[INTER_SPEC_LOC_(x, y) + 2 + z])
74 double *sub_model_float_data,
76 int *int_data = sub_model_int_data;
77 double *float_data = sub_model_float_data;
79 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase) {
80 for (
int i_ion_pair = 0; i_ion_pair <
NUM_ION_PAIRS_; ++i_ion_pair) {
84 for (
int j_ion_pair = 0; j_ion_pair <
NUM_ION_PAIRS_; ++j_ion_pair) {
106 double *sub_model_float_data,
int *deriv_ids,
108 int *int_data = sub_model_int_data;
109 double *float_data = sub_model_float_data;
111 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase) {
112 for (
int i_ion_pair = 0; i_ion_pair <
NUM_ION_PAIRS_; ++i_ion_pair) {
116 for (
int j_ion_pair = 0; j_ion_pair <
NUM_ION_PAIRS_; ++j_ion_pair) {
138 double *sub_model_float_data,
139 double *sub_model_env_data,
140 ModelData *model_data) {
141 int *int_data = sub_model_int_data;
142 double *float_data = sub_model_float_data;
143 double *env_data = model_data->grid_cell_env;
148 double t_steam = 373.15;
151 a = (((-0.1299 * a - 0.6445) * a - 1.976) * a + 13.3185) * a;
152 double water_vp = 101325.0 * exp(a);
168 double *sub_model_float_data,
169 double *sub_model_env_data,
170 ModelData *model_data) {
171 double *state = model_data->grid_cell_state;
172 int *int_data = sub_model_int_data;
173 double *float_data = sub_model_float_data;
180 if (a_w < 0.0) a_w = 0.0;
181 if (a_w > 1.0) a_w = 1.0;
184 for (
int i_phase = 0; i_phase <
NUM_PHASE_; i_phase++) {
186 for (
int i_ion_pair = 0; i_ion_pair <
NUM_ION_PAIRS_; i_ion_pair++) {
197 for (
int i_ion_pair = 0; i_ion_pair <
NUM_ION_PAIRS_; i_ion_pair++) {
208 long double omega = 0.0;
209 for (
int j_ion_pair = 0; j_ion_pair <
NUM_ION_PAIRS_; ++j_ion_pair) {
210 if (i_ion_pair == j_ion_pair)
continue;
211 omega += (
long double)2.0 *
217 long double ln_gamma = 0.0;
220 for (
int i_inter = 0; i_inter <
NUM_INTER_(i_ion_pair); i_inter++) {
224 if ((a_w <=
MIN_RH_(i_ion_pair, i_inter) ||
225 a_w >
MAX_RH_(i_ion_pair, i_inter)) &&
226 !(a_w <= 0.0 &&
MIN_RH_(i_ion_pair, i_inter) <= 0.0))
233 long double ln_gamma_inter = 0.0;
234 for (
int i_B = 0; i_B <
NUM_B_(i_ion_pair, i_inter); i_B++) {
235 ln_gamma_inter +=
B_Z_(i_ion_pair, i_inter, i_B) * pow(a_w, i_B);
240 if (i_ion_pair == j_ion_pair) {
242 ln_gamma += ln_gamma_inter;
251 ln_gamma += ln_gamma_inter *
CATION_N_(j_ion_pair) *
276#ifdef CAMP_USE_SUNDIALS
278 double *sub_model_float_data,
279 double *sub_model_env_data,
280 ModelData *model_data, realtype *J,
282 int *int_data = sub_model_int_data;
283 double *float_data = sub_model_float_data;
284 double *state = model_data->grid_cell_state;
285 double *env_data = model_data->grid_cell_env;
292 if (a_w < 0.0) a_w = 0.0;
293 if (a_w > 1.0) a_w = 1.0;
296 for (
int i_phase = 0; i_phase <
NUM_PHASE_; i_phase++) {
298 for (
int i_ion_pair = 0; i_ion_pair <
NUM_ION_PAIRS_; i_ion_pair++) {
309 for (
int i_ion_pair = 0; i_ion_pair <
NUM_ION_PAIRS_; i_ion_pair++) {
320 long double omega = 0.0;
321 for (
int j_ion_pair = 0; j_ion_pair <
NUM_ION_PAIRS_; ++j_ion_pair) {
322 if (i_ion_pair == j_ion_pair)
continue;
323 omega += (
long double)2.0 *
329 long double ln_gamma = 0.0;
332 for (
int i_inter = 0; i_inter <
NUM_INTER_(i_ion_pair); i_inter++) {
336 if ((a_w <=
MIN_RH_(i_ion_pair, i_inter) ||
337 a_w >
MAX_RH_(i_ion_pair, i_inter)) &&
338 !(a_w <= 0.0 &&
MIN_RH_(i_ion_pair, i_inter) <= 0.0))
345 long double ln_gamma_inter = 0.0;
346 for (
int i_B = 0; i_B <
NUM_B_(i_ion_pair, i_inter); i_B++) {
347 ln_gamma_inter +=
B_Z_(i_ion_pair, i_inter, i_B) * pow(a_w, i_B);
352 if (i_ion_pair == j_ion_pair) {
354 ln_gamma += ln_gamma_inter;
363 ln_gamma += ln_gamma_inter *
CATION_N_(j_ion_pair) *
370 long double gamma_i = exp(ln_gamma);
373 for (
int i_inter = 0; i_inter <
NUM_INTER_(i_ion_pair); i_inter++) {
377 if ((a_w <=
MIN_RH_(i_ion_pair, i_inter) ||
378 a_w >
MAX_RH_(i_ion_pair, i_inter)) &&
379 !(a_w <= 0.0 &&
MIN_RH_(i_ion_pair, i_inter) <= 0.0))
386 long double ln_gamma_inter =
B_Z_(i_ion_pair, i_inter, 0);
387 long double d_ln_gamma_inter_d_water = 0.0;
388 for (
int i_B = 1; i_B <
NUM_B_(i_ion_pair, i_inter); i_B++) {
389 ln_gamma_inter +=
B_Z_(i_ion_pair, i_inter, i_B) * pow(a_w, i_B);
390 d_ln_gamma_inter_d_water +=
391 B_Z_(i_ion_pair, i_inter, i_B) * i_B * pow(a_w, i_B - 1);
397 if (i_ion_pair == j_ion_pair) {
400 gamma_i * d_ln_gamma_inter_d_water;
412 gamma_i * ln_gamma_inter *
ANION_N_(j_ion_pair) /
417 gamma_i * ln_gamma_inter *
CATION_N_(j_ion_pair) /
423 d_ln_gamma_inter_d_water;
430 if (k_ion_pair == i_ion_pair)
continue;
434 -gamma_i * ln_gamma_inter *
CATION_N_(j_ion_pair) *
435 ANION_N_(j_ion_pair) / (omega * omega) * 2.0 *
441 -gamma_i * ln_gamma_inter *
CATION_N_(j_ion_pair) *
442 ANION_N_(j_ion_pair) / (omega * omega) * 2.0 *
463 double *sub_model_float_data) {
464 int *int_data = sub_model_int_data;
465 double *float_data = sub_model_float_data;
467 printf(
"\n\n*** PD-FiTE activity sub model ***\n");
470 printf(
" int param %d = %d\n", i, int_data[i]);
472 printf(
" float param %d = %le\n", i, float_data[i]);
474 printf(
"\n number of phases: %d",
NUM_PHASE_);
477 printf(
"\n ** Phase data **");
478 printf(
"\n (Ids for ions and activity coefficients are relative");
479 printf(
"\n to the state id of aerosol-phase water for each phase.)");
480 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase) {
481 printf(
"\n phase %d: aerosol-phase water state id: %d", i_phase,
484 printf(
"\n ** Ion pair data **");
486 printf(
"\n Ion pair %d", i_pair);
487 printf(
"\n State ids (relative to aerosol-phase water)");
490 printf(
"\n Anion: %d",
ANION_ID_(i_pair));
491 printf(
"\n Jacobian aerosol water id (by phase):");
492 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase)
494 printf(
"\n Cation stoichiometry: %d",
NUM_CATION_(i_pair));
495 printf(
"\n Anion stoichiometry: %d",
NUM_ANION_(i_pair));
496 printf(
"\n Cation MW (kg/mol): %le",
CATION_MW_(i_pair));
498 printf(
"\n Anion MW (kg/mol): %le",
ANION_MW_(i_pair));
500 printf(
"\n Cation concentration (mol m-3): %le",
CATION_N_(i_pair));
501 printf(
"\n Anion concentration (mol m-3): %le",
ANION_N_(i_pair));
502 printf(
"\n Number of ion-pair interactions: %d",
NUM_INTER_(i_pair));
503 printf(
"\n * Jacobian Omega ids *");
505 printf(
"\n Ion pair index: %d", i_oip);
506 printf(
"\n Anion (by phase)");
507 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase)
509 printf(
"\n Cation (by phase)");
510 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase)
513 printf(
"\n * Ion-pair interaction data *");
514 for (
int i_inter = 0; i_inter <
NUM_INTER_(i_pair); ++i_inter) {
515 printf(
"\n Interaction %d:", i_inter);
517 printf(
"\n Min RH: %le",
MIN_RH_(i_pair, i_inter));
518 printf(
"\n Max RH: %le",
MAX_RH_(i_pair, i_inter));
519 printf(
"\n Jacobian ids (by phase)");
520 printf(
"\n Cation:");
521 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase)
524 printf(
"\n Anion: ");
525 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase)
529 for (
int i_B = 0; i_B <
NUM_B_(i_pair, i_inter); ++i_B)
530 printf(
" B%d: %le", i_B,
B_Z_(i_pair, i_inter, i_B));
533 printf(
"\n*** end PD-FiTE activity sub model ***");
unsigned int jacobian_get_element_id(Jacobian jac, unsigned int dep_id, unsigned int ind_id)
void jacobian_register_element(Jacobian *jac, unsigned int dep_id, unsigned int ind_id)
#define INTER_SPEC_ID_(x, y)
void sub_model_PDFiTE_get_used_jac_elem(int *sub_model_int_data, double *sub_model_float_data, Jacobian *jac)
Flag Jacobian elements used by this sub model.
void sub_model_PDFiTE_calculate(int *sub_model_int_data, double *sub_model_float_data, double *sub_model_env_data, ModelData *model_data)
Perform the sub-model calculations for the current model state.
#define ION_PAIR_ACT_ID_(x)
void sub_model_PDFiTE_get_jac_contrib(int *sub_model_int_data, double *sub_model_float_data, double *sub_model_env_data, ModelData *model_data, realtype *J, double time_step)
Add contributions to the Jacobian from derivates calculated using the output of this sub model.
void sub_model_PDFiTE_print(int *sub_model_int_data, double *sub_model_float_data)
Print the PDFiTE Activity sub model parameters.
void sub_model_PDFiTE_update_ids(int *sub_model_int_data, double *sub_model_float_data, int *deriv_ids, Jacobian jac)
Update the time derivative and Jacbobian array indices.
#define JAC_ANION_ID_(p, x, y)
void sub_model_PDFiTE_update_env_state(int *sub_model_int_data, double *sub_model_float_data, double *sub_model_env_data, ModelData *model_data)
Update sub model data for new environmental conditions.
#define JAC_WATER_ID_(p, x)
#define JAC_CATION_ID_(p, x, y)