iphreeqc/phreeqcpp/basicsubs.cpp
Darth Vader 1b2eb6ca0d Squashed 'src/' changes from 6e248c34..81f180a0
81f180a0 Fixed bugs in inverse
6d575967 strcpy_safe and strcat_safe
6d98c4e1 trying different header files
72796f15 added <cstring>
e8481607 warnings, strcat, strcpy
988bdee0 Try using goto(s)
9b10ce3f Try updated logical expression
812061be Turn off optimizing on k_temp

git-subtree-dir: src
git-subtree-split: 81f180a069285bcb4d180c860664b4b2a193854d
2023-11-16 05:04:39 +00:00

4207 lines
107 KiB
C++

#include "Phreeqc.h"
#include "phqalloc.h"
#include "Utils.h"
#include "NameDouble.h"
#include "PBasic.h"
#include "Exchange.h"
#include "GasPhase.h"
#include "PPassemblage.h"
#include "SSassemblage.h"
#include "cxxKinetics.h"
#include "Solution.h"
#include "Parser.h"
#if defined(PHREEQCI_GUI)
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#endif
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
activity(const char* species_name)
/* ---------------------------------------------------------------------- */
{
class species* s_ptr;
LDBLE a;
s_ptr = s_search(species_name);
if (s_ptr == s_h2o)
{
a = pow((LDBLE)10., s_h2o->la);
}
else if (s_ptr == s_eminus)
{
a = pow((LDBLE)10., s_eminus->la);
}
else if (s_ptr == NULL || s_ptr->in == FALSE)
{
a = 1e-99;
}
else
{
a = pow((LDBLE)10., s_ptr->lm + s_ptr->lg);
}
return (a);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
activity_coefficient(const char* species_name)
/* ---------------------------------------------------------------------- */
{
class species* s_ptr;
LDBLE g, dum = 0.0;
s_ptr = s_search(species_name);
if (s_ptr != NULL && s_ptr->in != FALSE && ((s_ptr->type < EMINUS) || (s_ptr->type == EX) || (s_ptr->type == SURF)))
{
if (s_ptr->type == EX && s_ptr->equiv && s_ptr->alk)
dum = log10(s_ptr->equiv / s_ptr->alk);
g = pow((LDBLE)10., s_ptr->lg - dum);
}
else
{
g = 0;
}
return (g);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
log_activity_coefficient(const char* species_name)
/* ---------------------------------------------------------------------- */
{
class species* s_ptr;
LDBLE g, dum = 0.0;
s_ptr = s_search(species_name);
if (s_ptr != NULL && s_ptr->in != FALSE && ((s_ptr->type < EMINUS) || (s_ptr->type == EX) || (s_ptr->type == SURF)))
{
if (s_ptr->type == EX && s_ptr->equiv && s_ptr->alk)
dum = log10(s_ptr->equiv / s_ptr->alk);
g = s_ptr->lg - dum;
}
else
{
g = 0;
}
return (g);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
aqueous_vm(const char* species_name)
/* ---------------------------------------------------------------------- */
{
class species* s_ptr;
LDBLE g;
s_ptr = s_search(species_name);
if (s_ptr != NULL && s_ptr->in != FALSE && s_ptr->type < EMINUS)
{
g = s_ptr->logk[vm_tc];
}
else
{
g = 0;
}
return (g);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
phase_vm(const char* phase_name)
/* ---------------------------------------------------------------------- */
{
class phase* phase_ptr;
int l;
LDBLE g;
phase_ptr = phase_bsearch(phase_name, &l, FALSE);
if (phase_ptr == NULL)
{
g = 0.0;
}
else
{
g = phase_ptr->logk[vm0];
}
return (g);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
sa_declercq(double sa_type, double Sa, double d, double m, double m0, double gfw)
/* ---------------------------------------------------------------------- */
{
if (sa_type == 0)
{
// surface-area-calculation-Fixed_Surface
return Sa;
}
else if (sa_type == 1)
// surface-area-calculation-Square
{
double mass0 = m0 * gfw;
double V0 = mass0 / d;
double St0 = mass0 * Sa; // total surface
double a0 = pow(V0, 1.0 / 3.0); // side length
double Sp0 = 6.0 * a0 * a0; // surface particle
double np = St0 / Sp0; // number of particles
double RATS = Sa / St0;
double mass = m * gfw;
double V = mass / d;
double a = pow(V, 1.0 / 3.0);
double St = 6.0 * a * a * np;
return St * RATS; // total current surface
}
else if (sa_type == 2)
{
//double pi = 3.14159265359;
double mass0 = m0 * gfw;
double V0 = mass0 / d; // volume
double St0 = mass0 * Sa; // total surface
double a0 = pow(3.0 * V0 / (4.0 * pi), 1.0 / 3.0); // ((3*V0)/(4 * 3.14159265359))^(1/3)
double Sp0 = (4.0 * pi) * a0 * a0; // surface particle
double np = St0 / Sp0; // number of particles
double RATS = Sa / St0;
double mass = m * gfw;
double V = mass / d;
double a = pow(3.0 * V / (4.0 * pi), 1.0 / 3.0); //((3*V)/(4 * 3.14159265359))^(1/3)
double St = 4.0 * pi * a * a * np;
return St * RATS; // total current surface
}
error_string = sformatf("Unknown surface area type in SA_DECLERCQ %d.", (int)sa_type);
error_msg(error_string, CONTINUE);
input_error++;
return (MISSING);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
diff_c(const char* species_name)
/* ---------------------------------------------------------------------- */
{
class species* s_ptr;
LDBLE ka, l_z, Dw, ff, sqrt_mu;
sqrt_mu = sqrt(mu_x);
s_ptr = s_search(species_name);
//LDBLE g;
//if (s_ptr != NULL /*&& s_ptr->in != FALSE && s_ptr->type < EMINUS*/)
//{
// g = s_ptr->dw;
// if (s_ptr->dw_t)
// g *= exp(s_ptr->dw_t / tk_x - s_ptr->dw_t / 298.15);
// g *= viscos_0_25 / viscos * tk_x / 298.15;
//}
//else
//{
// g = 0;
//}
//return (g);
if (s_ptr == NULL)
return(0);
if ((Dw = s_ptr->dw) == 0)
{
if (correct_Dw)
Dw = default_Dw;
else
return(0);
}
if ((l_z = fabs(s_ptr->z)) == 0)
{
//l_z = 1; // only a 1st approximation for correct_Dw in electrical field
}
else
{
if (s_ptr->dw_a2)
ka = DH_B * s_ptr->dw_a2 * sqrt_mu / (1 + pow(mu_x, 0.75));
else
ka = DH_B * 4.73 * sqrt_mu / (1 + pow(mu_x, 0.75));
if (s_ptr->dw_a)
{
ff = exp(-s_ptr->dw_a * DH_A * l_z * sqrt_mu / (1 + ka));
//if (print_viscosity && s_ptr->dw_a_visc)
// ff *= pow((viscos_0 / viscos), s_ptr->dw_a_visc);
}
else
{
ff = exp(-1.6 * DH_A * l_z * sqrt_mu / (1 + ka));
}
Dw *= ff;
}
if (tk_x != 298.15 && s_ptr->dw_t)
Dw *= exp(s_ptr->dw_t / tk_x - s_ptr->dw_t / 298.15);
s_ptr->dw_corr = Dw;
return (Dw * viscos_0_25 / viscos_0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
setdiff_c(const char* species_name, double d)
/* ---------------------------------------------------------------------- */
{
class species* s_ptr;
LDBLE ka, l_z, Dw, ff, sqrt_mu;
sqrt_mu = sqrt(mu_x);
s_ptr = s_search(species_name);
//LDBLE g;
//s_ptr = s_search(species_name);
//if (s_ptr != NULL)
//{
// s_ptr->dw = d;
// g = s_ptr->dw;
// if (s_ptr->dw_t)
// g *= exp(s_ptr->dw_t / tk_x - s_ptr->dw_t / 298.15);
// g *= viscos_0_25 / viscos * tk_x / 298.15;;
//}
//else
//{
// g = 0;
//}
//return (g);
if (s_ptr == NULL)
return(0);
Dw = s_ptr->dw = d;
if ((l_z = fabs(s_ptr->z)) == 0)
{
//l_z = 1; // only a 1st approximation for correct_Dw in electrical field
}
else
{
if (s_ptr->dw_a2)
ka = DH_B * s_ptr->dw_a2 * sqrt_mu / (1 + pow(mu_x, 0.75));
else
ka = DH_B * 4.73 * sqrt_mu / (1 + pow(mu_x, 0.75));
if (s_ptr->dw_a)
{
ff = exp(-s_ptr->dw_a * DH_A * l_z * sqrt_mu / (1 + ka));
//if (print_viscosity && s_ptr->dw_a_visc)
// ff *= pow((viscos_0 / viscos), s_ptr->dw_a_visc);
}
else
{
ff = exp(-1.6 * DH_A * l_z * sqrt_mu / (1 + ka));
}
Dw *= ff;
}
if (tk_x != 298.15 && s_ptr->dw_t)
Dw *= exp(s_ptr->dw_t / tk_x - s_ptr->dw_t / 298.15);
s_ptr->dw_corr = Dw;
return (Dw * viscos_0_25 / viscos_0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
calc_SC(void)
/* ---------------------------------------------------------------------- */
{
//int i;
//LDBLE lm, a, l_z, Dw, SC, ff;
//SC = 0;
# ifdef SKIP
for (i = 0; i < count_species_list; i++)
{
if (species_list[i].s->type == EX)
continue;
if (species_list[i].s->type == SURF)
continue;
if (i > 0
&& strcmp(species_list[i].s->name,
species_list[i - 1].s->name) == 0)
continue;
if (species_list[i].s == s_h2o)
continue;
if ((Dw = species_list[i].s->dw) == 0)
continue;
if ((l_z = fabs(species_list[i].s->z)) == 0)
continue;
lm = species_list[i].s->lm;
if (lm > -9)
{
ff = (mu_x < .36 * l_z ? 0.6 / sqrt(l_z) : sqrt(mu_x) / l_z);
ff *= species_list[i].s->lg;
if (ff > 0) ff = 0;
a = under(lm + ff);
if (species_list[i].s->dw_t)
Dw *= exp(species_list[i].s->dw_t / tk_x - species_list[i].s->dw_t / 298.15); // the viscosity multiplier is done in SC
SC += a * l_z * l_z * Dw;
}
}
SC *= 1e7 * F_C_MOL * F_C_MOL / (R_KJ_DEG_MOL * 298160.0);
/* correct for temperature dependency...
SC_T = SC_298 * (Dw_T / T) * (298 / Dw_298) and
Dw_T = Dw_298 * (T / 298) * (viscos_298 / viscos_T) give:
SC_T = SC_298 * (viscos_298 / viscos_T)
*/
SC *= viscos_0_25 / viscos;
return (SC);
//# endif
for (i = 0; i < (int)this->s_x.size(); i++)
{
if (s_x[i]->type != AQ && s_x[i]->type != HPLUS)
continue;
if ((Dw = s_x[i]->dw) == 0)
continue;
if ((l_z = fabs(s_x[i]->z)) == 0)
continue;
lm = s_x[i]->lm;
if (lm > -9)
{
ff = (mu_x < .36 * l_z ? 0.6 / sqrt(l_z) : sqrt(mu_x) / l_z);
ff *= s_x[i]->lg;
if (ff > 0) ff = 0;
a = under(lm + ff);
if (s_x[i]->dw_t)
Dw *= exp(s_x[i]->dw_t / tk_x - s_x[i]->dw_t / 298.15); // the viscosity multiplier is done in SC
SC += a * l_z * l_z * Dw;
}
}
SC *= 1e7 * F_C_MOL * F_C_MOL / (R_KJ_DEG_MOL * 298160.0);
/* correct for temperature dependency...
SC_T = SC_298 * (Dw_T / T) * (298 / Dw_298) and
Dw_T = Dw_298 * (T / 298) * (viscos_298 / viscos_T) give:
SC_T = SC_298 * (viscos_298 / viscos_T)
*/
SC *= viscos_0_25 / viscos;
return (SC);
# endif
int i;
LDBLE ka, l_z, Dw, ff, sqrt_mu;
sqrt_mu = sqrt(mu_x);
SC = 0;
//LDBLE ta1, ta2, ta3, ta4;
//for (i = 0; i < (int)this->s_x.size(); i++)
//{
// // ** for optimizing, get numbers from -analyt for H+ = H+...
// if (!strcmp(s_x[i]->name, "H+"))
// {
// ta1 = s_x[i]->logk[2] * 1e15;
// ta2 = s_x[i]->logk[3] * 1e15;
// ta3 = s_x[i]->logk[4] * 1e15;
// ta4 = s_x[i]->logk[5] * 1e15;
// break;
// }
//}
for (i = 0; i < (int)this->s_x.size(); i++)
{
if (s_x[i]->type != AQ && s_x[i]->type != HPLUS)
continue;
if ((Dw = s_x[i]->dw) == 0)
{
if (correct_Dw)
Dw = default_Dw;
else
continue;
}
if (s_x[i]->lm < min_dif_LM)
continue;
if ((l_z = fabs(s_x[i]->z)) == 0)
{
//l_z = 1; // only a 1st approximation for correct_Dw in electrical field
}
else
{
if (s_x[i]->dw_a2)
ka = DH_B * s_x[i]->dw_a2 * sqrt_mu / (1 + pow(mu_x, 0.75));
else
{
ka = DH_B * 4.73 * sqrt_mu / (1 + pow(mu_x, 0.75));
//ka = DH_B * ta1 * sqrt_mu / (1 + pow(mu_x, ta2));
//ka = DH_B * ta1 * sqrt_mu / (1 + mu_x / ta2);
}
if (s_x[i]->dw_a)
{
ff = exp(-s_x[i]->dw_a * DH_A * l_z * sqrt_mu / (1 + ka));
//if (print_viscosity && s_x[i]->dw_a_visc)
// ff *= pow((viscos_0 / viscos), s_x[i]->dw_a_visc);
}
else
{
ff = exp(-1.6 * DH_A * l_z * sqrt_mu / (1 + ka));
//ff = exp(-ta3 * DH_A * l_z * sqrt_mu / (1 + ka));
}
Dw *= ff;
}
if (tk_x != 298.15)
{
if (s_x[i]->dw_t)
Dw *= exp(s_x[i]->dw_t / tk_x - s_x[i]->dw_t / 298.15);
//else
//{
// Dw *= exp(ta1 / tk_x - ta1 / 298.15);
//}
}
s_x[i]->dw_corr = Dw;
s_x[i]->dw_t_SC = s_x[i]->moles / mass_water_aq_x * l_z * l_z * Dw;
SC += s_x[i]->dw_t_SC;
}
SC *= 1e7 * F_C_MOL * F_C_MOL / (R_KJ_DEG_MOL * 298150.0);
/* correct for viscosity dependency...
SC_T = SC_298 * (viscos_298 / viscos_T)
*/
SC *= viscos_0_25 / viscos_0;
return (SC);
}
#ifdef SKIP
/*Debye-Onsager according to Robinson and Stokes, 1954, JACS 75, 1991,
but with sqrt charge multiplier for B2 and mu^ff dependent ka */
LDBLE q, B1, B2, m_plus, m_min, eq_plus, eq_min, eq_dw_plus, eq_dw_min, Sum_m_dw, z_plus, z_min, t1, t2, Dw_SC;
m_plus = m_min = eq_plus = eq_min = eq_dw_plus = eq_dw_min = Sum_m_dw = z_plus = z_min = 0;
SC = 0;
for (i = 0; i < (int)this->s_x.size(); i++)
{
if (s_x[i]->type != AQ && s_x[i]->type != HPLUS)
continue;
if ((l_z = s_x[i]->z) == 0)
continue;
if ((lm = s_x[i]->lm) < -9)
continue;
if ((Dw = s_x[i]->dw) == 0)
Dw = 1e-9;
if (s_x[i]->dw_t)
Dw *= exp(s_x[i]->dw_t / tk_x - s_x[i]->dw_t / 298.15); // the viscosity multiplier cancels in q...
if (l_z > 0)
{
m_plus += s_x[i]->moles;
t1 = s_x[i]->moles * l_z;
eq_plus += t1;
eq_dw_plus += t1 * Dw;
Sum_m_dw += s_x[i]->moles * Dw;
}
else
{
m_min += s_x[i]->moles;
t1 = s_x[i]->moles * l_z;
eq_min -= t1;
eq_dw_min -= t1 * Dw;
Sum_m_dw += s_x[i]->moles * Dw;
}
}
// Falkenhagen, q = (Sum(z1 * m1*Dw1) + Sum(z2 *m2*Dw2)) / ((Sum(m1*Dw1) + Sum(m2*Dw2))(av_z1 + av_z2))
z_plus = eq_plus / m_plus; // |av_z1|
z_min = eq_min / m_min; // |av_z2|
q = (eq_dw_plus + eq_dw_min) / (Sum_m_dw * (z_min + z_plus));
t1 = 1.60218e-19 * 1.60218e-19 / (6 * pi);
B1 = t1 / (2 * 8.8542e-12 * eps_r * 1.38066e-23 * tk_x) *
q / (1 + sqrt(q)) * DH_B * 1e10 * z_plus * z_min; // DH_B is per Angstrom (*1e10)
t2 = viscos_0; // (1 - 0.5) * viscos_0 + 0.5 * viscos;
B2 = t1 * AVOGADRO / t2 * DH_B * 1e17; // DH_B per Angstrom (*1e10), viscos in mPa.s (*1e3), B2 in cm2 (*1e4)
Dw_SC = viscos_0_25 / t2 * 1e4 * F_C_MOL * F_C_MOL / (R_KJ_DEG_MOL * 298160.0);
for (i = 0; i < (int)this->s_x.size(); i++)
{
if (s_x[i]->type != AQ && s_x[i]->type != HPLUS)
continue;
if ((l_z = fabs(s_x[i]->z)) == 0)
continue;
if ((lm = s_x[i]->lm) < -9)
continue;
if ((Dw = s_x[i]->dw) == 0)
Dw = 1e-9;
Dw *= Dw_SC;
if (s_x[i]->dw_t)
Dw *= exp(s_x[i]->dw_t / tk_x - s_x[i]->dw_t / 298.15); // the viscosity factor is in Dw_SC
a = (s_x[i]->dw_a ? s_x[i]->dw_a : 3.5);
ka = DH_B * a;
if (s_x[i]->dw_a2)
ka *= pow((double)mu_x, s_x[i]->dw_a2);
else
ka *= sqrt_mu;
// Falkenhagen...
//SC += under(lm) * l_z * l_z * (Dw - B2 * l_z * sqrt_mu / (1 + ka)) * (1 - B1 * sqrt_mu /
// ((1 + ka) * (1 + ka * sqrt(q) + ka * ka / 6)));
t1 = (Dw - (B1 * Dw + B2) * sqrt_mu / (1 + ka));
//t1 = (Dw - (B1 * Dw + B2 * sqrt(l_z)) * sqrt_mu / (1 + ka));
//t1 = (Dw - (B1 * Dw + B2 * l_z * l_z) * sqrt_mu / (1 + ka));
if (t1 > 0)
SC += under(lm) * l_z * l_z * t1;
}
return (SC * 1e3);
#endif
/* VP: Density Start */
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
calc_dens(void)
/* ---------------------------------------------------------------------- */
{
/*
* Calculates density based on the formulas and parameters from Millero,
* 2000.
*
* Millero, F.J. (2000) The equation of state of lakes. Aquatic geochemistry
* volume 6, pages 1-17
*/
int i;
LDBLE M_T, /*rho_new,*/ gfw;
/* 2 options: original VP, assign the volumes of species with zero molar volume to their master species,
but this doubles counts of complexes with -Vm defined. And, cation-OH and H-anion
complexes are counted once. Also, must add H+ and OH-... */
//class species *s_ptr;
//V_solutes = M_T = 0.0;
//for (i = 0; i < count_species_list; i++)
//{
// if (species_list[i].s->type != AQ && species_list[i].s->type != HPLUS)
// continue;
// //if (species_list[i].master_s->secondary != NULL)
// // gfw = species_list[i].master_s->secondary->gfw;
// //else
// // gfw = species_list[i].master_s->primary->gfw;
// /* OH-... */
// if (!strcmp(species_list[i].s->name, "OH-"))
// s_ptr = s_search("OH-");
// else if (species_list[i].s->logk[vm_tc] == 0)
// {
// s_ptr = species_list[i].master_s;
// if (s_ptr->secondary)
// gfw = s_ptr->secondary->gfw;
// else
// gfw = s_ptr->primary->gfw;
// }
// else
// {
// s_ptr = species_list[i].s;
// compute_gfw(species_list[i].s->name, &gfw);
// }
// /* Special case: CO3-2 species */
// if (strcmp(s_ptr->name, "CO3-2") == 0)
// {
// if (strstr(species_list[i].s->name, "HCO3") != NULL)
// {
// s_ptr = s_search("HCO3-");
// } else if (strstr(species_list[i].s->name, "CO3") != NULL)
// {
// compute_gfw("CO3-2", &gfw);
// }
// }
// if (!gfw || !strcmp(species_list[i].s->name, "CO2")) /* CO2, H+ and OH- */
// compute_gfw(species_list[i].s->name, &gfw);
// M_T += (species_list[i].s->moles * gfw);
// V_solutes += species_list[i].s->moles * s_ptr->logk[vm_tc];
//}
/* 2nd option, use species_x, vm = 0 for complexes with undefined volume... */
V_solutes = M_T = 0.0;
for (i = 0; i < (int)this->s_x.size(); i++)
{
if (s_x[i]->type != AQ && s_x[i]->type != HPLUS)
continue;
//compute_gfw(s_x[i]->name, &gfw);
gfw = s_x[i]->gfw;
M_T += s_x[i]->moles * gfw;
V_solutes += s_x[i]->moles * s_x[i]->logk[vm_tc];
}
/* If pure water then return rho_0 */
if (M_T == 0)
return rho_0;
else
return rho_0 * (1e3 + M_T / mass_water_aq_x) / (rho_0 * V_solutes / mass_water_aq_x + 1e3);
//M_T /= 1e3;
//solution_mass = mass_water_aq_x + M_T;
//V_solutes = M_T - rho_0 * V_solutes / 1e3;
//rho_new = halve(f_rho, 0.5, 2.0, 1e-7);
//if (!PHR_ISFINITE(rho_new) || rho_new > 1.99999) rho_new = 1.99999;
//return rho_new;
}
/* VP: Density End */
/* DP: Function for interval halving */
LDBLE Phreeqc::
f_rho(LDBLE rho_old, void* cookie)
/* ---------------------------------------------------------------------- */
{
LDBLE rho = 1.0;
Phreeqc* pThis;
pThis = (Phreeqc*)cookie;
pThis->solution_volume = pThis->solution_mass / rho_old;
if (pThis->solution_volume != 0)
{
rho = pThis->V_solutes / pThis->solution_volume;
}
rho = rho + pThis->rho_0;
return (rho - rho_old);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
calc_solution_volume(void)
/* ---------------------------------------------------------------------- */
{
/*
* Calculates solution volume based on sum of mass of element plus density
*/
LDBLE total_mass = 0;
LDBLE gfw;
//compute_gfw("H", &gfw);
gfw = s_hplus->primary->gfw;
total_mass = total_h_x * gfw;
//compute_gfw("O", &gfw);
gfw = s_h2o->primary->gfw;
total_mass += total_o_x * gfw;
for (int i = 0; i < (int)master.size(); i++)
{
if (master[i]->s->type != AQ) continue;
class master* master_ptr = master[i];
if (master_ptr->primary == TRUE && strcmp(master_ptr->elt->name, "Alkalinity"))
{
total_mass += master_ptr->total_primary * master_ptr->elt->gfw;
}
}
LDBLE rho = calc_dens();
LDBLE vol = 1e-3 * total_mass / rho;
return (vol);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
calc_logk_n(const char* name)
/* ---------------------------------------------------------------------- */
{
char token[MAX_LENGTH];
int i;
LDBLE lk;
class logk* logk_ptr;
LDBLE l_logk[MAX_LOG_K_INDICES];
class name_coef add_logk;
std::vector<class name_coef> add_logk_v;
for (i = 0; i < MAX_LOG_K_INDICES; i++)
{
l_logk[i] = 0.0;
}
Utilities::strcpy_safe(token, MAX_LENGTH, name);
logk_ptr = logk_search(token);
if (logk_ptr != NULL)
{
add_logk.name = token;
add_logk.coef = 1.0;
add_logk_v.push_back(add_logk);
add_other_logk(l_logk, add_logk_v);
lk = k_calc(l_logk, tk_x, patm_x * PASCAL_PER_ATM);
return (lk);
}
return (-999.99);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
calc_logk_p(const char* name)
/* ---------------------------------------------------------------------- */
{
int i, j;
char token[MAX_LENGTH];
class phase* phase_ptr;
LDBLE lk = -999.9;
LDBLE l_logk[MAX_LOG_K_INDICES];
Utilities::strcpy_safe(token, MAX_LENGTH, name);
phase_ptr = phase_bsearch(token, &j, FALSE);
if (phase_ptr != NULL)
{
CReaction* reaction_ptr;
if (phase_ptr->replaced)
reaction_ptr = &phase_ptr->rxn_s;
else
reaction_ptr = &phase_ptr->rxn;
/*
* Print saturation index
*/
reaction_ptr->logk[delta_v] = calc_delta_v(*reaction_ptr, true) -
phase_ptr->logk[vm0];
if (reaction_ptr->logk[delta_v])
mu_terms_in_logk = true;
for (i = 0; i < MAX_LOG_K_INDICES; i++)
{
l_logk[i] = 0.0;
}
//lk = k_calc(reaction_ptr->logk, tk_x, patm_x * PASCAL_PER_ATM);
select_log_k_expression(reaction_ptr->logk, l_logk);
add_other_logk(l_logk, phase_ptr->add_logk);
lk = k_calc(l_logk, tk_x, patm_x * PASCAL_PER_ATM);
}
return (lk);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
calc_logk_s(const char* name)
/* ---------------------------------------------------------------------- */
{
int i;
char token[MAX_LENGTH];
class species* s_ptr;
LDBLE lk, l_logk[MAX_LOG_K_INDICES];
Utilities::strcpy_safe(token, MAX_LENGTH, name);
s_ptr = s_search(token);
if (s_ptr != NULL)
{
//if (s_ptr->logk[vm_tc])
/* calculate delta_v for the reaction... */
s_ptr->logk[delta_v] = calc_delta_v(*&s_ptr->rxn, false);
for (i = 0; i < MAX_LOG_K_INDICES; i++)
{
l_logk[i] = 0.0;
}
select_log_k_expression(s_ptr->logk, l_logk);
mu_terms_in_logk = true;
add_other_logk(l_logk, s_ptr->add_logk);
lk = k_calc(l_logk, tk_x, patm_x * PASCAL_PER_ATM);
return (lk);
}
return (-999.99);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
dh_a0(const char* name)
/* ---------------------------------------------------------------------- */
{
char token[MAX_LENGTH];
class species* s_ptr;
double a = -999.99;
Utilities::strcpy_safe(token, MAX_LENGTH, name);
s_ptr = s_search(token);
if (s_ptr != NULL)
{
a = s_ptr->dha;
}
return (a);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
dh_bdot(const char* name)
/* ---------------------------------------------------------------------- */
{
char token[MAX_LENGTH];
class species* s_ptr;
double b = -999.99;
if (llnl_temp.size() > 0)
{
b = bdot_llnl;
}
else
{
Utilities::strcpy_safe(token, MAX_LENGTH, name);
s_ptr = s_search(token);
if (s_ptr != NULL)
{
b = s_ptr->dhb;
}
}
return (b);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
calc_deltah_p(const char* name)
/* ---------------------------------------------------------------------- */
{
int i, j;
char token[MAX_LENGTH];
class phase* phase_ptr;
LDBLE lkm, lkp;
LDBLE l_logk[MAX_LOG_K_INDICES];
double dh = -999.99;
Utilities::strcpy_safe(token, MAX_LENGTH, name);
phase_ptr = phase_bsearch(token, &j, FALSE);
if (phase_ptr != NULL)
{
CReaction* reaction_ptr;
if (phase_ptr->replaced)
reaction_ptr = &phase_ptr->rxn_s;
else
reaction_ptr = &phase_ptr->rxn;
/*
* Print saturation index
*/
reaction_ptr->logk[delta_v] = calc_delta_v(*reaction_ptr, true) -
phase_ptr->logk[vm0];
if (reaction_ptr->logk[delta_v])
mu_terms_in_logk = true;
for (i = 0; i < MAX_LOG_K_INDICES; i++)
{
l_logk[i] = 0.0;
}
//lk = k_calc(reaction_ptr->logk, tk_x, patm_x * PASCAL_PER_ATM);
select_log_k_expression(reaction_ptr->logk, l_logk);
add_other_logk(l_logk, phase_ptr->add_logk);
lkm = k_calc(l_logk, tk_x - 1.0, patm_x * PASCAL_PER_ATM);
lkp = k_calc(l_logk, tk_x + 1.0, patm_x * PASCAL_PER_ATM);
dh = (lkp - lkm) / 2.0 * LOG_10 * R_KJ_DEG_MOL * pow(tk_x, 2.0);
}
return (dh);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
calc_deltah_s(const char* name)
/* ---------------------------------------------------------------------- */
{
int i;
char token[MAX_LENGTH];
class species* s_ptr;
LDBLE lkm, lkp, l_logk[MAX_LOG_K_INDICES];
double dh = -999.99;
Utilities::strcpy_safe(token, MAX_LENGTH, name);
s_ptr = s_search(token);
if (s_ptr != NULL)
{
/* calculate delta_v for the reaction... */
s_ptr->logk[delta_v] = calc_delta_v(*&s_ptr->rxn, false);
for (i = 0; i < MAX_LOG_K_INDICES; i++)
{
l_logk[i] = 0.0;
}
select_log_k_expression(s_ptr->logk, l_logk);
mu_terms_in_logk = true;
add_other_logk(l_logk, s_ptr->add_logk);
lkm = k_calc(l_logk, tk_x - 1.0, patm_x * PASCAL_PER_ATM);
lkp = k_calc(l_logk, tk_x + 1.0, patm_x * PASCAL_PER_ATM);
dh = (lkp - lkm) / 2.0 * LOG_10 * R_KJ_DEG_MOL * pow(tk_x, 2.0);
return (dh);
}
return (0.0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
calc_surface_charge(const char* surface_name)
/* ---------------------------------------------------------------------- */
{
char token[MAX_LENGTH], token1[MAX_LENGTH];
const char* cptr;
int i, j, k;
LDBLE charge;
class rxn_token_temp* token_ptr;
class master* master_ptr;
/*
* Go through species, sum charge
*/
charge = 0;
for (k = 0; k < (int)this->s_x.size(); k++)
{
if (s_x[k]->type != SURF)
continue;
/*
* Match surface_name
*/
count_trxn = 0;
trxn_add(s_x[k]->rxn_s, 1.0, false); /* rxn_s is set in tidy_model */
for (i = 1; i < count_trxn; i++)
{
token_ptr = &(trxn.token[i]);
if (token_ptr->s->type != SURF)
continue;
master_ptr = trxn.token[i].s->primary;
Utilities::strcpy_safe(token, MAX_LENGTH, master_ptr->elt->name);
replace("_", " ", token);
cptr = token;
copy_token(token1, &cptr, &j);
if (strcmp(surface_name, token1) == 0)
{
charge += s_x[k]->moles * s_x[k]->z;
}
}
}
return (charge);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
diff_layer_total(const char* total_name, const char* surface_name)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in DDL layer
*/
cxxSurfaceCharge* surface_charge_ptr1;
std::string name, token, surface_name_local;
class master* master_ptr;
LDBLE mass_water_surface;
LDBLE molality, moles_excess, moles_surface, charge;
if (use.Get_surface_ptr() == NULL || (dl_type_x == cxxSurface::NO_DL &&
strcmp_nocase("psi", total_name) != 0 &&
strcmp_nocase("psi1", total_name) != 0 &&
strcmp_nocase("psi2", total_name) != 0 &&
strcmp_nocase("charge", total_name) != 0
&& strcmp_nocase("charge1",
total_name) != 0
&& strcmp_nocase("charge2",
total_name) != 0
&& strcmp_nocase("sigma",
total_name) != 0
&& strcmp_nocase("sigma1",
total_name) != 0
&& strcmp_nocase("sigma2",
total_name) != 0))
return (0);
/*
* Find surface...
*/
int j;
for (j = 0; j < count_unknowns; j++)
{
if (use.Get_surface_ptr()->Get_type() == cxxSurface::DDL || use.Get_surface_ptr()->Get_type() == cxxSurface::CCM)
{
if (x[j]->type != SURFACE_CB)
continue;
name = x[j]->master[0]->elt->name;
Utilities::replace("_psi", "", name);
}
else if (use.Get_surface_ptr()->Get_type() == cxxSurface::CD_MUSIC)
{
if (x[j]->type != SURFACE_CB)
continue;
name = x[j]->master[0]->elt->name;
Utilities::replace("_psi", "", name);
}
else
{
if (x[j]->type != SURFACE)
continue;
token = x[j]->master[0]->elt->name;
Utilities::replace("_", " ", token);
std::string::iterator b = token.begin();
std::string::iterator e = token.end();
CParser::copy_token(name, b, e);
}
if (surface_name != NULL)
{
if (strcmp(name.c_str(), surface_name) == 0)
break;
}
else
{
break;
}
}
if (j >= count_unknowns)
return (0);
surface_name_local = name;
/*
* Psi, charge, sigma
*/
if (strcmp_nocase("psi", total_name) == 0)
{
if (use.Get_surface_ptr()->Get_type() == cxxSurface::DDL || use.Get_surface_ptr()->Get_type() == cxxSurface::CCM)
{
return ((LDBLE)(x[j]->master[0]->s->la * 2 * R_KJ_DEG_MOL *
tk_x * LOG_10 / F_KJ_V_EQ));
}
else if (use.Get_surface_ptr()->Get_type() == cxxSurface::CD_MUSIC)
{
master_ptr = surface_get_psi_master(surface_name, SURF_PSI);
if (master_ptr != NULL)
{
return ((LDBLE)
(-master_ptr->s->la * R_KJ_DEG_MOL * tk_x * LOG_10 /
F_KJ_V_EQ));
}
else
{
return (0.0);
}
}
else
{
return (0);
}
}
else if (strcmp_nocase("psi1", total_name) == 0)
{
master_ptr = surface_get_psi_master(surface_name, SURF_PSI1);
if (master_ptr != NULL)
{
return ((LDBLE)
(-master_ptr->s->la * R_KJ_DEG_MOL * tk_x * LOG_10 /
F_KJ_V_EQ));
}
else
{
return (0.0);
}
}
else if (strcmp_nocase("psi2", total_name) == 0)
{
master_ptr = surface_get_psi_master(surface_name, SURF_PSI2);
if (master_ptr != NULL)
{
return ((LDBLE)
(-master_ptr->s->la * R_KJ_DEG_MOL * tk_x * LOG_10 /
F_KJ_V_EQ));
}
else
{
return (0.0);
}
}
else if (strcmp_nocase("charge", total_name) == 0)
{
if ((use.Get_surface_ptr()->Get_type() == cxxSurface::DDL || use.Get_surface_ptr()->Get_type() == cxxSurface::CCM) && dl_type_x == cxxSurface::NO_DL)
{
return ((LDBLE)(x[j]->f));
}
else if (use.Get_surface_ptr()->Get_type() == cxxSurface::CD_MUSIC)
{
cxxSurfaceCharge* charge_ptr = use.Get_surface_ptr()->Find_charge(x[j]->surface_charge);
return ((charge_ptr->Get_sigma0() *
(charge_ptr->Get_specific_area() *
charge_ptr->Get_grams()) / F_C_MOL));
}
else
{
return (calc_surface_charge(surface_name_local.c_str()));
}
}
else if (strcmp_nocase("charge1", total_name) == 0)
{
if (use.Get_surface_ptr()->Get_type() == cxxSurface::CD_MUSIC)
{
cxxSurfaceCharge* charge_ptr = use.Get_surface_ptr()->Find_charge(x[j]->surface_charge);
return ((charge_ptr->Get_sigma1() *
(charge_ptr->Get_specific_area() *
charge_ptr->Get_grams()) / F_C_MOL));
}
else
{
return (0);
}
}
else if (strcmp_nocase("charge2", total_name) == 0)
{
if (use.Get_surface_ptr()->Get_type() == cxxSurface::CD_MUSIC)
{
cxxSurfaceCharge* charge_ptr = use.Get_surface_ptr()->Find_charge(x[j]->surface_charge);
return ((charge_ptr->Get_sigma2() *
(charge_ptr->Get_specific_area() *
charge_ptr->Get_grams()) / F_C_MOL));
}
else
{
return (0);
}
}
else if (strcmp_nocase("sigma", total_name) == 0)
{
if (use.Get_surface_ptr()->Get_type() == cxxSurface::DDL || use.Get_surface_ptr()->Get_type() == cxxSurface::CCM)
{
cxxSurfaceCharge* charge_ptr = use.Get_surface_ptr()->Find_charge(x[j]->surface_charge);
if (dl_type_x != cxxSurface::NO_DL)
{
charge = calc_surface_charge(surface_name_local.c_str());
}
else
{
charge = x[j]->f;
}
if ((charge_ptr->Get_specific_area() *
charge_ptr->Get_grams()) > 0)
{
return ((charge * F_C_MOL /
(charge_ptr->Get_specific_area() *
charge_ptr->Get_grams())));
}
else
{
return (0);
}
}
else if (use.Get_surface_ptr()->Get_type() == cxxSurface::CD_MUSIC)
{
cxxSurfaceCharge* charge_ptr = use.Get_surface_ptr()->Find_charge(x[j]->surface_charge);
return ((LDBLE)(charge_ptr->Get_sigma0()));
}
else
{
return (0);
}
}
else if (strcmp_nocase("sigma1", total_name) == 0)
{
if (use.Get_surface_ptr()->Get_type() == cxxSurface::CD_MUSIC)
{
cxxSurfaceCharge* charge_ptr = use.Get_surface_ptr()->Find_charge(x[j]->surface_charge);
return ((LDBLE)(charge_ptr->Get_sigma1()));
}
else
{
return (0);
}
}
else if (strcmp_nocase("sigma2", total_name) == 0)
{
if (use.Get_surface_ptr()->Get_type() == cxxSurface::CD_MUSIC)
{
cxxSurfaceCharge* charge_ptr = use.Get_surface_ptr()->Find_charge(x[j]->surface_charge);
return ((LDBLE)(charge_ptr->Get_sigma2()));
}
else
{
return (0);
}
}
else if (strcmp_nocase("water", total_name) == 0)
{
if (dl_type_x != cxxSurface::NO_DL)
{
cxxSurfaceCharge* charge_ptr = use.Get_surface_ptr()->Find_charge(x[j]->surface_charge);
return (charge_ptr->Get_mass_water());
}
else
{
return (0);
}
}
/*
* find total moles of each element in diffuse layer...
*/
surface_charge_ptr1 = use.Get_surface_ptr()->Find_charge(x[j]->surface_charge);
if (surface_charge_ptr1)
{
mass_water_surface = surface_charge_ptr1->Get_mass_water();
count_elts = 0;
paren_count = 0;
for (j = 0; j < (int)this->s_x.size(); j++)
{
if (s_x[j]->type > HPLUS)
continue;
molality = under(s_x[j]->lm);
LDBLE g = surface_charge_ptr1->Get_g_map()[s_x[j]->z].Get_g();
moles_excess = mass_water_aq_x * molality * (g * s_x[j]->erm_ddl +
mass_water_surface /
mass_water_aq_x * (s_x[j]->erm_ddl - 1));
moles_surface = mass_water_surface * molality + moles_excess;
/*
* Accumulate elements in diffuse layer
*/
add_elt_list(s_x[j]->next_elt, moles_surface);
}
elt_list_combine();
/*
* Return totals
*/
for (j = 0; j < count_elts; j++)
{
if (strcmp(elt_list[j].elt->name, total_name) == 0)
{
return ((LDBLE)elt_list[j].coef);
}
}
}
return (0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
calc_t_sc(const char* name)
/* ---------------------------------------------------------------------- */
{
char token[MAX_LENGTH];
class species* s_ptr;
Utilities::strcpy_safe(token, MAX_LENGTH, name);
s_ptr = s_search(token);
if (s_ptr != NULL && s_ptr->in)
{
if (!s_ptr->z)
return (0);
calc_SC();
if (!SC)
return (0);
LDBLE t = s_ptr->dw_t_SC * 1e7 * F_C_MOL * F_C_MOL / (R_KJ_DEG_MOL * 298150.0) * viscos_0_25 / viscos_0;
return (t / SC);
}
return (0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
calc_f_visc(const char* name)
/* ---------------------------------------------------------------------- */
{
char token[MAX_LENGTH];
class species* s_ptr;
if (print_viscosity)
{
Utilities::strcpy_safe(token, MAX_LENGTH, name);
s_ptr = s_search(token);
if (s_ptr != NULL && s_ptr->in)
return s_ptr->dw_t_visc;
}
return 0;
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
equi_phase(const char* phase_name)
/* ---------------------------------------------------------------------- */
{
int j;
if (use.Get_pp_assemblage_in() == FALSE || use.Get_pp_assemblage_ptr() == NULL)
return (0);
for (j = 0; j < count_unknowns; j++)
{
if (x[j]->type != PP)
continue;
if (strcmp_nocase(x[j]->pp_assemblage_comp_name, phase_name) == 0)
{
break;
}
}
/*
* Print pure phase assemblage data
*/
cxxPPassemblage* pp_assemblage_ptr = use.Get_pp_assemblage_ptr();
if (j == count_unknowns)
{
/* if not an unknown */
std::map<std::string, cxxPPassemblageComp>::iterator it;
it = pp_assemblage_ptr->Get_pp_assemblage_comps().begin();
for (; it != pp_assemblage_ptr->Get_pp_assemblage_comps().end(); it++)
{
if (strcmp_nocase
(it->second.Get_name().c_str(), phase_name) == 0)
{
return (it->second.Get_moles());
}
}
}
else
{
/* if an unknown */
if (x[j]->moles < 0.0)
x[j]->moles = 0.0;
return (x[j]->moles);
}
return (0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
equi_phase_delta(const char* phase_name)
/* ---------------------------------------------------------------------- */
{
int j;
if (use.Get_pp_assemblage_in() == FALSE || use.Get_pp_assemblage_ptr() == NULL)
return (0);
for (j = 0; j < count_unknowns; j++)
{
if (x[j]->type != PP)
continue;
if (strcmp_nocase(x[j]->pp_assemblage_comp_name, phase_name) == 0)
{
break;
}
}
/*
* Print pure phase assemblage data
*/
cxxPPassemblage* pp_assemblage_ptr = use.Get_pp_assemblage_ptr();
if (j == count_unknowns)
{
/* if not an unknown */
std::map<std::string, cxxPPassemblageComp>::iterator it;
it = pp_assemblage_ptr->Get_pp_assemblage_comps().begin();
for (; it != pp_assemblage_ptr->Get_pp_assemblage_comps().end(); it++)
{
if (strcmp_nocase
(it->second.Get_name().c_str(), phase_name) == 0)
{
cxxPPassemblageComp* comp_ptr = &(it->second);
if (state != TRANSPORT && state != PHAST)
{
//LDBLE moles = it->second.Get_moles();
//LDBLE delta_moles = moles - comp_ptr->Get_moles() -
// comp_ptr->Get_delta();
return(0);
}
else
{
LDBLE moles = it->second.Get_moles();
LDBLE delta_moles = moles - comp_ptr->Get_initial_moles();
return(delta_moles);
}
}
}
}
else
{
//cxxPPassemblageComp * comp_ptr = pp_assemblage_ptr->Find(x[j]->pp_assemblage_comp_name);
cxxPPassemblageComp* comp_ptr = (cxxPPassemblageComp*)x[j]->pp_assemblage_comp_ptr;
if (state != TRANSPORT && state != PHAST)
{
LDBLE delta_moles =
x[j]->moles - comp_ptr->Get_moles() -
comp_ptr->Get_delta();
return(delta_moles);
}
else
{
LDBLE delta_moles =
x[j]->moles - comp_ptr->Get_initial_moles();
return(delta_moles);
}
}
return (0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
equivalent_fraction(const char* name, LDBLE * eq, std::string & elt_name)
/* ---------------------------------------------------------------------- */
{
class species* s_ptr = s_search(name);
*eq = 0;
elt_name.clear();
LDBLE f = 0;
if (s_ptr != NULL && (s_ptr->type == EX || s_ptr->type == SURF))
{
*eq = s_ptr->equiv;
const class elt_list* next_elt;
LDBLE tot = 0.0;
for (next_elt = &s_ptr->next_elt[0]; next_elt->elt != NULL; next_elt++)
{
if (next_elt->elt->master->s->type == SURF ||
next_elt->elt->master->s->type == EX)
{
tot = total_mole(next_elt->elt->name);
elt_name = next_elt->elt->name;
}
}
if (s_ptr->in == TRUE && tot > 0.0)
{
f = s_ptr->moles * s_ptr->equiv / tot;
}
}
return f;
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
find_gas_comp(const char* gas_comp_name)
/* ---------------------------------------------------------------------- */
{
int i;
if (use.Get_gas_phase_in() == FALSE || use.Get_gas_phase_ptr() == NULL)
return (0);
cxxGasPhase* gas_phase_ptr = use.Get_gas_phase_ptr();
for (size_t j = 0; j < gas_phase_ptr->Get_gas_comps().size(); j++)
{
if (strcmp_nocase(gas_phase_ptr->Get_gas_comps()[j].Get_phase_name().c_str(), gas_comp_name) == 0)
{
class phase* phase_ptr = phase_bsearch(gas_comp_name, &i, false);
if (phase_ptr)
{
return (phase_ptr->moles_x);
}
}
}
return (0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
find_gas_p(void)
/* ---------------------------------------------------------------------- */
{
if (use.Get_gas_phase_in() == FALSE || use.Get_gas_phase_ptr() == NULL)
return (0);
cxxGasPhase* gas_phase_ptr = use.Get_gas_phase_ptr();
if (gas_phase_ptr->Get_type() == cxxGasPhase::GP_PRESSURE)
{
if (gas_unknown == NULL)
return (0);
if (gas_unknown->moles < 1e-12)
return (0);
}
return (gas_phase_ptr->Get_total_p());
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
find_gas_vm(void)
/* ---------------------------------------------------------------------- */
{
if (use.Get_gas_phase_in() == FALSE || use.Get_gas_phase_ptr() == NULL)
return (0);
cxxGasPhase* gas_phase_ptr = use.Get_gas_phase_ptr();
if (gas_phase_ptr->Get_type() == cxxGasPhase::GP_PRESSURE)
{
if (gas_unknown == NULL)
return (0);
if (gas_unknown->moles < 1e-12)
return (0);
gas_phase_ptr->Set_total_moles(gas_unknown->moles);
gas_phase_ptr->Set_volume(gas_phase_ptr->Get_total_moles() * R_LITER_ATM * tk_x /
gas_phase_ptr->Get_total_p());
if (gas_phase_ptr->Get_v_m() >= 0.01)
gas_phase_ptr->Set_volume(gas_phase_ptr->Get_v_m() * gas_unknown->moles);
}
return gas_phase_ptr->Get_volume() / gas_phase_ptr->Get_total_moles();
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
find_misc1(const char* ss_name)
/* ---------------------------------------------------------------------- */
{
if (use.Get_ss_assemblage_in() == FALSE || use.Get_ss_assemblage_ptr() == NULL)
return (0.0);
std::vector<cxxSS*> ss_ptrs = use.Get_ss_assemblage_ptr()->Vectorize();
for (size_t j = 0; j < ss_ptrs.size(); j++)
{
cxxSS* ss_ptr = ss_ptrs[j];
if (strcmp_nocase(ss_ptr->Get_name().c_str(), ss_name) == 0)
{
if (ss_ptr->Get_miscibility())
{
return (ss_ptr->Get_xb1());
}
else
{
return (1.0);
}
}
}
return (0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
find_misc2(const char* ss_name)
/* ---------------------------------------------------------------------- */
{
if (use.Get_ss_assemblage_in() == FALSE || use.Get_ss_assemblage_ptr() == NULL)
return (0.0);
std::vector<cxxSS*> ss_ptrs = use.Get_ss_assemblage_ptr()->Vectorize();
for (size_t j = 0; j < ss_ptrs.size(); j++)
{
cxxSS* ss_ptr = ss_ptrs[j];
if (strcmp_nocase(ss_ptr->Get_name().c_str(), ss_name) == 0)
{
if (ss_ptr->Get_miscibility())
{
return (ss_ptr->Get_xb2());
}
else
{
return (1.0);
}
}
}
return (0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
find_ss_comp(const char* ss_comp_name)
/* ---------------------------------------------------------------------- */
{
if (use.Get_ss_assemblage_in() == FALSE || use.Get_ss_assemblage_ptr() == NULL)
return (0);
std::vector<cxxSS*> ss_ptrs = use.Get_ss_assemblage_ptr()->Vectorize();
for (size_t j = 0; j < ss_ptrs.size(); j++)
{
cxxSS* ss_ptr = ss_ptrs[j];
for (size_t i = 0; i < ss_ptr->Get_ss_comps().size(); i++)
{
cxxSScomp* comp_ptr = &(ss_ptr->Get_ss_comps()[i]);
if (strcmp_nocase(comp_ptr->Get_name().c_str(), ss_comp_name) == 0)
{
if (ss_ptr->Get_ss_in())
{
return (comp_ptr->Get_moles());
}
else
{
return (0.0);
}
}
}
}
return (0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
get_calculate_value(const char* name)
/* ---------------------------------------------------------------------- */
/*
* Gets value from a calclate_value structure
* arguments: name
* return: LDBLE of value
*/
{
class calculate_value* calculate_value_ptr;
calculate_value_ptr = calculate_value_search(name);
if (calculate_value_ptr == NULL)
{
error_string = sformatf("CALC_VALUE Basic function, %s not found.",
name);
//error_msg(error_string, CONTINUE);
//input_error++;
warning_msg(error_string);
return (MISSING);
}
if (name == NULL)
{
error_string = sformatf(
"Definition for calculated value not found, %s", name);
input_error++;
error_msg(error_string, CONTINUE);
return (MISSING);
}
char l_command[] = "run";
PBasic interp(this, this->phrq_io);
if (calculate_value_ptr->new_def == TRUE)
{
if (interp.basic_compile
(calculate_value_ptr->commands.c_str(),
&calculate_value_ptr->linebase,
&calculate_value_ptr->varbase,
&calculate_value_ptr->loopbase) != 0)
{
error_string = sformatf(
"Fatal Basic error in CALCULATE_VALUES %s.",
calculate_value_ptr->name);
error_msg(error_string, STOP);
}
calculate_value_ptr->new_def = FALSE;
}
if (interp.basic_run(l_command,
calculate_value_ptr->linebase,
calculate_value_ptr->varbase,
calculate_value_ptr->loopbase) != 0)
{
error_string = sformatf("Fatal Basic error in calculate_value %s.",
calculate_value_ptr->name);
error_msg(error_string, STOP);
}
if (std::isnan(rate_moles))
{
error_string = sformatf("Calculated value not SAVEed for %s.",
calculate_value_ptr->name);
error_msg(error_string, STOP);
}
else
{
calculate_value_ptr->calculated = TRUE;
calculate_value_ptr->value = rate_moles;
}
return (calculate_value_ptr->value);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
kinetics_moles(const char* kinetics_name)
/* ---------------------------------------------------------------------- */
{
if (use.Get_kinetics_in() == FALSE || use.Get_kinetics_ptr() == NULL)
return (0);
for (size_t i = 0; i < use.Get_kinetics_ptr()->Get_kinetics_comps().size(); i++)
{
cxxKineticsComp* kinetics_comp_ptr = &(use.Get_kinetics_ptr()->Get_kinetics_comps()[i]);
if (strcmp_nocase
(kinetics_comp_ptr->Get_rate_name().c_str(), kinetics_name) == 0)
{
return (kinetics_comp_ptr->Get_m());
}
}
error_string = sformatf("No data for rate %s in KINETICS keyword.",
kinetics_name);
//if (count_warnings >= 0) // appt debug cvode
// warning_msg(error_string);
return (0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
kinetics_moles_delta(const char* kinetics_name)
/* ---------------------------------------------------------------------- */
{
if (use.Get_kinetics_in() == FALSE || use.Get_kinetics_ptr() == NULL)
return (0);
for (size_t i = 0; i < use.Get_kinetics_ptr()->Get_kinetics_comps().size(); i++)
{
cxxKineticsComp* kinetics_comp_ptr = &(use.Get_kinetics_ptr()->Get_kinetics_comps()[i]);
if (strcmp_nocase
(kinetics_comp_ptr->Get_rate_name().c_str(), kinetics_name) == 0)
{
//return (kinetics_comp_ptr->Get_m());
if (state != TRANSPORT && state != PHAST)
{
//LDBLE moles = kinetics_comp_ptr->Get_m();
LDBLE delta_moles = -kinetics_comp_ptr->Get_moles();
return delta_moles;
}
else
{
//moles = kinetics_comp_ptr->Get_m();
LDBLE delta_moles =
kinetics_comp_ptr->Get_m() -
kinetics_comp_ptr->Get_initial_moles();
return delta_moles;
}
}
}
//error_string = sformatf( "No data for rate %s in KINETICS keyword.",
// kinetics_name);
//warning_msg(error_string);
return (0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
log_activity(const char* species_name)
/* ---------------------------------------------------------------------- */
{
class species* s_ptr;
LDBLE la;
s_ptr = s_search(species_name);
if (s_ptr == s_eminus)
{
la = s_eminus->la;
}
else if (s_ptr == NULL || s_ptr->in == FALSE)
{
la = -99.99;
}
else if (s_ptr == s_h2o)
{
la = s_h2o->la;
}
else
{
la = s_ptr->lm + s_ptr->lg;
}
return (la);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
log_molality(const char* species_name)
/* ---------------------------------------------------------------------- */
{
class species* s_ptr;
LDBLE lm;
s_ptr = s_search(species_name);
if (s_ptr == s_eminus)
{
lm = -99.99;
}
else if (s_ptr == NULL || s_ptr->in == FALSE)
{
lm = -99.99;
}
else if (s_ptr == s_h2o)
{
lm = log10(s_ptr->moles / mass_water_aq_x);
}
else
{
lm = s_ptr->lm;
}
return (lm);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
molality(const char* species_name)
/* ---------------------------------------------------------------------- */
{
class species* s_ptr;
LDBLE m;
s_ptr = s_search(species_name);
if (s_ptr == NULL || s_ptr == s_eminus || s_ptr->in == FALSE)
{
m = 1e-99;
}
else
{
/* m = pow(10., s_ptr->lm); */
m = s_ptr->moles / mass_water_aq_x;
}
return (m);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
pr_pressure(const char* phase_name)
/* ---------------------------------------------------------------------- */
{
int l;
class phase* phase_ptr = phase_bsearch(phase_name, &l, FALSE);
if (phase_ptr == NULL)
{
error_string = sformatf("Gas %s, not found.", phase_name);
warning_msg(error_string);
return (1e-99);
}
cxxGasPhase* gas_phase_ptr = use.Get_gas_phase_ptr();
if (gas_phase_ptr != NULL)
{
for (size_t i = 0; i < gas_phase_ptr->Get_gas_comps().size(); i++)
{
const cxxGasComp* gas_comp_ptr = &(gas_phase_ptr->Get_gas_comps()[i]);
int j;
class phase* phase_ptr_gas = phase_bsearch(gas_comp_ptr->Get_phase_name().c_str(), &j, FALSE);
if (phase_ptr == phase_ptr_gas)
{
if (gas_phase_ptr->Get_pr_in())
{
return phase_ptr->pr_p;
}
else
{
return gas_comp_ptr->Get_p();
}
}
}
}
else if (phase_ptr->in != FALSE && phase_ptr->pr_in)
{
return phase_ptr->pr_p;
}
return(0.0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
pressure(void)
/* ---------------------------------------------------------------------- */
{
return (patm_x);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
pr_phi(const char* phase_name)
/* ---------------------------------------------------------------------- */
{
int l;
class phase* phase_ptr = phase_bsearch(phase_name, &l, FALSE);
if (phase_ptr == NULL)
{
error_string = sformatf("Gas %s, not found.", phase_name);
warning_msg(error_string);
return (1e-99);
}
cxxGasPhase* gas_phase_ptr = use.Get_gas_phase_ptr();
if (gas_phase_ptr != NULL)
{
for (size_t i = 0; i < gas_phase_ptr->Get_gas_comps().size(); i++)
{
const cxxGasComp* gas_comp_ptr = &(gas_phase_ptr->Get_gas_comps()[i]);
int j;
class phase* phase_ptr_gas = phase_bsearch(gas_comp_ptr->Get_phase_name().c_str(), &j, FALSE);
if (phase_ptr == phase_ptr_gas)
{
if (gas_phase_ptr->Get_pr_in())
return phase_ptr->pr_phi;
else
return gas_comp_ptr->Get_phi();
}
}
}
else if (phase_ptr->in != FALSE && phase_ptr->pr_in)
{
return phase_ptr->pr_phi;
}
return (1.0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
saturation_ratio(const char* phase_name)
/* ---------------------------------------------------------------------- */
{
class rxn_token* rxn_ptr;
class phase* phase_ptr;
int l;
LDBLE si, iap;
iap = 0.0;
phase_ptr = phase_bsearch(phase_name, &l, FALSE);
if (phase_ptr == NULL)
{
error_string = sformatf("Mineral %s, not found.", phase_name);
warning_msg(error_string);
return (1e-99);
}
else if (phase_ptr->in != FALSE)
{
for (rxn_ptr = &phase_ptr->rxn_x.token[0] + 1; rxn_ptr->s != NULL;
rxn_ptr++)
{
iap += rxn_ptr->s->la * rxn_ptr->coef;
}
si = iap - phase_ptr->lk;
return (pow((LDBLE)10.0, si));
}
return (0.0);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
saturation_index(const char* phase_name, LDBLE * iap, LDBLE * si)
/* ---------------------------------------------------------------------- */
{
class rxn_token* rxn_ptr;
class phase* phase_ptr;
int l;
*si = -99.99;
*iap = 0.0;
phase_ptr = phase_bsearch(phase_name, &l, FALSE);
if (phase_ptr == NULL)
{
error_string = sformatf("Mineral %s, not found.", phase_name);
warning_msg(error_string);
*si = -99;
}
else if (phase_ptr->in != FALSE)
{
for (rxn_ptr = &phase_ptr->rxn_x.token[0] + 1; rxn_ptr->s != NULL;
rxn_ptr++)
{
*iap += rxn_ptr->s->la * rxn_ptr->coef;
}
*si = *iap - phase_ptr->lk;
}
else
{
return (ERROR);
}
return (OK);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
sum_match_gases(const char* mytemplate, const char* name)
/* ---------------------------------------------------------------------- */
{
int i;
LDBLE tot;
const class elt_list* next_elt;
if (use.Get_gas_phase_in() == FALSE || use.Get_gas_phase_ptr() == NULL)
return (0);
cxxGasPhase* gas_phase_ptr = use.Get_gas_phase_ptr();
tot = 0;
for (size_t j = 0; j < gas_phase_ptr->Get_gas_comps().size(); j++)
{
class phase* phase_ptr = phase_bsearch(gas_phase_ptr->Get_gas_comps()[j].Get_phase_name().c_str(),
&i, FALSE);
if (match_elts_in_species(phase_ptr->formula, mytemplate) == TRUE)
{
if (name == NULL)
{
tot += phase_ptr->moles_x;
}
else
{
for (next_elt = &phase_ptr->next_elt[0];
next_elt->elt != NULL; next_elt++)
{
if (strcmp(next_elt->elt->name, name) == 0)
{
tot += next_elt->coef * phase_ptr->moles_x;
break;
}
}
}
}
}
return (tot);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
sum_match_species(const char* mytemplate, const char* name)
/* ---------------------------------------------------------------------- */
{
int i;
LDBLE tot;
const class elt_list* next_elt;
count_elts = 0;
paren_count = 0;
tot = 0;
if (sum_species_map.find(mytemplate) == sum_species_map.end())
{
std::vector<std::string> species_list;
for (i = 0; i < (int)this->s_x.size(); i++)
{
class species* s_ptr = s_x[i];
if (match_elts_in_species(s_ptr->name, mytemplate) == TRUE)
{
species_list.push_back(s_ptr->name);
}
}
sum_species_map[mytemplate] = species_list;
}
std::vector<std::string>& species_list = (sum_species_map.find(mytemplate))->second;
for (size_t i = 0; i < species_list.size(); i++)
{
class species* s_ptr = s_search(species_list[i].c_str());
if (s_ptr->in == FALSE) continue;
if (name == NULL)
{
tot += s_ptr->moles;
}
else
{
for (next_elt = &s_ptr->next_elt[0]; next_elt->elt != NULL;
next_elt++)
{
if (strcmp(next_elt->elt->name, name) == 0)
{
tot += next_elt->coef * s_ptr->moles;
break;
}
}
}
}
return (tot);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
sum_match_ss(const char* mytemplate, const char* name)
/* ---------------------------------------------------------------------- */
{
LDBLE tot;
const class elt_list* next_elt;
if (use.Get_ss_assemblage_in() == FALSE || use.Get_ss_assemblage_ptr() == NULL)
return (0);
tot = 0;
std::vector<cxxSS*> ss_ptrs = use.Get_ss_assemblage_ptr()->Vectorize();
for (size_t j = 0; j < ss_ptrs.size(); j++)
{
cxxSS* ss_ptr = ss_ptrs[j];
if (strcmp_nocase(ss_ptr->Get_name().c_str(), mytemplate) == 0)
{
if (!ss_ptr->Get_ss_in())
{
tot = 0;
break;
}
for (size_t i = 0; i < ss_ptr->Get_ss_comps().size(); i++)
{
cxxSScomp* comp_ptr = &(ss_ptr->Get_ss_comps()[i]);
if (name == NULL)
{
tot += comp_ptr->Get_moles();
}
else
{
int l;
class phase* phase_ptr = phase_bsearch(comp_ptr->Get_name().c_str(), &l, FALSE);
for (next_elt = &phase_ptr->next_elt[0]; next_elt->elt != NULL; next_elt++)
{
if (strcmp(next_elt->elt->name, name) == 0)
{
tot += next_elt->coef * comp_ptr->Get_moles();
break;
}
}
}
}
break;
}
}
return (tot);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
list_ss(std::string ss_name, cxxNameDouble & composition)
/* ---------------------------------------------------------------------- */
{
LDBLE tot = 0;
composition.clear();
if (use.Get_ss_assemblage_in() == FALSE || use.Get_ss_assemblage_ptr() == NULL)
return (0);
std::vector<cxxSS*> ss_ptrs = use.Get_ss_assemblage_ptr()->Vectorize();
for (size_t j = 0; j < ss_ptrs.size(); j++)
{
cxxSS* ss_ptr = ss_ptrs[j];
if (strcmp_nocase(ss_ptr->Get_name().c_str(), ss_name.c_str()) == 0)
{
for (size_t i = 0; i < ss_ptr->Get_ss_comps().size(); i++)
{
cxxSScomp* comp_ptr = &(ss_ptr->Get_ss_comps()[i]);
composition.add(comp_ptr->Get_name().c_str(), comp_ptr->Get_moles());
tot += comp_ptr->Get_moles();
}
break;
}
}
return (tot);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
match_elts_in_species(const char* name, const char* mytemplate)
/* ---------------------------------------------------------------------- */
{
/*
* Makes a list of elements with their coefficients, stores elements
* in elt_list at position count_elts. Global variable count_elts is
* updated with each stored element. Also uses static global variable
* paren_count.
*
* Arguments:
* **t_ptr input, point in token string to start looking
* output, is next position to start looking
* coef input, coefficient to multiply subscripts by
*/
int i, i1, l, case_no, match;
char c, c1;
const char* cptr, * ptr1;
LDBLE d;
char token[MAX_LENGTH], equal_list[MAX_LENGTH];
char token1[MAX_LENGTH], template1[MAX_LENGTH], equal_list1[MAX_LENGTH];
char str[2];
Utilities::strcpy_safe(token, MAX_LENGTH, name);
squeeze_white(token);
replace("(+", "(", token);
if (strstr("token", "++") != NULL)
{
replace("++++++", "+6", token);
replace("+++++", "+5", token);
replace("++++", "+4", token);
replace("+++", "+3", token);
replace("++", "+2", token);
}
if (strstr("token", "--") != NULL)
{
replace("------", "-6", token);
replace("-----", "-5", token);
replace("----", "-4", token);
replace("---", "-3", token);
replace("--", "-2", token);
}
cptr = token;
std::vector< std::pair<std::string, LDBLE> > match_vector;
while ((c = *cptr) != '\0')
{
c1 = *(cptr + 1);
str[0] = c;
str[1] = '\0';
/*
* New element
*/
if (isupper((int)c) || (c == 'e' && c1 == '-') || (c == '['))
{
/*
* Get new element and subscript
*/
std::string element;
if (get_elt(&cptr, element, &l) == ERROR)
{
return (ERROR);
}
if (get_num(&cptr, &d) == ERROR)
{
return (ERROR);
}
std::pair<std::string, LDBLE> pr(element, d);
match_vector.push_back(pr);
}
else
{
std::pair<std::string, LDBLE> pr(str, 1.0);
match_vector.push_back(pr);
cptr += 1;
}
}
/*
* Replace elements with first of equivalent elements
*/
Utilities::strcpy_safe(template1, MAX_LENGTH, mytemplate);
squeeze_white(template1);
cptr = template1;
while (extract_bracket(&cptr, equal_list) == TRUE)
{
replace("{", "", equal_list);
replace("}", "", equal_list);
while (replace(",", " ", equal_list) == TRUE);
ptr1 = equal_list;
/*
* Get first name in a list from template
*/
std::string elt_name;
if (copy_token(elt_name, &ptr1) == EMPTY)
{
error_string = sformatf(
"Expecting a nonempty list of element names in isotope sum. %s",
mytemplate);
error_msg(error_string, CONTINUE);
return (ERROR);
}
std::string replace_name = elt_name;
/*
* Replace in species all equivalent names from template
*/
while (copy_token(elt_name, &ptr1) != EMPTY)
{
for (i = 0; i < (int)match_vector.size(); i++)
{
if (elt_name == match_vector[i].first)
{
match_vector[i].first = replace_name;
}
}
}
}
/*
* Combine contiguous elements
*/
i1 = 0;
for (i = 1; i < (int)match_vector.size(); i++)
{
if ((isupper((int)(match_vector[i].first[0])) != FALSE)
&& (match_vector[i].first == match_vector[i1].first))
{
match_vector[i1].second += match_vector[i].second;
}
else
{
i1++;
match_vector[i1].first = match_vector[i].first;
match_vector[i1].second = match_vector[i].second;
}
}
int count_match_tokens = i1 + 1;
/*
* write out string
*/
token[0] = '\0';
for (i = 0; i < count_match_tokens; i++)
{
Utilities::strcat_safe(token, MAX_LENGTH, match_vector[i].first.c_str());
if (match_vector[i].second != 1.0)
{
snprintf(token1, sizeof(token1), "%g", (double)match_vector[i].second);
Utilities::strcat_safe(token, MAX_LENGTH, token1);
}
}
/*
* Write a template name using first of equivalent elements
*/
Utilities::strcpy_safe(template1, MAX_LENGTH, mytemplate);
squeeze_white(template1);
cptr = template1;
while (extract_bracket(&cptr, equal_list) == TRUE)
{
Utilities::strcpy_safe(equal_list1, MAX_LENGTH, equal_list);
replace("{", "", equal_list);
replace("}", "", equal_list);
while (replace(",", " ", equal_list) == TRUE);
ptr1 = equal_list;
/*
* Get first name in a list
*/
std::string elt_name;
if (copy_token(elt_name, &ptr1) == EMPTY)
{
error_string = sformatf(
"Expecting a nonempty list of element names in isotope sum. %s",
mytemplate);
error_msg(error_string, CONTINUE);
return (ERROR);
}
replace(equal_list1, elt_name.c_str(), template1);
squeeze_white(template1);
cptr = template1;
}
/*
* Compare string
*/
/* Cases: 0 exact match
* 1 leading wild card
* 2 trailing wild card
* 3 leading and trailing wild card
*/
case_no = 0;
if (template1[0] == '*')
case_no = 1;
l = (int)strlen(template1);
if (template1[l - 1] == '*')
{
if (case_no != 1)
{
case_no = 2;
}
else
{
case_no = 3;
}
}
while (replace("*", "", template1));
match = FALSE;
switch (case_no)
{
case 0:
/* exact match */
if (strcmp(token, template1) == 0)
match = TRUE;
break;
case 1:
/* leading wild card */
if ((cptr = strstr(token, template1)) == NULL)
{
match = FALSE;
}
else
{
if (strcmp(cptr, template1) == 0)
match = TRUE;
}
break;
case 2:
/* trailing wild card */
if (strstr(token, template1) == token)
match = TRUE;
break;
case 3:
/* trailing wild card */
if (strstr(token, template1) != NULL)
match = TRUE;
break;
}
return (match);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
extract_bracket(const char** string, char* bracket_string)
/* ---------------------------------------------------------------------- */
{
const char* cptr;
char* ptr1;
if ((cptr = strstr(*string, "{")) == NULL)
return (FALSE);
strcpy(bracket_string, cptr);
if ((ptr1 = strstr(bracket_string, "}")) == NULL)
{
error_string = sformatf(
"No matching bracket (}) in isotope template string %s",
*string);
error_msg(error_string, CONTINUE);
input_error++;
return (FALSE);
}
ptr1[1] = '\0';
*string = strstr(*string, "}");
*string += 1;
return (TRUE);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
surf_total(const char* total_name, const char* surface_name)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in LDBLE layer
*/
int j;
if (use.Get_surface_ptr() == NULL || surface_name == NULL || total_name == NULL)
return (0);
bool redox = false;
if (strstr(total_name, "(") != NULL)
{
redox = true;
}
if (!redox)
{
if (strcmp(total_name, "H") == 0 || strcmp(total_name, "O") == 0)
{
return surf_total_no_redox(total_name, surface_name);
}
}
/*
* Find surface...
*/
for (j = 0; j < count_unknowns; j++)
{
if (x[j]->type != SURFACE)
continue;
std::string token;
token = x[j]->master[0]->elt->name;
replace("_", " ", token);
std::string::iterator b = token.begin();
std::string::iterator e = token.end();
std::string name;
CParser::copy_token(name, b, e);
if (strcmp(name.c_str(), surface_name) == 0)
break;
}
if (j >= count_unknowns)
return (0);
/*
* find total moles for redox state
*/
LDBLE t = 0;
for (j = 0; j < (int)this->s_x.size(); j++)
{
if (s_x[j]->type != SURF)
continue;
std::string token;
bool match = false;
// find if surface matches
for (int i = 0; s_x[j]->next_elt[i].elt != NULL; i++)
{
if (s_x[j]->next_elt[i].elt->master->type != SURF) continue;
token = s_x[j]->next_elt[i].elt->name;
replace("_", " ", token);
std::string::iterator b = token.begin();
std::string::iterator e = token.end();
std::string name;
CParser::copy_token(name, b, e);
if (strcmp(name.c_str(), surface_name) == 0)
{
match = true;
break;
}
}
if (!match) continue;
// surface matches, now match element or redox state
class rxn_token* rxn_ptr;
if (s_x[j]->mole_balance == NULL)
{
for (rxn_ptr = &s_x[j]->rxn_s.token[0] + 1; rxn_ptr->s != NULL; rxn_ptr++)
{
if (redox && rxn_ptr->s->secondary)
{
token = rxn_ptr->s->secondary->elt->name;
}
else if (!redox && rxn_ptr->s->secondary)
{
token = rxn_ptr->s->secondary->elt->primary->elt->name;
}
else if (!redox && rxn_ptr->s->primary)
{
token = rxn_ptr->s->primary->elt->name;
}
else
{
continue;
}
if (strcmp(token.c_str(), total_name) == 0)
{
t += rxn_ptr->coef * s_x[j]->moles;
break;
}
else
// sum all sites in case total_name is a surface name without underscore surf ("Hfo_w", "Hfo")
{
if (rxn_ptr->s->type == SURF)
{
if (token.find("_") != std::string::npos)
{
token = token.substr(0, token.find("_"));
}
if (strcmp(token.c_str(), total_name) == 0)
{
t += rxn_ptr->coef * s_x[j]->moles;
break;
}
}
}
}
}
else
{
for (int i = 0; s_x[j]->next_secondary[i].elt != NULL; i++)
{
token = s_x[j]->next_secondary[i].elt->name;
if (strcmp(token.c_str(), total_name) == 0)
{
t += s_x[j]->next_secondary[i].coef * s_x[j]->moles;
break;
}
}
}
}
return t;
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
surf_total_no_redox(const char* total_name, const char* surface_name)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in LDBLE layer
*/
int i, j, k;
char name[MAX_LENGTH], token[MAX_LENGTH];
char surface_name_local[MAX_LENGTH];
const char* cptr;
if (use.Get_surface_ptr() == NULL)
return (0);
/*
* Find surface...
*/
for (j = 0; j < count_unknowns; j++)
{
if (x[j]->type != SURFACE)
continue;
Utilities::strcpy_safe(token, MAX_LENGTH, x[j]->master[0]->elt->name);
replace("_", " ", token);
cptr = token;
copy_token(name, &cptr, &k);
if (surface_name != NULL)
{
if (strcmp(name, surface_name) == 0)
break;
}
else
{
break;
}
}
if (j >= count_unknowns)
return (0);
Utilities::strcpy_safe(surface_name_local, MAX_LENGTH, name);
/*
* find total moles of each element in diffuse layer...
*/
count_elts = 0;
paren_count = 0;
for (j = 0; j < (int)this->s_x.size(); j++)
{
if (s_x[j]->type != SURF)
continue;
for (i = 0; s_x[j]->next_elt[i].elt != NULL; i++)
{
if (s_x[j]->next_elt[i].elt->master->type != SURF) continue;
Utilities::strcpy_safe(token, MAX_LENGTH, s_x[j]->next_elt[i].elt->name);
replace("_", " ", token);
cptr = token;
copy_token(name, &cptr, &k);
if (strcmp(name, surface_name_local) == 0)
{
/*
* Accumulate elements in diffuse layer
*/
add_elt_list(s_x[j]->next_elt, s_x[j]->moles);
//fprintf(stderr, "%15s\t%e\t%s\t%s\n", s_x[j]->name, s_x[j]->moles, name, surface_name_local );
break;
}
}
}
elt_list_combine();
/*
* Return totals
*/
for (j = 0; j < count_elts; j++)
{
if (strcmp(elt_list[j].elt->name, total_name) == 0)
{
return ((LDBLE)elt_list[j].coef);
}
}
return (0);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
total(const char* total_name)
/* ---------------------------------------------------------------------- */
{
class master* master_ptr;
LDBLE t;
if (strcmp(total_name, "H") == 0)
{
return (total_h_x / mass_water_aq_x);
}
if (strcmp(total_name, "O") == 0)
{
return (total_o_x / mass_water_aq_x);
}
std::string noplus = total_name;
replace(noplus, "(+", "(");
master_ptr = master_bsearch(noplus.c_str());
t = 0.0;
if (master_ptr == NULL)
{
if (strcmp_nocase(total_name, "water") == 0)
{
return (mass_water_aq_x);
}
else if (strcmp_nocase(total_name, "charge") == 0)
{
return (cb_x / mass_water_aq_x);
}
/*
sprintf (error_string, "Cannot find definition for master species, %s.",
total_name);
warning_msg (error_string);
*/
}
/*
* Primary master species
*/
else if (master_ptr->primary == TRUE)
{
/*
* Not a redox element
*/
if (master_ptr->s->secondary == NULL)
{
t = master_ptr->total / mass_water_aq_x;
/*
* Redox element, need to sum totals of all redox states
*/
}
else
{
t = 0;
for (size_t i = master_ptr->number + 1;
(i < (int)master.size() && master[i]->elt->primary == master_ptr);
i++)
{
t += master[i]->total / mass_water_aq_x;
}
}
}
/*
* Secondary master species
*/
else
{
t = master_ptr->total / mass_water_aq_x;
}
return (t);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
total_mole(const char* total_name)
/* ---------------------------------------------------------------------- */
{
class master* master_ptr;
LDBLE t;
if (strcmp(total_name, "H") == 0)
{
return (total_h_x);
}
if (strcmp(total_name, "O") == 0)
{
return (total_o_x);
}
std::string noplus = total_name;
replace(noplus, "(+", "(");
master_ptr = master_bsearch(noplus.c_str());
t = 0.0;
if (master_ptr == NULL)
{
if (strcmp_nocase(total_name, "water") == 0)
{
return (mass_water_aq_x / gfw_water);
}
else if (strcmp_nocase(total_name, "charge") == 0)
{
return (cb_x);
}
/*
sprintf (error_string, "Cannot find definition for master species, %s.",
total_name);
warning_msg (error_string);
*/
}
/*
* Primary master species
*/
else if (master_ptr->primary == TRUE)
{
/*
* Not a redox element
*/
if (master_ptr->s->secondary == NULL)
{
t = master_ptr->total;
/*
* Redox element, need to sum totals of all redox states
*/
}
else
{
t = 0;
for (size_t i = master_ptr->number + 1;
(i < master.size() && master[i]->elt->primary == master_ptr);
i++)
{
t += master[i]->total;
}
}
}
/*
* Secondary master species
*/
else
{
t = master_ptr->total;
}
return (t);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
get_edl_species(cxxSurfaceCharge & charge_ref)
/* ---------------------------------------------------------------------- */
{
double mass_water_surface = charge_ref.Get_mass_water();
sys.clear();
for (int j = 0; j < (int)this->s_x.size(); j++)
{
if (s_x[j]->type == H2O)
{
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(s_x[j]->name);
sys[count_sys].moles = mass_water_surface / gfw_water;
sys_tot += sys[count_sys].moles;
count_sys++;
}
else if (s_x[j]->type < H2O)
{
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
double molality = under(s_x[j]->lm);
double moles_excess = mass_water_aq_x * molality * charge_ref.Get_g_map()[s_x[j]->z].Get_g();
double moles_surface = mass_water_surface * molality + moles_excess;
sys[count_sys].name = string_duplicate(s_x[j]->name);
sys[count_sys].moles = moles_surface;
sys_tot += sys[count_sys].moles;
count_sys++;
}
else
{
continue;
}
}
return (OK);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
edl_species(const char* surf_name, LDBLE * count, char*** names, LDBLE * *moles, LDBLE * area, LDBLE * thickness)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in system and lists of species/phases in sort order
*/
int i;
sys_tot = 0;
sys.clear();
if (!(dl_type_x == cxxSurface::NO_DL))
{
cxxSurface* surface_ptr = use.Get_surface_ptr();
for (size_t i = 0; i < surface_ptr->Get_surface_charges().size(); i++)
{
cxxSurfaceCharge& charge_ref = surface_ptr->Get_surface_charges()[i];
if (strcmp(charge_ref.Get_name().c_str(), surf_name) == 0)
{
get_edl_species(charge_ref);
*area = charge_ref.Get_specific_area() * charge_ref.Get_grams();
*thickness = surface_ptr->Get_thickness();
break;
}
}
}
/*
* Sort system species
*/
if (sys.size() > 1)
{
qsort(&sys[0], sys.size(),
sizeof(class system_species), system_species_compare);
}
/*
* malloc space
*/
*names = (char**)PHRQ_malloc((sys.size() + 1) * sizeof(char*));
if (names == NULL)
malloc_error();
*moles = (LDBLE*)PHRQ_malloc((sys.size() + 1) * sizeof(LDBLE));
if (*moles == NULL)
malloc_error();
(*names)[0] = NULL;
(*moles)[0] = 0;
for (i = 0; i < (int)sys.size(); i++)
{
(*names)[i + 1] = sys[i].name;
(*moles)[i + 1] = sys[i].moles;
}
*count = (LDBLE)sys.size();
//PHRQ_free(sys);
sys.clear();
return (sys_tot);
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
system_total(const char* total_name, LDBLE * count, char*** names,
char*** types, LDBLE * *moles, int isort)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in system and lists of species/phases in sort order
*/
int i;
sys_tot = 0;
sys.clear();
if (strcmp_nocase(total_name, "elements") == 0)
{
system_total_elements();
}
else if (strcmp_nocase(total_name, "phases") == 0)
{
system_total_si();
}
else if (strcmp_nocase(total_name, "aq") == 0)
{
system_total_aq();
}
else if (strcmp_nocase(total_name, "ex") == 0)
{
system_total_ex();
}
else if (strcmp_nocase(total_name, "surf") == 0)
{
system_total_surf();
}
else if (strcmp_nocase(total_name, "s_s") == 0)
{
system_total_ss();
}
else if (strcmp_nocase(total_name, "gas") == 0)
{
system_total_gas();
}
else if (strcmp_nocase(total_name, "equi") == 0)
{
system_total_equi();
}
else if (strcmp_nocase(total_name, "kin") == 0)
{
system_total_kin();
}
else
{
if (strstr(total_name, "(") == NULL)
{
system_total_elt(total_name);
}
else
{
system_total_elt_secondary(total_name);
}
}
/*
* Sort system species
*/
if (sys.size() > 1 && isort == 0)
{
qsort(&sys[0], sys.size(),
sizeof(class system_species), system_species_compare);
}
else if (sys.size() > 1)
{
qsort(&sys[0], sys.size(),
sizeof(class system_species), system_species_compare_name);
}
/*
* malloc space
*/
size_t count_sys = sys.size();
*names = (char**)PHRQ_malloc((count_sys + 1) * sizeof(char*));
if (*names == NULL)
malloc_error();
*types = (char**)PHRQ_malloc((count_sys + 1) * sizeof(char*));
if (*types == NULL)
malloc_error();
*moles = (LDBLE*)PHRQ_malloc((count_sys + 1) * sizeof(LDBLE));
if (*moles == NULL)
malloc_error();
(*names)[0] = NULL;
(*types)[0] = NULL;
(*moles)[0] = 0;
for (i = 0; i < (int)count_sys; i++)
{
(*names)[i + 1] = sys[i].name;
(*types)[i + 1] = sys[i].type;
(*moles)[i + 1] = sys[i].moles;
}
*count = (LDBLE)count_sys;
if (strcmp_nocase(total_name, "elements") == 0)
{
sys_tot = 0;;
for (i = 0; i < (int)count_sys; i++)
{
if (strcmp(sys[i].type, "dis") == 0 &&
strstr(sys[i].name, "(") == NULL &&
strcmp(sys[i].name, "H") != 0
&& strcmp(sys[i].name, "O") != 0)
{
sys_tot += sys[i].moles;
}
}
}
//PHRQ_free(sys);
sys.clear();
return (sys_tot);
}
/* ---------------------------------------------------------------------- */
std::string Phreeqc::
kinetics_formula(std::string kin_name, cxxNameDouble & stoichiometry)
/* ---------------------------------------------------------------------- */
{
/*
* Returns formula of kinetic reactant
* Also returns arrays of elements and stoichiometry in stoichiometry
*/
stoichiometry.clear();
std::string formula;
if (use.Get_kinetics_ptr() == NULL)
return (formula);
std::vector <cxxKineticsComp> comps = use.Get_kinetics_ptr()->Get_kinetics_comps();
count_elts = 0;
paren_count = 0;
for (size_t i = 0; i < comps.size(); i++)
{
cxxKineticsComp* comp_ptr = &comps[i];
if (kin_name == comp_ptr->Get_rate_name().c_str())
{
cxxNameDouble nd = comp_ptr->Get_namecoef();
cxxNameDouble::iterator it = nd.begin();
for (; it != nd.end(); it++)
{
// Try Phases
int l;
class phase* phase_ptr = phase_bsearch(it->first.c_str(), &l, FALSE);
if (phase_ptr != NULL)
{
add_elt_list(phase_ptr->next_elt, it->second);
}
else
{
// add formula
std::string name = it->first;
LDBLE coef = it->second;
const char* cptr = &name[0];
get_elts_in_species(&cptr, coef);
}
}
formula.append(kin_name);
//elt_list[count_elts].elt = NULL;
elt_list_combine();
stoichiometry = elt_list_NameDouble();
break;
}
}
return (formula);
}
/* ---------------------------------------------------------------------- */
std::string Phreeqc::
phase_formula(std::string phase_name, cxxNameDouble & stoichiometry)
/* ---------------------------------------------------------------------- */
{
/*
* Returns formula of mineral
* Also returns arrays of elements and stoichiometry in elts_arg and coef_arg
*/
stoichiometry.clear();
std::string formula;
int j;
class phase* phase_ptr = phase_bsearch(phase_name.c_str(), &j, FALSE);
if (phase_ptr != NULL)
{
formula.append(phase_ptr->formula);
cxxNameDouble nd(phase_ptr->next_elt);
stoichiometry = nd;
}
return (formula);
}
/* ---------------------------------------------------------------------- */
std::string Phreeqc::
species_formula(std::string phase_name, cxxNameDouble & stoichiometry)
/* ---------------------------------------------------------------------- */
{
/*
* Returns formula of mineral
* Also returns arrays of elements and stoichiometry in elts_arg and coef_arg
*/
stoichiometry.clear();
std::string formula;
formula = "none";
class species* s_ptr = s_search(phase_name.c_str());
if (s_ptr != NULL)
{
cxxNameDouble nd(s_ptr->next_elt);
stoichiometry = nd;
stoichiometry["charge"] = s_ptr->z;
if (s_ptr->type == EX)
{
formula = "ex";
}
else if (s_ptr->type == SURF)
{
formula = "surf";
}
else
{
formula = "aq";
}
}
return (formula);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_elements(void)
/* ---------------------------------------------------------------------- */
{
int i;
LDBLE t;
char name[MAX_LENGTH];
class master* master_ptr;
/*
* Include H and O
*/
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate("H");
sys[count_sys].moles = total_h_x;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("dis");
count_sys++;
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate("O");
sys[count_sys].moles = total_o_x;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("dis");
count_sys++;;
/*
* Include H(1) and O(-2)
*/
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate("H(1)");
sys[count_sys].moles = solution_sum_secondary("H(1)");
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("dis");
count_sys++;
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate("O(-2)");
sys[count_sys].moles = solution_sum_secondary("O(-2)");
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("dis");
count_sys++;
for (i = 0; i < (int)master.size(); i++)
{
master_ptr = master[i];
if (master_ptr->primary == TRUE && master_ptr->total_primary <= 0)
continue;
if (master_ptr->in == FALSE
&& (master_ptr->primary == FALSE
|| master_ptr->total_primary == 0))
continue;
/*
* H and O
*/
if (master_ptr->s == s_hplus)
{
continue;
}
else if (master_ptr->s == s_h2o)
{
continue;
}
if (master_ptr->primary == TRUE)
{
if (master_ptr->total_primary > 0)
{
t = master_ptr->total_primary;
/*
* Not a redox element
*/
}
else if (master_ptr->s->secondary == NULL)
{
t = master_ptr->total;
/*
* Redox element, need to sum totals of all redox states
*/
}
else
{
t = 0;
for (size_t j = master_ptr->number + 1;
master[j]->elt->primary == master_ptr; j++)
{
t += master[j]->total;
}
}
/*
* Secondary master species
*/
}
else
{
t = master_ptr->total;
}
Utilities::strcpy_safe(name, MAX_LENGTH, master[i]->elt->name);
count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(name);
sys[count_sys].moles = t;
sys_tot += sys[count_sys].moles;
if (master[i]->s->type <= SOLID)
{
sys[count_sys].type = string_duplicate("dis");
}
else if (master[i]->s->type == EX)
{
sys[count_sys].type = string_duplicate("ex");
}
else if (master[i]->s->type == SURF || master[i]->s->type == SURF_PSI)
{
sys[count_sys].type = string_duplicate("surf");
}
}
return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_si(void)
/* ---------------------------------------------------------------------- */
{
int i;
LDBLE si, iap;
class rxn_token* rxn_ptr;
char name[MAX_LENGTH];
sys_tot = -999.9;
for (i = 0; i < (int)phases.size(); i++)
{
if (phases[i]->in == FALSE || phases[i]->type != SOLID)
continue;
/*
* Print saturation index
*/
iap = 0.0;
for (rxn_ptr = &phases[i]->rxn_x.token[0] + 1; rxn_ptr->s != NULL;
rxn_ptr++)
{
iap += rxn_ptr->s->la * rxn_ptr->coef;
}
si = -phases[i]->lk + iap;
Utilities::strcpy_safe(name, MAX_LENGTH, phases[i]->name);
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(name);
sys[count_sys].moles = si;
if (si > sys_tot)
sys_tot = si;
sys[count_sys].type = string_duplicate("phase");
}
return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_aq(void)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in system and lists of species/phases in sort order
*/
int i;
/*
* find total moles in aq, surface, and exchange
*/
for (i = 0; i < (int)this->s_x.size(); i++)
{
//if (s_x[i]->type != AQ)
if (s_x[i]->type > HPLUS)
continue;
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(s_x[i]->name);
sys[count_sys].moles = s_x[i]->moles;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("aq");
}
return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_ex(void)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in system and lists of species/phases in sort order
*/
int i;
/*
* find total moles in aq, surface, and exchange
*/
for (i = 0; i < (int)this->s_x.size(); i++)
{
if (s_x[i]->type != EX)
continue;
if (s_x[i]->primary != NULL)
continue;
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(s_x[i]->name);
sys[count_sys].moles = s_x[i]->moles;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("ex");
}
return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_surf(void)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in system and lists of species/phases in sort order
*/
int i;
/*
* find total moles in aq, surface, and exchange
*/
for (i = 0; i < (int)this->s_x.size(); i++)
{
if (s_x[i]->type != SURF)
continue;
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(s_x[i]->name);
sys[count_sys].moles = s_x[i]->moles;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("surf");
}
return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_gas(void)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in system and lists of species/phases in sort order
*/
int i;
/*
* find total in gas phase
*/
if (use.Get_gas_phase_ptr() == NULL)
return (OK);
cxxGasPhase* gas_phase_ptr = use.Get_gas_phase_ptr();
for (size_t j = 0; j < gas_phase_ptr->Get_gas_comps().size(); j++)
{
class phase* phase_ptr = phase_bsearch(gas_phase_ptr->Get_gas_comps()[j].Get_phase_name().c_str(),
&i, FALSE);
assert(phase_ptr);
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(phase_ptr->name);
sys[count_sys].moles = phase_ptr->moles_x;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("gas");
}
return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_equi(void)
/* ---------------------------------------------------------------------- */
{
/*
* Equilibrium phases
*/
if (use.Get_pp_assemblage_ptr() == NULL)
return (OK);
std::map <std::string, cxxPPassemblageComp > comps = use.Get_pp_assemblage_ptr()->Get_pp_assemblage_comps();
std::map <std::string, cxxPPassemblageComp >::iterator it = comps.begin();
for (; it != comps.end(); it++)
{
cxxPPassemblageComp* comp_ptr = &(it->second);
int l;
class phase* phase_ptr = phase_bsearch(comp_ptr->Get_name().c_str(), &l, FALSE);
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(phase_ptr->name);
sys[count_sys].moles = equi_phase(sys[count_sys].name);
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("equi");
}
return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_kin(void)
/* ---------------------------------------------------------------------- */
{
/*
* Equilibrium phases
*/
if (use.Get_kinetics_ptr() == NULL)
return (OK);
std::vector <cxxKineticsComp> comps = use.Get_kinetics_ptr()->Get_kinetics_comps();
for (size_t i = 0; i < comps.size(); i++)
{
cxxKineticsComp* comp_ptr = &comps[i];
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(comp_ptr->Get_rate_name().c_str());
sys[count_sys].moles = comp_ptr->Get_m();
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("kin");
}
return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_ss(void)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in system and lists of species/phases in sort order
*/
/*
* Solid solutions
*/
if (use.Get_ss_assemblage_ptr() == NULL)
return (OK);
std::vector<cxxSS*> ss_ptrs = use.Get_ss_assemblage_ptr()->Vectorize();
for (size_t k = 0; k < ss_ptrs.size(); k++)
{
cxxSS* ss_ptr = ss_ptrs[k];
for (size_t i = 0; i < ss_ptr->Get_ss_comps().size(); i++)
{
cxxSScomp* comp_ptr = &(ss_ptr->Get_ss_comps()[i]);
int l;
class phase* phase_ptr = phase_bsearch(comp_ptr->Get_name().c_str(), &l, FALSE);
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(phase_ptr->name);
sys[count_sys].moles = comp_ptr->Get_moles();
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("s_s");
}
}
return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_elt(const char* total_name)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in system and lists of species/phases in sort order
*/
int i, j, k;
LDBLE molality, moles_excess, moles_surface, mass_water_surface;
char name[MAX_LENGTH];
/*
* find total moles in aq, surface, and exchange
*/
for (i = 0; i < (int)this->s_x.size(); i++)
{
count_elts = 0;
paren_count = 0;
add_elt_list(s_x[i]->next_elt, s_x[i]->moles);
elt_list_combine();
/*
* Look for element
*/
for (j = 0; j < count_elts; j++)
{
if (strcmp(elt_list[j].elt->name, total_name) == 0)
{
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(s_x[i]->name);
sys[count_sys].moles = elt_list[j].coef;
sys_tot += sys[count_sys].moles;
if (s_x[i]->type == AQ)
{
sys[count_sys].type = string_duplicate("aq");
}
else if (s_x[i]->type == EX)
{
sys[count_sys].type = string_duplicate("ex");
/* subtract again the dummy moles of primary exchange species... */
if (s_x[i]->primary != NULL)
{
sys_tot -= elt_list[j].coef;
}
}
else if (s_x[i]->type == SURF)
{
sys[count_sys].type = string_duplicate("surf");
}
else if (s_x[i]->type == HPLUS)
{
sys[count_sys].type = string_duplicate("aq");
/* sys[count_sys].moles = total_h_x; */
}
else if (s_x[i]->type == H2O)
{
sys[count_sys].type = string_duplicate("aq");
/* sys[count_sys].moles = total_o_x; */
}
else
{
error_msg("System_total", STOP);
}
break;
}
}
}
if (use.Get_surface_ptr() != NULL && dl_type_x != cxxSurface::NO_DL)
{
/*
* Find position of component in surface charge data
*/
i = -1;
for (k = 0; k < count_unknowns; k++)
{
if (x[k]->type != SURFACE_CB)
continue;
cxxSurfaceCharge* charge_ptr = use.Get_surface_ptr()->Find_charge(x[k]->surface_charge);
i++;
/*
* Loop through all surface components, calculate each H2O surface (diffuse layer),
* H2O aq, and H2O bulk (diffuse layers plus aqueous).
*/
mass_water_surface = charge_ptr->Get_mass_water();
count_elts = 0;
paren_count = 0;
for (j = 0; j < (int)this->s_x.size(); j++)
{
if (s_x[j]->type > HPLUS)
continue;
molality = under(s_x[j]->lm);
moles_excess =
mass_water_aq_x * molality *
(charge_ptr->Get_g_map()[s_x[j]->z].Get_g() * s_x[j]->erm_ddl +
mass_water_surface / mass_water_aq_x * (s_x[j]->erm_ddl -
1));
moles_surface = mass_water_surface * molality + moles_excess;
/*
* Accumulate elements in diffuse layer
*/
add_elt_list(s_x[j]->next_elt, moles_surface);
}
elt_list_combine();
/*
* Print totals
*/
for (j = 0; j < count_elts; j++)
{
if (strcmp(elt_list[j].elt->name, total_name) == 0)
{
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
Utilities::strcpy_safe(name, MAX_LENGTH, x[k]->master[0]->elt->name);
replace("_psi", "", name);
sys[count_sys].name = string_duplicate(name);
sys[count_sys].moles = elt_list[j].coef;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("diff");
break;
}
}
}
}
/*
* find total moles in mineral phases
*/
if (use.Get_pp_assemblage_in() == TRUE && use.Get_pp_assemblage_ptr() != NULL)
{
for (i = 0; i < count_unknowns; i++)
{
if (x[i]->type != PP)
continue;
//std::map<std::string, cxxPPassemblageComp>::iterator it;
//it = pp_assemblage_ptr->Get_pp_assemblage_comps().find(x[i]->pp_assemblage_comp_name);
cxxPPassemblageComp* comp_ptr = (cxxPPassemblageComp*)x[i]->pp_assemblage_comp_ptr;
//if (it->second.Get_add_formula().size() > 0)
if (comp_ptr->Get_add_formula().size() > 0)
continue;
count_elts = 0;
paren_count = 0;
int j;
//class phase * phase_ptr = phase_bsearch(x[i]->pp_assemblage_comp_name, &j, FALSE);
class phase* phase_ptr = x[i]->phase;
add_elt_list(phase_ptr->next_elt, x[i]->moles);
elt_list_combine();
for (j = 0; j < count_elts; j++)
{
if (strcmp(elt_list[j].elt->name, total_name) == 0)
{
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(phase_ptr->name);
sys[count_sys].moles = elt_list[j].coef;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("equi");
break;
}
}
}
}
/*
* Solid solutions
*/
if (use.Get_ss_assemblage_ptr() != NULL)
{
std::vector<cxxSS*> ss_ptrs = use.Get_ss_assemblage_ptr()->Vectorize();
for (size_t k = 0; k < ss_ptrs.size(); k++)
{
cxxSS* ss_ptr = ss_ptrs[k];
if (ss_ptr->Get_ss_in())
{
for (size_t i = 0; i < ss_ptr->Get_ss_comps().size(); i++)
{
cxxSScomp* comp_ptr = &(ss_ptr->Get_ss_comps()[i]);
int l;
class phase* phase_ptr = phase_bsearch(comp_ptr->Get_name().c_str(), &l, FALSE);
count_elts = 0;
paren_count = 0;
add_elt_list(phase_ptr->next_elt,
comp_ptr->Get_moles());
elt_list_combine();
for (j = 0; j < count_elts; j++)
{
if (strcmp(elt_list[j].elt->name, total_name) == 0)
{
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name =
string_duplicate(phase_ptr->name);
sys[count_sys].moles = elt_list[j].coef;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("s_s");
break;
}
}
}
}
}
}
/*
* find total in gas phase
*/
if (use.Get_gas_phase_ptr() != NULL)
{
cxxGasPhase* gas_phase_ptr = use.Get_gas_phase_ptr();
for (size_t i = 0; i < gas_phase_ptr->Get_gas_comps().size(); i++)
{
class phase* phase_ptr =
phase_bsearch(gas_phase_ptr->Get_gas_comps()[i].Get_phase_name().c_str(), &k, FALSE);
assert(phase_ptr);
if (phase_ptr->in == TRUE)
{
count_elts = 0;
paren_count = 0;
add_elt_list(phase_ptr->next_elt, phase_ptr->moles_x);
elt_list_combine();
/*
* Look for element
*/
for (j = 0; j < count_elts; j++)
{
if (strcmp(elt_list[j].elt->name, total_name) == 0)
{
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(phase_ptr->name);
sys[count_sys].moles = elt_list[j].coef;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("gas");
break;
}
}
}
}
}
return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_elt_secondary(const char* total_name)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in system and lists of species/phases in sort order
*/
int i, j, k, l;
LDBLE molality, moles_excess, moles_surface, mass_water_surface, sum,
coef;
char name[MAX_LENGTH];
/*
* find total moles in aq, surface, and exchange
*/
for (i = 0; i < (int)this->s_x.size(); i++)
{
count_elts = 0;
paren_count = 0;
if (s_x[i]->next_secondary.size() != 0)
{
add_elt_list(s_x[i]->next_secondary, s_x[i]->moles);
}
else
{
add_elt_list(s_x[i]->next_sys_total, s_x[i]->moles);
}
elt_list_combine();
/*
* Look for element
*/
for (j = 0; j < count_elts; j++)
{
if (strcmp(elt_list[j].elt->name, total_name) == 0)
{
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(s_x[i]->name);
sys[count_sys].moles = elt_list[j].coef;
sys_tot += sys[count_sys].moles;
if (s_x[i]->type == AQ)
{
sys[count_sys].type = string_duplicate("aq");
}
else if (s_x[i]->type == EX)
{
sys[count_sys].type = string_duplicate("ex");
}
else if (s_x[i]->type == SURF)
{
sys[count_sys].type = string_duplicate("surf");
}
else if (s_x[i]->type == HPLUS)
{
sys[count_sys].type = string_duplicate("aq");
/* sys[count_sys].moles = total_h_x; */
}
else if (s_x[i]->type == H2O)
{
sys[count_sys].type = string_duplicate("aq");
/* sys[count_sys].moles = total_o_x; */
}
else
{
error_msg("System_total", STOP);
}
break;
}
}
}
if (use.Get_surface_ptr() != NULL && dl_type_x != cxxSurface::NO_DL)
{
/*
* Find position of component in surface charge data
*/
i = -1;
for (k = 0; k < count_unknowns; k++)
{
if (x[k]->type != SURFACE_CB)
continue;
cxxSurfaceCharge* charge_ptr = use.Get_surface_ptr()->Find_charge(x[k]->surface_charge);
i++;
/*
* Loop through all surface components, calculate each H2O surface (diffuse layer),
* H2O aq, and H2O bulk (diffuse layers plus aqueous).
*/
mass_water_surface = charge_ptr->Get_mass_water();
sum = 0;
for (j = 0; j < (int)this->s_x.size(); j++)
{
count_elts = 0;
paren_count = 0;
if (s_x[i]->next_secondary.size() != 0)
{
add_elt_list(s_x[i]->next_secondary, 1);
}
else
{
add_elt_list(s_x[i]->next_sys_total, 1);
}
for (l = 0; l < count_elts; l++)
{
if (strcmp(elt_list[l].elt->name, total_name) == 0)
{
coef = elt_list[l].coef;
if (s_x[j]->type > H2O)
continue;
molality = under(s_x[j]->lm);
moles_excess =
mass_water_aq_x * molality *
charge_ptr->Get_g_map()[s_x[j]->z].Get_g();
moles_surface =
mass_water_surface * molality + moles_excess;
sum += moles_surface * coef;
break;
}
}
if (l >= count_elts)
continue;
Utilities::strcpy_safe(name, MAX_LENGTH, x[k]->master[0]->elt->name);
replace("_psi", "", name);
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name = string_duplicate(name);
sys[count_sys].moles = sum;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("diff");
break;
}
}
}
/*
* find total moles in mineral phases
*/
if (use.Get_pp_assemblage_in() == TRUE && use.Get_pp_assemblage_ptr() != NULL)
{
for (i = 0; i < count_unknowns; i++)
{
if (x[i]->type != PP)
continue;
//std::map<std::string, cxxPPassemblageComp>::iterator it;
//it = pp_assemblage_ptr->Get_pp_assemblage_comps().find(x[i]->pp_assemblage_comp_name);
cxxPPassemblageComp* comp_ptr = (cxxPPassemblageComp*)x[i]->pp_assemblage_comp_ptr;
//if (it->second.Get_add_formula().size() > 0)
if (comp_ptr->Get_add_formula().size() > 0)
continue;
count_elts = 0;
paren_count = 0;
int j;
//class phase * phase_ptr = phase_bsearch(x[i]->pp_assemblage_comp_name, &j, FALSE);
class phase* phase_ptr = x[i]->phase;
add_elt_list(phase_ptr->next_sys_total, x[i]->moles);
elt_list_combine();
for (j = 0; j < count_elts; j++)
{
if (strcmp(elt_list[j].elt->name, total_name) == 0)
{
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name =
string_duplicate(phase_ptr->name);
sys[count_sys].moles = elt_list[j].coef;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("equi");
break;
}
}
}
}
/*
* Solid solutions
*/
if (use.Get_ss_assemblage_ptr() != NULL)
{
std::vector<cxxSS*> ss_ptrs = use.Get_ss_assemblage_ptr()->Vectorize();
for (size_t i = 0; i < ss_ptrs.size(); i++)
{
cxxSS* ss_ptr = ss_ptrs[i];
if (ss_ptr->Get_ss_in())
{
for (size_t k = 0; k < ss_ptr->Get_ss_comps().size(); k++)
{
cxxSScomp* comp_ptr = &(ss_ptr->Get_ss_comps()[k]);
int l;
class phase* phase_ptr = phase_bsearch(comp_ptr->Get_name().c_str(), &l, FALSE);
count_elts = 0;
paren_count = 0;
add_elt_list(phase_ptr->next_sys_total,
comp_ptr->Get_moles());
elt_list_combine();
for (j = 0; j < count_elts; j++)
{
if (strcmp(elt_list[j].elt->name, total_name) == 0)
{
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name =
string_duplicate(phase_ptr->name);
sys[count_sys].moles = elt_list[j].coef;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("s_s");
break;
}
}
}
}
}
}
/*
* find total in gas phase
*/
if (use.Get_gas_phase_ptr() != NULL)
{
cxxGasPhase* gas_phase_ptr = use.Get_gas_phase_ptr();
for (size_t j = 0; j < gas_phase_ptr->Get_gas_comps().size(); j++)
{
class phase* phase_ptr =
phase_bsearch(gas_phase_ptr->Get_gas_comps()[j].Get_phase_name().c_str(), &i, FALSE);
assert(phase_ptr);
if (phase_ptr->in == TRUE)
{
count_elts = 0;
paren_count = 0;
add_elt_list(phase_ptr->next_sys_total,
phase_ptr->moles_x);
elt_list_combine();
/*
* Look for element
*/
for (size_t j1 = 0; j1 < (size_t)count_elts; j1++)
{
if (strcmp(elt_list[j1].elt->name, total_name) == 0)
{
size_t count_sys = sys.size();
sys.resize(count_sys + 1);
sys[count_sys].name =
string_duplicate(phase_ptr->name);
sys[count_sys].moles = elt_list[j1].coef;
sys_tot += sys[count_sys].moles;
sys[count_sys].type = string_duplicate("gas");
break;
}
}
}
}
}
return (OK);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
solution_number(void)
/* ---------------------------------------------------------------------- */
{
Phreeqc* PhreeqcPtr = this;
int soln_no = -999;
if (PhreeqcPtr->state == TRANSPORT)
{
soln_no = PhreeqcPtr->cell_no;
}
else if (PhreeqcPtr->state == PHAST)
{
soln_no = PhreeqcPtr->cell_no;
}
else if (PhreeqcPtr->state == ADVECTION)
{
soln_no = PhreeqcPtr->cell_no;
}
else if (PhreeqcPtr->state < REACTION)
{
soln_no = PhreeqcPtr->use.Get_solution_ptr()->Get_n_user();
}
else
{
if (PhreeqcPtr->use.Get_mix_in())
{
soln_no = PhreeqcPtr->use.Get_n_mix_user();
}
else
{
soln_no = PhreeqcPtr->use.Get_n_solution_user();
}
}
return soln_no;
}
/* ---------------------------------------------------------------------- */
LDBLE Phreeqc::
solution_sum_secondary(const char* total_name)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in system and lists of species/phases in sort order
*/
int i, j;
LDBLE sum;
/*
* find total moles in aq, surface, and exchange
*/
sum = 0;
for (i = 0; i < (int)this->s_x.size(); i++)
{
if (s_x[i]->type > H2O)
continue;
count_elts = 0;
paren_count = 0;
if (s_x[i]->next_secondary.size() != 0)
{
add_elt_list(s_x[i]->next_secondary, s_x[i]->moles);
}
else
{
add_elt_list(s_x[i]->next_sys_total, s_x[i]->moles);
}
elt_list_combine();
/*
* Look for element
*/
for (j = 0; j < count_elts; j++)
{
if (strcmp(elt_list[j].elt->name, total_name) == 0)
{
sum += elt_list[j].coef;
break;
}
}
}
return (sum);
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_species_compare(const void* ptr1, const void* ptr2)
/* ---------------------------------------------------------------------- */
{
const class system_species* a, * b;
a = (const class system_species*)ptr1;
b = (const class system_species*)ptr2;
if (a->moles < b->moles)
return (1);
if (a->moles > b->moles)
return (-1);
return (0);
}
int Phreeqc::
system_species_compare_name(const void* ptr1, const void* ptr2)
/* ---------------------------------------------------------------------- */
{
const class system_species* a, * b;
a = (const class system_species*)ptr1;
b = (const class system_species*)ptr2;
return (strncmp(a->name, b->name, MAX_LENGTH));
}
/* ---------------------------------------------------------------------- */
int Phreeqc::
system_total_solids(cxxExchange * exchange_ptr,
cxxPPassemblage * pp_assemblage_ptr,
cxxGasPhase * gas_phase_ptr,
cxxSSassemblage * ss_assemblage_ptr,
cxxSurface * surface_ptr)
/* ---------------------------------------------------------------------- */
{
/*
* Provides total moles in solid phases
*/
count_elts = 0;
paren_count = 0;
/*
* find total moles in exchanger
*/
if (exchange_ptr != NULL)
{
for (size_t i = 0; i < exchange_ptr->Get_exchange_comps().size(); i++)
{
add_elt_list(exchange_ptr->Get_exchange_comps()[i].Get_totals(), 1.0);
}
}
if (surface_ptr != NULL)
{
for (size_t i = 0; i < surface_ptr->Get_surface_comps().size(); i++)
{
add_elt_list(surface_ptr->Get_surface_comps()[i].Get_totals(), 1.0);
}
}
if (ss_assemblage_ptr != NULL)
{
std::vector<cxxSS*> ss_ptrs = ss_assemblage_ptr->Vectorize();
for (size_t i = 0; i < ss_ptrs.size(); i++)
{
cxxSS* ss_ptr = ss_ptrs[i];
for (size_t j = 0; j < ss_ptr->Get_ss_comps().size(); j++)
{
cxxSScomp* comp_ptr = &(ss_ptr->Get_ss_comps()[j]);
int l;
class phase* phase_ptr = phase_bsearch(comp_ptr->Get_name().c_str(), &l, FALSE);
add_elt_list(phase_ptr->next_elt,
comp_ptr->Get_moles());
}
}
}
if (gas_phase_ptr != NULL)
{
for (size_t j = 0; j < gas_phase_ptr->Get_gas_comps().size(); j++)
{
int i;
class phase* phase_ptr =
phase_bsearch(gas_phase_ptr->Get_gas_comps()[j].Get_phase_name().c_str(), &i, FALSE);
add_elt_list(phase_ptr->next_elt, gas_phase_ptr->Get_gas_comps()[j].Get_moles());
}
}
if (pp_assemblage_ptr != NULL)
{
std::map<std::string, cxxPPassemblageComp>::iterator it;
it = pp_assemblage_ptr->Get_pp_assemblage_comps().begin();
for (; it != pp_assemblage_ptr->Get_pp_assemblage_comps().end(); it++)
{
int j;
class phase* phase_ptr = phase_bsearch(it->first.c_str(), &j, FALSE);
add_elt_list(phase_ptr->next_elt,
it->second.Get_moles());
}
}
elt_list_combine();
return (OK);
}
LDBLE Phreeqc::
iso_value(const char* total_name)
{
int j;
char token[MAX_LENGTH];
char my_total_name[MAX_LENGTH];
Utilities::strcpy_safe(token, MAX_LENGTH, "");
Utilities::strcpy_safe(my_total_name, MAX_LENGTH, total_name);
while (replace(" ", "_", my_total_name));
for (j = 0; j < (int)isotope_ratio.size(); j++)
{
if (isotope_ratio[j]->ratio == MISSING)
continue;
if (strcmp(my_total_name, isotope_ratio[j]->name) != 0)
continue;
return (isotope_ratio[j]->converted_ratio);
}
Utilities::strcpy_safe(my_total_name, MAX_LENGTH, total_name);
while (replace("[", "", my_total_name));
while (replace("]", "", my_total_name));
Utilities::strcat_safe(token, MAX_LENGTH, "R(");
Utilities::strcat_safe(token, MAX_LENGTH, my_total_name);
Utilities::strcat_safe(token, MAX_LENGTH, ")");
for (j = 0; j < (int)isotope_ratio.size(); j++)
{
if (isotope_ratio[j]->ratio == MISSING)
continue;
if (strcmp(token, isotope_ratio[j]->name) != 0)
continue;
return (isotope_ratio[j]->converted_ratio);
}
return -1000.;
}
char* Phreeqc::
iso_unit(const char* total_name)
{
int j;
char token[MAX_LENGTH], unit[MAX_LENGTH];
class master_isotope* master_isotope_ptr;
char my_total_name[MAX_LENGTH];
Utilities::strcpy_safe(token, MAX_LENGTH, "");
Utilities::strcpy_safe(my_total_name, MAX_LENGTH, total_name);
while (replace(" ", "_", my_total_name));
Utilities::strcpy_safe(unit, MAX_LENGTH, "unknown");
for (j = 0; j < (int)isotope_ratio.size(); j++)
{
if (isotope_ratio[j]->ratio == MISSING)
continue;
if (strcmp(my_total_name, isotope_ratio[j]->name) != 0)
continue;
master_isotope_ptr = master_isotope_search(isotope_ratio[j]->isotope_name);
if (master_isotope_ptr != NULL)
{
Utilities::strcpy_safe(unit, MAX_LENGTH, master_isotope_ptr->units);
}
return string_duplicate(unit);
}
Utilities::strcpy_safe(my_total_name, MAX_LENGTH, total_name);
while (replace("[", "", my_total_name));
while (replace("]", "", my_total_name));
Utilities::strcat_safe(token, MAX_LENGTH, "R(");
Utilities::strcat_safe(token, MAX_LENGTH, my_total_name);
Utilities::strcat_safe(token, MAX_LENGTH, ")");
for (j = 0; j < (int)isotope_ratio.size(); j++)
{
if (isotope_ratio[j]->ratio == MISSING)
continue;
if (strcmp(token, isotope_ratio[j]->name) != 0)
continue;
master_isotope_ptr = master_isotope_search(isotope_ratio[j]->isotope_name);
if (master_isotope_ptr != NULL)
{
Utilities::strcpy_safe(unit, MAX_LENGTH, master_isotope_ptr->units);
}
return string_duplicate(unit);
}
return string_duplicate(unit);
}
int Phreeqc::
basic_compile(const char* commands, void** lnbase, void** vbase, void** lpbase)
{
return this->basic_interpreter->basic_compile(commands, lnbase, vbase, lpbase);
}
int Phreeqc::
basic_run(char* commands, void* lnbase, void* vbase, void* lpbase)
{
return this->basic_interpreter->basic_run(commands, lnbase, vbase, lpbase);
}
void Phreeqc::
basic_free(void)
{
delete this->basic_interpreter;
this->basic_interpreter = NULL;
}
#if defined(SWIG) || defined(SWIG_IPHREEQC)
#include "BasicCallback.h"
double Phreeqc::
basic_callback(double x1, double x2, const char* str)
{
if (this->basicCallback)
{
return this->basicCallback->Callback(x1, x2, str);
}
return 0.0;
}
#else /* defined(SWIG) || defined(SWIG_IPHREEQC) */
#ifdef IPHREEQC_NO_FORTRAN_MODULE
double Phreeqc::
basic_callback(double x1, double x2, char* str)
#else
double Phreeqc::
basic_callback(double x1, double x2, const char* str)
#endif
{
double local_x1 = x1;
double local_x2 = x2;
if (basic_callback_ptr != NULL)
{
return (*basic_callback_ptr) (x1, x2, (const char*)str, basic_callback_cookie);
}
if (basic_fortran_callback_ptr != NULL)
{
#ifdef IPHREEQC_NO_FORTRAN_MODULE
return (*basic_fortran_callback_ptr) (&local_x1, &local_x2, str, (int)strlen(str));
#else
return (*basic_fortran_callback_ptr) (&local_x1, &local_x2, str, (int)strlen(str));
#endif
}
return 0;
}
void
Phreeqc::register_basic_callback(double (*fcn)(double x1, double x2, const char* str, void* cookie), void* cookie1)
{
this->basic_callback_ptr = fcn;
this->basic_callback_cookie = cookie1;
}
#ifdef IPHREEQC_NO_FORTRAN_MODULE
void
Phreeqc::register_fortran_basic_callback(double (*fcn)(double* x1, double* x2, char* str, size_t l))
{
this->basic_fortran_callback_ptr = fcn;
}
#else
void
Phreeqc::register_fortran_basic_callback(double (*fcn)(double* x1, double* x2, const char* str, int l))
{
this->basic_fortran_callback_ptr = fcn;
}
#endif
#endif /* defined(SWIG) || defined(SWIG_IPHREEQC) */