diff --git a/src/phast/PhreeqcRM/database/Amm.dat b/src/phast/PhreeqcRM/database/Amm.dat index c7169124..1b06f4d3 100644 --- a/src/phast/PhreeqcRM/database/Amm.dat +++ b/src/phast/PhreeqcRM/database/Amm.dat @@ -44,7 +44,7 @@ N(+5) NO3- 0 NO3 N(+3) NO2- 0 NO2 N(0) N2 0 N #N(-3) NH4+ 0 NH4 14.0067 -Amm AmmH+ 0 AmmH 17.031 +Amm AmmH+ 0 Amm 17.031 B H3BO3 0 B 10.81 P PO4-3 2 P 30.9738 F F- 0 F 18.9984 diff --git a/src/phast/PhreeqcRM/database/phreeqc.dat b/src/phast/PhreeqcRM/database/phreeqc.dat index 04fe478e..f925376f 100644 --- a/src/phast/PhreeqcRM/database/phreeqc.dat +++ b/src/phast/PhreeqcRM/database/phreeqc.dat @@ -44,7 +44,7 @@ N(+5) NO3- 0 N N(+3) NO2- 0 N N(0) N2 0 N N(-3) NH4+ 0 N 14.0067 -#Amm AmmH+ 0 AmmH 17.031 +#Amm AmmH+ 0 Amm 17.031 B H3BO3 0 B 10.81 P PO4-3 2 P 30.9738 F F- 0 F 18.9984 diff --git a/src/phast/PhreeqcRM/database/phreeqc_rates.dat b/src/phast/PhreeqcRM/database/phreeqc_rates.dat index d5e2fbe5..280ee03c 100644 --- a/src/phast/PhreeqcRM/database/phreeqc_rates.dat +++ b/src/phast/PhreeqcRM/database/phreeqc_rates.dat @@ -44,7 +44,7 @@ N(+5) NO3- 0 N N(+3) NO2- 0 N N(0) N2 0 N N(-3) NH4+ 0 N 14.0067 -#Amm AmmH+ 0 AmmH 17.031 +#Amm AmmH+ 0 Amm 17.031 B H3BO3 0 B 10.81 P PO4-3 2 P 30.9738 F F- 0 F 18.9984 diff --git a/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.cpp b/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.cpp index f0923558..1ccf4126 100644 --- a/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.cpp +++ b/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.cpp @@ -1548,6 +1548,14 @@ listtokens(FILE * f, tokenrec * l_buf) case tokspecies_formula_: output_msg("SPECIES_FORMULA$"); break; + case tokphase_equation: + case tokphase_equation_: + output_msg("PHASE_EQUATION$"); + break; + case tokspecies_equation: + case tokspecies_equation_: + output_msg("SPECIES_EQUATION$"); + break; case toksr: output_msg("SR"); break; @@ -4080,6 +4088,202 @@ factor(struct LOC_exec * LINK) } break; + case tokphase_equation: + case tokphase_equation_: + { + require(toklp, LINK); + std::string phase_name(stringfactor(STR1, LINK)); + varrec* elts_varrec = NULL, * coef_varrec = NULL; + std::vector > stoichiometry; + /* + * Parse arguments + */ + require(tokcomma, LINK); + + count_varrec = LINK->t->UU.vp; + if (LINK->t->kind != tokvar || count_varrec->stringvar != 0) + snerr(": Cannot find count variable"); + + /* return number of names of species */ + LINK->t = LINK->t->next; + require(tokcomma, LINK); + elts_varrec = LINK->t->UU.vp; + if (LINK->t->kind != tokvar || elts_varrec->stringvar != 1) + snerr(": Cannot find species string variable"); + + /* return coefficients of species */ + LINK->t = LINK->t->next; + require(tokcomma, LINK); + coef_varrec = LINK->t->UU.vp; + if (LINK->t->kind != tokvar || coef_varrec->stringvar != 0) + snerr(": Cannot find coefficient variable"); + LINK->t = LINK->t->next; + + require(tokrp, LINK); + + free_dim_stringvar(elts_varrec); + PhreeqcPtr->free_check_null(coef_varrec->UU.U0.arr); + coef_varrec->UU.U0.arr = NULL; + /* + * Call subroutine + */ + std::string eq = PhreeqcPtr->phase_equation(phase_name, stoichiometry); + + // put type as return value + n.stringval = true; + n.UU.sval = PhreeqcPtr->string_duplicate(eq.c_str()); + + /* + * fill in varrec structure + */ + + size_t count = stoichiometry.size(); + *count_varrec->UU.U0.val = (LDBLE)count; + /* + * malloc space + */ + elts_varrec->UU.U1.sarr = (char**)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(char*)); + if (elts_varrec->UU.U1.sarr == NULL) + { + PhreeqcPtr->malloc_error(); +#if !defined(R_SO) + exit(4); +#endif + } + coef_varrec->UU.U0.arr = (LDBLE*)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(LDBLE)); + if (coef_varrec->UU.U0.arr == NULL) + { + PhreeqcPtr->malloc_error(); +#if !defined(R_SO) + exit(4); +#endif + } + + // first position not used + elts_varrec->UU.U1.sarr[0] = NULL; + coef_varrec->UU.U0.arr[0] = 0; + + // set dims for Basic array + for (i = 0; i < maxdims; i++) + { + elts_varrec->dims[i] = 0; + coef_varrec->dims[i] = 0; + } + // set dims for first dimension and number of dims + elts_varrec->dims[0] = (long)(count + 1); + coef_varrec->dims[0] = (long)(count + 1); + elts_varrec->numdims = 1; + coef_varrec->numdims = 1; + + // fill in arrays + i = 1; + for (std::vector >::iterator it = stoichiometry.begin(); it != stoichiometry.end(); it++) + { + elts_varrec->UU.U1.sarr[i] = PhreeqcPtr->string_duplicate((it->first).c_str()); + coef_varrec->UU.U0.arr[i] = it->second; + i++; + } + } + break; + + case tokspecies_equation: + case tokspecies_equation_: + { + require(toklp, LINK); + std::string species_name(stringfactor(STR1, LINK)); + varrec* elts_varrec = NULL, * coef_varrec = NULL; + std::vector > stoichiometry; + /* + * Parse arguments + */ + require(tokcomma, LINK); + + count_varrec = LINK->t->UU.vp; + if (LINK->t->kind != tokvar || count_varrec->stringvar != 0) + snerr(": Cannot find count variable"); + + /* return number of names of species */ + LINK->t = LINK->t->next; + require(tokcomma, LINK); + elts_varrec = LINK->t->UU.vp; + if (LINK->t->kind != tokvar || elts_varrec->stringvar != 1) + snerr(": Cannot find species string variable"); + + /* return coefficients of species */ + LINK->t = LINK->t->next; + require(tokcomma, LINK); + coef_varrec = LINK->t->UU.vp; + if (LINK->t->kind != tokvar || coef_varrec->stringvar != 0) + snerr(": Cannot find coefficient variable"); + LINK->t = LINK->t->next; + + require(tokrp, LINK); + + free_dim_stringvar(elts_varrec); + PhreeqcPtr->free_check_null(coef_varrec->UU.U0.arr); + coef_varrec->UU.U0.arr = NULL; + /* + * Call subroutine + */ + std::string eq = PhreeqcPtr->species_equation(species_name, stoichiometry); + + // put type as return value + n.stringval = true; + n.UU.sval = PhreeqcPtr->string_duplicate(eq.c_str()); + + /* + * fill in varrec structure + */ + + size_t count = stoichiometry.size(); + *count_varrec->UU.U0.val = (LDBLE)count; + /* + * malloc space + */ + elts_varrec->UU.U1.sarr = (char**)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(char*)); + if (elts_varrec->UU.U1.sarr == NULL) + { + PhreeqcPtr->malloc_error(); +#if !defined(R_SO) + exit(4); +#endif + } + coef_varrec->UU.U0.arr = (LDBLE*)PhreeqcPtr->PHRQ_malloc((count + 1) * sizeof(LDBLE)); + if (coef_varrec->UU.U0.arr == NULL) + { + PhreeqcPtr->malloc_error(); +#if !defined(R_SO) + exit(4); +#endif + } + + // first position not used + elts_varrec->UU.U1.sarr[0] = NULL; + coef_varrec->UU.U0.arr[0] = 0; + + // set dims for Basic array + for (i = 0; i < maxdims; i++) + { + elts_varrec->dims[i] = 0; + coef_varrec->dims[i] = 0; + } + // set dims for first dimension and number of dims + elts_varrec->dims[0] = (long)(count + 1); + coef_varrec->dims[0] = (long)(count + 1); + elts_varrec->numdims = 1; + coef_varrec->numdims = 1; + + // fill in arrays + i = 1; + for (std::vector >::iterator it = stoichiometry.begin(); it != stoichiometry.end(); it++) + { + elts_varrec->UU.U1.sarr[i] = PhreeqcPtr->string_duplicate((it->first).c_str()); + coef_varrec->UU.U0.arr[i] = it->second; + i++; + } + } + break; + case toksr: { const char* str = stringfactor(STR1, LINK); @@ -8088,6 +8292,10 @@ const std::map::value_type temp_tokens[] std::map::value_type("soln_vol", PBasic::toksoln_vol), std::map::value_type("species_formula", PBasic::tokspecies_formula), std::map::value_type("species_formula$", PBasic::tokspecies_formula_), + std::map::value_type("phase_equation", PBasic::tokphase_equation), + std::map::value_type("phase_equation$", PBasic::tokphase_equation_), + std::map::value_type("species_equation", PBasic::tokspecies_equation), + std::map::value_type("species_equation$", PBasic::tokspecies_equation_), std::map::value_type("sr", PBasic::toksr), std::map::value_type("step_no", PBasic::tokstep_no), std::map::value_type("str_e$", PBasic::tokstr_e_), diff --git a/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.h b/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.h index 231bae56..4a04ce9e 100644 --- a/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.h +++ b/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.h @@ -323,6 +323,10 @@ class PBasic: public PHRQ_base toksoln_vol, tokspecies_formula, tokspecies_formula_, + tokphase_equation, + tokphase_equation_, + tokspecies_equation, + tokspecies_equation_, toksr, tokstep_no, tokstr_e_, diff --git a/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Phreeqc.h b/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Phreeqc.h index be150845..86b6bfff 100644 --- a/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Phreeqc.h +++ b/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Phreeqc.h @@ -167,6 +167,8 @@ class Phreeqc std::string kinetics_formula(std::string kinetics_name, cxxNameDouble& stoichiometry); std::string phase_formula(std::string phase_name, cxxNameDouble& stoichiometry); std::string species_formula(std::string phase_name, cxxNameDouble& stoichiometry); + std::string phase_equation(std::string phase_name, std::vector >& stoichiometry); + std::string species_equation(std::string species_name, std::vector >& stoichiometry); LDBLE list_ss(std::string ss_name, cxxNameDouble& composition); int system_total_elements(void); int system_total_si(void); diff --git a/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/basicsubs.cpp b/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/basicsubs.cpp index a9305f73..d49141da 100644 --- a/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/basicsubs.cpp +++ b/src/phast/PhreeqcRM/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/basicsubs.cpp @@ -3009,6 +3009,109 @@ species_formula(std::string phase_name, cxxNameDouble& stoichiometry) return (formula); } +/* ---------------------------------------------------------------------- */ +std::string Phreeqc:: +phase_equation(std::string phase_name, std::vector >& stoichiometry) +/* ---------------------------------------------------------------------- */ +{ + /* + * Returns equation + * Also returns arrays of species and stoichiometry in stoichiometry + */ + stoichiometry.clear(); + std::ostringstream eq, lhs, rhs; + int j = -1; + class phase* phase_ptr = phase_bsearch(phase_name.c_str(), &j, FALSE); + bool rhs_started = false; + bool lhs_started = false; + if (phase_ptr != NULL) + { + std::vector::iterator it = phase_ptr->rxn.Get_tokens().begin(); + for (; it->name != NULL; it++) + { + if (!lhs_started) + { + std::pair item(phase_ptr->formula, it->coef); + stoichiometry.push_back(item); + } + else + { + std::pair item(it->name, it->coef); + stoichiometry.push_back(item); + } + if (it->coef < 0.0) + { + if (lhs_started) lhs << "+ "; + if (it->coef != -1.0) + { + lhs << -it->coef; + } + lhs << it->name << " "; + lhs_started = true; + } + else if (it->coef > 0.0) + { + if (rhs_started) rhs << "+ "; + if (it->coef != 1.0) + { + rhs << it->coef; + } + rhs << it->name << " "; + rhs_started = true; + } + } + } + eq << lhs.str() << "= " << rhs.str(); + return (eq.str()); +} + +/* ---------------------------------------------------------------------- */ +std::string Phreeqc:: +species_equation(std::string species_name, std::vector >& stoichiometry) +/* ---------------------------------------------------------------------- */ +{ + /* + * Returns equation + * Also returns arrays of species and stoichiometry in stoichiometry + */ + stoichiometry.clear(); + std::ostringstream eq, lhs, rhs;; + class species* s_ptr = s_search(species_name.c_str()); + bool rhs_started = false; + bool lhs_started = false; + if (s_ptr != NULL) + { + std::vector::iterator it = s_ptr->rxn.Get_tokens().begin(); + for ( ; it->name != NULL; it++) + { + std::pair item(it->name, it->coef); + stoichiometry.push_back(item); + if (it->coef > 0.0) + { + if (lhs_started) lhs << "+ "; + if (it->coef != 1.0) + { + lhs << it->coef; + } + lhs << it->name << " "; + lhs_started = true; + } + else if (it->coef < 0.0) + { + if (rhs_started) rhs << "+ "; + if (it->coef != -1.0) + { + rhs << -it->coef; + } + rhs << it->name << " "; + rhs_started = true; + } + } + } + eq << lhs.str() << "= " << rhs.str(); + return (eq.str()); +} + /* ---------------------------------------------------------------------- */ int Phreeqc:: system_total_elements(void)