14#include "../Jacobian.h"
15#include "../sub_models.h"
18#define TEMPERATURE_K_ env_data[0]
19#define PRESSURE_PA_ env_data[1]
22#define MINIMUM_WATER_MASS_ 1.0e-30L
25#define ALPHA_ (-100.0)
27#define ACT_TYPE_JACOBSON 1
28#define ACT_TYPE_EQSAM 2
30#define NUM_PHASE_ (int_data[0])
31#define GAS_WATER_ID_ (int_data[1] - 1)
32#define NUM_ION_PAIR_ (int_data[2])
33#define INT_DATA_SIZE_ (int_data[3])
34#define FLOAT_DATA_SIZE_ (int_data[4])
35#define PPM_TO_RH_ (sub_model_env_data[0])
36#define NUM_INT_PROP_ 5
37#define NUM_REAL_PROP_ 0
38#define NUM_ENV_PARAM_ 1
39#define PHASE_ID_(p) (int_data[NUM_INT_PROP_ + p] - 1)
40#define PAIR_INT_PARAM_LOC_(x) (int_data[NUM_INT_PROP_ + NUM_PHASE_ + x] - 1)
41#define PAIR_FLOAT_PARAM_LOC_(x) \
42 (int_data[NUM_INT_PROP_ + NUM_PHASE_ + NUM_ION_PAIR_ + x] - 1)
43#define TYPE_(x) (int_data[PAIR_INT_PARAM_LOC_(x)])
44#define JACOB_NUM_CATION_(x) (int_data[PAIR_INT_PARAM_LOC_(x) + 1])
45#define JACOB_NUM_ANION_(x) (int_data[PAIR_INT_PARAM_LOC_(x) + 2])
46#define JACOB_CATION_ID_(x) (int_data[PAIR_INT_PARAM_LOC_(x) + 3])
47#define JACOB_ANION_ID_(x) (int_data[PAIR_INT_PARAM_LOC_(x) + 4])
48#define JACOB_NUM_Y_(x) (int_data[PAIR_INT_PARAM_LOC_(x) + 5])
49#define JACOB_GAS_WATER_JAC_ID_(p, x) int_data[PAIR_INT_PARAM_LOC_(x) + 6 + p]
50#define JACOB_CATION_JAC_ID_(p, x) \
51 int_data[PAIR_INT_PARAM_LOC_(x) + 6 + NUM_PHASE_ + p]
52#define JACOB_ANION_JAC_ID_(p, x) \
53 int_data[PAIR_INT_PARAM_LOC_(x) + 6 + 2 * NUM_PHASE_ + p]
54#define EQSAM_NUM_ION_(x) (int_data[PAIR_INT_PARAM_LOC_(x) + 1])
55#define EQSAM_GAS_WATER_JAC_ID_(p, x) (int_data[PAIR_INT_PARAM_LOC_(x) + 2 + p])
56#define EQSAM_ION_ID_(x, y) \
57 (int_data[PAIR_INT_PARAM_LOC_(x) + 2 + NUM_PHASE_ + y])
58#define EQSAM_ION_JAC_ID_(p, x, y) \
59 int_data[PAIR_INT_PARAM_LOC_(x) + 2 + NUM_PHASE_ + EQSAM_NUM_ION_(x) + \
61#define JACOB_low_RH_(x) (float_data[PAIR_FLOAT_PARAM_LOC_(x)])
62#define JACOB_CATION_MW_(x) (float_data[PAIR_FLOAT_PARAM_LOC_(x) + 1])
63#define JACOB_ANION_MW_(x) (float_data[PAIR_FLOAT_PARAM_LOC_(x) + 2])
64#define JACOB_Y_(x, y) (float_data[PAIR_FLOAT_PARAM_LOC_(x) + 3 + y])
65#define EQSAM_NW_(x) (float_data[PAIR_FLOAT_PARAM_LOC_(x)])
66#define EQSAM_ZW_(x) (float_data[PAIR_FLOAT_PARAM_LOC_(x) + 1])
67#define EQSAM_ION_PAIR_MW_(x) (float_data[PAIR_FLOAT_PARAM_LOC_(x) + 2])
68#define EQSAM_ION_MW_(x, y) (float_data[PAIR_FLOAT_PARAM_LOC_(x) + 3 + y])
82 double *sub_model_float_data,
84 int *int_data = sub_model_int_data;
85 double *float_data = sub_model_float_data;
89 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase) {
94 for (
int i_ion_pair = 0; i_ion_pair <
NUM_ION_PAIR_; ++i_ion_pair) {
96 switch (
TYPE_(i_ion_pair)) {
113 for (
int i_ion = 0; i_ion <
EQSAM_NUM_ION_(i_ion_pair); i_ion++) {
134 double *sub_model_float_data,
136 int *int_data = sub_model_int_data;
137 double *float_data = sub_model_float_data;
141 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase) {
143 for (
int i_ion_pair = 0; i_ion_pair <
NUM_ION_PAIR_; ++i_ion_pair) {
145 switch (
TYPE_(i_ion_pair)) {
170 for (
int i_ion = 0; i_ion <
EQSAM_NUM_ION_(i_ion_pair); i_ion++) {
190 double *sub_model_float_data,
191 double *sub_model_env_data,
193 int *int_data = sub_model_int_data;
194 double *float_data = sub_model_float_data;
200 double t_steam = 373.15;
203 a = (((-0.1299 * a - 0.6445) * a - 1.976) * a + 13.3185) * a;
204 double water_vp = 101325.0 * exp(a);
217 double *sub_model_float_data,
218 double *sub_model_env_data,
221 int *int_data = sub_model_int_data;
222 double *float_data = sub_model_float_data;
228 for (
int i_phase = 0; i_phase <
NUM_PHASE_; i_phase++) {
229 double *water = &(state[
PHASE_ID_(i_phase)]);
233 for (
int i_ion_pair = 0; i_ion_pair <
NUM_ION_PAIR_; i_ion_pair++) {
234 long double molality, conc;
237 switch (
TYPE_(i_ion_pair)) {
247 for (
int i_order = 0; i_order <
JACOB_NUM_Y_(i_ion_pair); i_order++)
248 molality +=
JACOB_Y_(i_ion_pair, i_order) * pow(j_aw, i_order);
249 molality *= molality;
268 long double e_ac = exp(
ALPHA_ * cation);
269 long double e_aa = exp(
ALPHA_ * anion);
270 conc = (cation * e_ac + anion * e_aa) / (e_ac + e_aa);
272 *water += conc / molality * 1000.0;
280 long double e_aw = a_w > 0.99 ? 0.99 : a_w;
281 e_aw = e_aw < 0.001 ? 0.001 : e_aw;
287 molality = pow(molality,
EQSAM_ZW_(i_ion_pair));
290 for (
int i_ion = 0; i_ion <
EQSAM_NUM_ION_(i_ion_pair); i_ion++) {
292 conc = (conc > 0.0 ? conc : 0.0);
313#ifdef CAMP_USE_SUNDIALS
315 double *sub_model_float_data,
316 double *sub_model_env_data,
320 int *int_data = sub_model_int_data;
321 double *float_data = sub_model_float_data;
330 for (
int i_phase = 0; i_phase <
NUM_PHASE_; i_phase++) {
332 for (
int i_ion_pair = 0; i_ion_pair <
NUM_ION_PAIR_; i_ion_pair++) {
333 long double molality, d_molal_d_wg;
337 switch (
TYPE_(i_ion_pair)) {
344 long double d_jaw_d_wg =
350 for (
int i_order = 1; i_order <
JACOB_NUM_Y_(i_ion_pair); i_order++) {
351 molality +=
JACOB_Y_(i_ion_pair, i_order) * pow(j_aw, i_order);
352 d_molal_d_wg +=
JACOB_Y_(i_ion_pair, i_order) * i_order *
353 pow(j_aw, (i_order - 1));
355 d_molal_d_wg *= d_jaw_d_wg;
373 long double e_ac = exp(
ALPHA_ * cation);
374 long double e_aa = exp(
ALPHA_ * anion);
375 conc = (cation * e_ac + anion * e_aa) / (e_ac + e_aa);
376 long double denom = (e_ac + e_aa) * (e_ac + e_aa);
377 long double d_conc_d_cation =
379 e_ac * e_aa * (1.0 -
ALPHA_ * anion +
ALPHA_ * cation)) /
381 long double d_conc_d_anion =
383 e_ac * e_aa * (1.0 -
ALPHA_ * cation +
ALPHA_ * anion)) /
388 -2.0 * conc / pow(molality, 3) * 1000.0 * d_molal_d_wg;
390 1.0 / pow(molality, 2) * 1000.0 * d_conc_d_anion * d_anion_d_A;
392 1.0 / pow(molality, 2) * 1000.0 * d_conc_d_cation * d_cation_d_C;
400 long double e_aw = a_w > 0.99 ? 0.99 : a_w;
401 e_aw = e_aw < 0.001 ? 0.001 : e_aw;
402 long double d_eaw_d_wg = a_w > 0.99 ? 0.0 : d_aw_d_wg;
403 d_eaw_d_wg = a_w < 0.001 ? 0.0 : d_eaw_d_wg;
409 d_molal_d_wg = -
EQSAM_NW_(i_ion_pair) * 55.51 * 18.01 /
411 pow(e_aw, 2) * d_eaw_d_wg;
413 pow(molality,
EQSAM_ZW_(i_ion_pair) - 1.0) *
415 molality = pow(molality,
EQSAM_ZW_(i_ion_pair));
418 for (
int i_ion = 0; i_ion <
EQSAM_NUM_ION_(i_ion_pair); i_ion++) {
420 conc = (conc > 0.0 ? conc : 0.0);
421 long double d_conc_d_ion = (conc > 0.0 ? 1.0 : 0.0);
426 pow(molality, 2) * d_molal_d_wg;
446 double *sub_model_float_data) {
447 int *int_data = sub_model_int_data;
448 double *float_data = sub_model_float_data;
450 printf(
"\n\nZSR aerosol water sub model\n");
452 printf(
" int param %d = %d\n", i, int_data[i]);
454 printf(
" float param %d = %le\n", i, float_data[i]);
458 printf(
"\n*** Phase state ids (index of water in each phase) ***");
459 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase) {
460 printf(
"\n phase %d: %d", i_phase,
PHASE_ID_(i_phase));
462 printf(
"\n*** Ion-Pair info ***");
463 for (
int i_ion_pair = 0; i_ion_pair <
NUM_ION_PAIR_; ++i_ion_pair) {
464 printf(
"\n ION PAIR %d", i_ion_pair);
465 switch (
TYPE_(i_ion_pair)) {
467 printf(
"\n *** JACOBSON ***");
469 printf(
"\n number of cations: %d number of anions: %d",
473 printf(
"\n cation MW: %le anion MW: %le",
475 printf(
"\n number of Y parameters: %d:",
JACOB_NUM_Y_(i_ion_pair));
476 for (
int i_Y = 0; i_Y <
JACOB_NUM_Y_(i_ion_pair); ++i_Y)
477 printf(
" Y(%d)=%le", i_Y,
JACOB_Y_(i_ion_pair, i_Y));
478 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase) {
479 printf(
"\n PHASE %d:", i_phase);
480 printf(
" gas-phase water Jac id: %d",
482 printf(
" cation Jac id: %d",
488 printf(
"\n *** EQSAM ***");
489 printf(
"\n NW: %le ZW: %le ion pair MW: %le",
EQSAM_NW_(i_ion_pair),
493 for (
int i_ion = 0; i_ion <
EQSAM_NUM_ION_(i_ion_pair); ++i_ion) {
495 for (
int i_phase = 0; i_phase <
NUM_PHASE_; ++i_phase) {
497 "\n phase: %d gas-phase water Jac id: %d "
505 printf(
"\n !!! INVALID TYPE SPECIFIED: %d",
TYPE_(i_ion_pair));
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_register_element(Jacobian *jac, unsigned int dep_id, unsigned int ind_id)
Adds an element to the sparse matrix.
#define EQSAM_NUM_ION_(x)
#define EQSAM_ION_PAIR_MW_(x)
#define EQSAM_ION_ID_(x, y)
void sub_model_ZSR_aerosol_water_get_used_jac_elem(int *sub_model_int_data, double *sub_model_float_data, Jacobian *jac)
Flag Jacobian elements used by this sub model.
#define MINIMUM_WATER_MASS_
#define EQSAM_ION_JAC_ID_(p, x, y)
#define EQSAM_GAS_WATER_JAC_ID_(p, x)
#define JACOB_CATION_MW_(x)
#define JACOB_CATION_ID_(x)
void sub_model_ZSR_aerosol_water_calculate(int *sub_model_int_data, double *sub_model_float_data, double *sub_model_env_data, ModelData *model_data)
Do pre-derivative calculations.
void sub_model_ZSR_aerosol_water_print(int *sub_model_int_data, double *sub_model_float_data)
Print the ZSR Aerosol Water sub model parameters.
#define JACOB_ANION_JAC_ID_(p, x)
void sub_model_ZSR_aerosol_water_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 JACOB_ANION_MW_(x)
#define ACT_TYPE_JACOBSON
void sub_model_ZSR_aerosol_water_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.
#define EQSAM_ION_MW_(x, y)
#define JACOB_NUM_ANION_(x)
#define JACOB_ANION_ID_(x)
#define JACOB_GAS_WATER_JAC_ID_(p, x)
#define JACOB_NUM_CATION_(x)
void sub_model_ZSR_aerosol_water_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 JACOB_CATION_JAC_ID_(p, x)