19#include "../Jacobian.h"
20#include "../sub_models.h"
23#define TEMPERATURE_K_ env_data[0]
24#define PRESSURE_PA_ env_data[1]
26#define NUM_UNIQUE_PHASE_ (int_data[0])
27#define NUM_GROUP_ (int_data[1])
28#define TOTAL_INT_PROP_ (int_data[2])
29#define TOTAL_FLOAT_PROP_ (int_data[3])
30#define NUM_INT_PROP_ 4
31#define NUM_FLOAT_PROP_ 0
32#define PHASE_INT_LOC_(p) (int_data[NUM_INT_PROP_ + p] - 1)
33#define PHASE_FLOAT_LOC_(p) \
34 (int_data[NUM_INT_PROP_ + NUM_UNIQUE_PHASE_ + p] - 1)
35#define PHASE_ENV_LOC_(p) \
36 (int_data[NUM_INT_PROP_ + 2 * NUM_UNIQUE_PHASE_ + p] - 1)
37#define NUM_PHASE_INSTANCE_(p) (int_data[PHASE_INT_LOC_(p)])
38#define NUM_SPEC_(p) (int_data[PHASE_INT_LOC_(p) + 1])
39#define PHASE_INST_ID_(p, c) (int_data[PHASE_INT_LOC_(p) + 2 + c] - 1)
40#define SPEC_ID_(p, i) \
41 (int_data[PHASE_INT_LOC_(p) + 2 + NUM_PHASE_INSTANCE_(p) + i])
42#define GAMMA_ID_(p, i) \
43 (int_data[PHASE_INT_LOC_(p) + 2 + NUM_PHASE_INSTANCE_(p) + NUM_SPEC_(p) + i])
44#define JAC_ID_(p, c, j, i) \
45 int_data[PHASE_INT_LOC_(p) + 2 + NUM_PHASE_INSTANCE_(p) + \
46 (2 + c * NUM_SPEC_(p) + j) * NUM_SPEC_(p) + i]
47#define V_IK_(p, i, k) \
48 (int_data[PHASE_INT_LOC_(p) + 2 + NUM_PHASE_INSTANCE_(p) + \
49 (k + 2 + NUM_PHASE_INSTANCE_(p) * NUM_SPEC_(p)) * NUM_SPEC_(p) + \
52#define Q_K_(k) (float_data[k])
53#define R_K_(k) (float_data[NUM_GROUP_ + k])
54#define X_K_(m) (float_data[2 * NUM_GROUP_ + m])
55#define DTHETA_M_DC_I_(m) (float_data[3 * NUM_GROUP_ + m])
56#define XI_M_(m) (float_data[4 * NUM_GROUP_ + m])
57#define LN_GAMMA_K_(m) (float_data[5 * NUM_GROUP_ + m])
58#define A_MN_(m, n) (float_data[(m + 6) * NUM_GROUP_ + n])
59#define R_I_(p, i) (float_data[PHASE_FLOAT_LOC_(p) + i])
60#define Q_I_(p, i) (float_data[PHASE_FLOAT_LOC_(p) + NUM_SPEC_(p) + i])
61#define L_I_(p, i) (float_data[PHASE_FLOAT_LOC_(p) + 2 * NUM_SPEC_(p) + i])
62#define MW_I_(p, i) (float_data[PHASE_FLOAT_LOC_(p) + 3 * NUM_SPEC_(p) + i])
63#define X_I_(p, i) (float_data[PHASE_FLOAT_LOC_(p) + 4 * NUM_SPEC_(p) + i])
65#define THETA_M_(m) (sub_model_env_data[m])
66#define PSI_MN_(m, n) (sub_model_env_data[(m + 1) * NUM_GROUP_ + n])
67#define LN_GAMMA_IK_(p, i, k) \
68 (sub_model_env_data[PHASE_ENV_LOC_(p) + i * NUM_GROUP_ + k])
70#define INT_DATA_SIZE_ (TOTAL_INT_PROP_)
71#define FLOAT_DATA_SIZE_ (TOTAL_FLOAT_PROP_)
83 double *sub_model_float_data,
85 int *int_data = sub_model_int_data;
86 double *float_data = sub_model_float_data;
90 for (
int i_gamma = 0; i_gamma <
NUM_SPEC_(i_phase); ++i_gamma)
91 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec)
107 double *sub_model_float_data,
int *deriv_ids,
109 int *int_data = sub_model_int_data;
110 double *float_data = sub_model_float_data;
114 for (
int i_gamma = 0; i_gamma <
NUM_SPEC_(i_phase); ++i_gamma)
115 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec)
130 double *sub_model_float_data,
131 double *sub_model_env_data,
133 int *int_data = sub_model_int_data;
134 double *float_data = sub_model_float_data;
145 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); i_spec++) {
148 double sum_Qn_Xn = 0.0;
149 double total_group_moles = 0.0;
150 for (
int i_group = 0; i_group <
NUM_GROUP_; i_group++) {
151 sum_Qn_Xn +=
Q_K_(i_group) *
V_IK_(i_phase, i_spec, i_group);
152 total_group_moles +=
V_IK_(i_phase, i_spec, i_group);
154 sum_Qn_Xn *= 1.0 / total_group_moles;
159 Q_K_(m) *
V_IK_(i_phase, i_spec, m) / sum_Qn_Xn / total_group_moles;
163 double sum_m_A = 0.0;
164 double sum_m_B = 0.0;
173 Q_K_(k) * (1.0 - log(sum_m_A) - sum_m_B);
227 double *sub_model_float_data,
228 double *sub_model_env_data,
230 int *int_data = sub_model_int_data;
231 double *float_data = sub_model_float_data;
241 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec) {
244 MW_I_(i_phase, i_spec);
249 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec) {
262 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec) {
266 MW_I_(i_phase, i_spec) / m_T;
267 X_I_(i_phase, i_spec) = x_i;
270 sigma +=
R_I_(i_phase, i_spec) * x_i;
271 tau +=
Q_I_(i_phase, i_spec) * x_i;
272 mu +=
L_I_(i_phase, i_spec) * x_i;
278 for (
int i_group = 0; i_group <
NUM_GROUP_; ++i_group) {
280 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec) {
282 V_IK_(i_phase, i_spec, i_group) *
X_I_(i_phase, i_spec);
284 X_K_(i_group) += v_ik_x_i;
288 for (
int i_group = 0; i_group <
NUM_GROUP_; ++i_group) {
289 X_K_(i_group) *= c_xX;
290 Pi +=
Q_K_(i_group) *
X_K_(i_group);
293 for (
int i_group = 0; i_group <
NUM_GROUP_; ++i_group)
297 for (
int i_group = 0; i_group <
NUM_GROUP_; ++i_group) {
298 XI_M_(i_group) = 0.0;
299 for (
int j_group = 0; j_group <
NUM_GROUP_; ++j_group) {
313 for (
int j = 0; j <
NUM_SPEC_(i_phase); ++j) {
315 double x_j =
X_I_(i_phase, j);
319 Phi_j =
R_I_(i_phase, j) * x_j / sigma;
323 Theta_j =
Q_I_(i_phase, j) * x_j / tau;
326 double lngammaC_j = 0.0;
327 if (
X_I_(i_phase, j) > 0.0) {
328 lngammaC_j = log(Phi_j / x_j) +
329 5.0 *
Q_I_(i_phase, j) * log(Theta_j / Phi_j) +
330 L_I_(i_phase, j) - Phi_j / x_j * mu;
334 double lngammaR_j = 0.0;
336 lngammaR_j +=
V_IK_(i_phase, j, k) *
342 exp(lngammaC_j + lngammaR_j) *
X_I_(i_phase, j);
574#ifdef CAMP_USE_SUNDIALS
576 double *sub_model_float_data,
577 double *sub_model_env_data,
580 int *int_data = sub_model_int_data;
581 double *float_data = sub_model_float_data;
592 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec) {
595 MW_I_(i_phase, i_spec);
609 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec) {
613 MW_I_(i_phase, i_spec) / m_T;
614 X_I_(i_phase, i_spec) = x_i;
617 sigma +=
R_I_(i_phase, i_spec) * x_i;
618 tau +=
Q_I_(i_phase, i_spec) * x_i;
619 mu +=
L_I_(i_phase, i_spec) * x_i;
625 for (
int i_group = 0; i_group <
NUM_GROUP_; ++i_group) {
627 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec) {
629 V_IK_(i_phase, i_spec, i_group) *
X_I_(i_phase, i_spec);
631 X_K_(i_group) += v_ik_x_i;
635 for (
int i_group = 0; i_group <
NUM_GROUP_; ++i_group) {
636 X_K_(i_group) *= c_xX;
637 Pi +=
Q_K_(i_group) *
X_K_(i_group);
641 for (
int i_group = 0; i_group <
NUM_GROUP_; ++i_group)
645 for (
int i_group = 0; i_group <
NUM_GROUP_; ++i_group) {
647 for (
int j_group = 0; j_group <
NUM_GROUP_; ++j_group)
660 for (
int j = 0; j <
NUM_SPEC_(i_phase); ++j) {
662 double x_j =
X_I_(i_phase, j);
666 Phi_j =
R_I_(i_phase, j) * x_j / sigma;
670 Theta_j =
Q_I_(i_phase, j) * x_j / tau;
673 double lngammaC_j = 0.0;
674 if (
X_I_(i_phase, j) > 0.0) {
675 lngammaC_j = log(Phi_j / x_j) +
676 5.0 *
Q_I_(i_phase, j) * log(Theta_j / Phi_j) +
677 L_I_(i_phase, j) - Phi_j / x_j * mu;
681 double lngammaR_j = 0.0;
683 lngammaR_j +=
V_IK_(i_phase, j, k) *
688 double gamma_j = exp(lngammaC_j + lngammaR_j);
691 double dx_j_dc_i, dPhi_j_dc_i, dTheta_j_dc_i;
692 double dmu_dc_i, dlngammaC_j_dc_i;
693 for (
int i = 0; i <
NUM_SPEC_(i_phase); ++i) {
696 dx_j_dc_i = 1.0 - x_j;
697 dPhi_j_dc_i = sigma - x_j *
R_I_(i_phase, i);
698 dTheta_j_dc_i = tau - x_j *
Q_I_(i_phase, i);
701 dPhi_j_dc_i = -x_j *
R_I_(i_phase, i);
702 dTheta_j_dc_i = -x_j *
Q_I_(i_phase, i);
704 double MWimT_inv = 1.0 / (
MW_I_(i_phase, i) * m_T);
705 dx_j_dc_i *= MWimT_inv;
706 dPhi_j_dc_i *=
R_I_(i_phase, j) * MWimT_inv / sigma / sigma;
707 dTheta_j_dc_i *=
Q_I_(i_phase, j) * MWimT_inv / tau / tau;
709 dmu_dc_i = MWimT_inv * (
L_I_(i_phase, i) - mu);
713 dPhi_j_dc_i / Phi_j - dx_j_dc_i / x_j +
714 5.0 *
Q_I_(i_phase, j) *
715 (dTheta_j_dc_i / Theta_j - dPhi_j_dc_i / Phi_j) -
716 dPhi_j_dc_i * mu / x_j - Phi_j / x_j * dmu_dc_i +
717 Phi_j * mu / x_j / x_j * dx_j_dc_i;
722 double sumQnvn_i = 0.0;
724 sumQnvn_i +=
Q_K_(n) *
V_IK_(i_phase, i, n);
727 Q_K_(m) * c_xX * MWimT_inv / Pi / Pi *
728 (Pi *
V_IK_(i_phase, i, m) -
X_K_(m) * sumQnvn_i);
732 double dlngammaR_j_dc_i = 0.0;
736 double dlnGamma_k_dc_i = 0.0;
746 dlnGamma_k_dc_i *= -
Q_K_(k);
748 dlngammaR_j_dc_i +=
V_IK_(i_phase, j, k) * dlnGamma_k_dc_i;
752 double dgamma_j_dc_i =
753 gamma_j * x_j * (dlngammaC_j_dc_i + dlngammaR_j_dc_i) +
758 J[
JAC_ID_(i_phase, i_instance, j, i)] += dgamma_j_dc_i;
772 double *sub_model_float_data) {
773 int *int_data = sub_model_int_data;
774 double *float_data = sub_model_float_data;
776 printf(
"\n\nUNIFAC sub model\n\n");
777 printf(
"\nint_data");
778 for (
int i = 0; i <
INT_DATA_SIZE_; i++) printf(
" %d", int_data[i]);
779 printf(
"\nfloat_data");
782 printf(
"\nNumber of UNIFAC groups %d",
NUM_GROUP_);
783 printf(
"\n*** General group data ***");
784 for (
int i_group = 0; i_group <
NUM_GROUP_; ++i_group) {
785 printf(
"\nGroup %d:", i_group);
786 printf(
"\n Q_K: %le R_K: %le X_k: %le",
Q_K_(i_group),
R_K_(i_group),
788 printf(
"\n Xi_M: %le ln(Gamma_k): %le",
XI_M_(i_group),
791 printf(
"\n A_MN (by group):");
792 for (
int j_group = 0; j_group <
NUM_GROUP_; ++j_group)
793 printf(
" %le",
A_MN_(i_group, j_group));
795 printf(
"\n\n*** Phase data ***");
797 printf(
"\nPhase %d:", i_phase);
799 printf(
"\n Number of species: %d",
NUM_SPEC_(i_phase));
800 printf(
"\n Species ids:");
801 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec)
802 printf(
" %d",
SPEC_ID_(i_phase, i_spec));
803 printf(
"\n ** Instance data **");
805 printf(
"\n Instance %d:", i_inst);
807 printf(
"\n Gamma ids:");
808 for (
int i_gamma = 0; i_gamma <
NUM_SPEC_(i_phase); ++i_gamma)
811 printf(
"\n Species ids:");
812 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec)
815 printf(
"\n Jacobian ids:");
816 for (
int i_gamma = 0; i_gamma <
NUM_SPEC_(i_phase); ++i_gamma)
817 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec)
818 printf(
" J[%d][%d] = %d", i_gamma, i_spec,
819 JAC_ID_(i_phase, i_inst, i_gamma, i_spec));
821 printf(
"\n R_I (by species):");
822 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec)
823 printf(
" %le",
R_I_(i_phase, i_spec));
824 printf(
"\n Q_I (by species):");
825 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec)
826 printf(
" %le",
Q_I_(i_phase, i_spec));
827 printf(
"\n L_I (by species):");
828 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec)
829 printf(
" %le",
L_I_(i_phase, i_spec));
830 printf(
"\n MW_I (by species):");
831 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec)
832 printf(
" %le",
MW_I_(i_phase, i_spec));
833 printf(
"\n X_I (by species):");
834 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec)
835 printf(
" %le",
X_I_(i_phase, i_spec));
836 printf(
"\n ** Phase-specific group data **");
837 for (
int i_group = 0; i_group <
NUM_GROUP_; ++i_group) {
838 printf(
"\n Group %d:", i_group);
839 printf(
"\n v_ik (by species):");
840 for (
int i_spec = 0; i_spec <
NUM_SPEC_(i_phase); ++i_spec)
841 printf(
" %d",
V_IK_(i_phase, i_spec, i_group));
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.
void sub_model_UNIFAC_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_UNIFAC_update_ids(int *sub_model_int_data, double *sub_model_float_data, int *deriv_ids, Jacobian jac)
Update stored ids for elements used within a row of the Jacobian matrix.
#define LN_GAMMA_IK_(p, i, k)
void sub_model_UNIFAC_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 DTHETA_M_DC_I_(m)
#define PHASE_INST_ID_(p, c)
void sub_model_UNIFAC_get_used_jac_elem(int *sub_model_int_data, double *sub_model_float_data, Jacobian *jac)
Get the Jacobian elements used for a particular row of the matrix.
void sub_model_UNIFAC_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 NUM_PHASE_INSTANCE_(p)
#define NUM_UNIQUE_PHASE_
void sub_model_UNIFAC_print(int *sub_model_int_data, double *sub_model_float_data)
Print the sub model data.
#define JAC_ID_(p, c, j, i)