iphreeqc/KineticsComp.cxx
David L Parkhurst 91f650a5e9 Merged ErrorHandling 6119-6268 changes.
All reactant structs have been removed.
Tony's pressure uses mu in pressure term of log_k.
Test cases run, discriminant check at 1e-8.

Still want to optimize out some k_temp calls and checks for same T, P, mu.

git-svn-id: svn://136.177.114.72/svn_GW/phreeqc3/trunk@6269 1feff8c3-07ed-0310-ac33-dd36852eb9cd
2012-03-06 23:42:49 +00:00

365 lines
8.7 KiB
C++

// KineticsComp.cxx: implementation of the cxxKineticsComp class.
//
//////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
#pragma warning(disable : 4786) // disable truncation warning (Only used by debugger)
#endif
#include <cassert> // assert
#include <algorithm> // std::sort
#include "Utils.h" // define first
#include "Phreeqc.h"
#include "KineticsComp.h"
//#include "Dictionary.h"
#include "phqalloc.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
cxxKineticsComp::cxxKineticsComp(PHRQ_io *io)
:
PHRQ_base(io)
//
// default constructor for cxxKineticsComp
//
{
tol = 1e-8;
m = -1;
m0 = -1;
moles = 0.0;
initial_moles = 0;
namecoef.type = cxxNameDouble::ND_NAME_COEF;
}
cxxKineticsComp::~cxxKineticsComp()
{
}
#ifdef SKIP
void
cxxKineticsComp::dump_xml(std::ostream & s_oss, unsigned int indent) const const
{
unsigned int i;
s_oss.precision(DBL_DIG - 1);
std::string indent0(""), indent1(""), indent2("");
for (i = 0; i < indent; ++i)
indent0.append(Utilities::INDENT);
for (i = 0; i < indent + 1; ++i)
indent1.append(Utilities::INDENT);
for (i = 0; i < indent + 2; ++i)
indent2.append(Utilities::INDENT);
// Kinetics_Comp element and attributes
s_oss << indent0 << "formula=\"" << this->formula << "\"" << "\n";
s_oss << indent0 << "moles=\"" << this->moles << "\"" << "\n";
s_oss << indent0 << "la=\"" << this->la << "\"" << "\n";
s_oss << indent0 << "charge_balance=\"" << this->
charge_balance << "\"" << "\n";
if (this->phase_name != NULL)
{
s_oss << indent0 << "phase_name=\"" << this->
phase_name << "\"" << "\n";
}
if (this->rate_name != NULL)
{
s_oss << indent0 << "rate_name=\"" << this->
rate_name << "\"" << "\n";
}
s_oss << indent0 << "phase_proportion=\"" << this->
phase_proportion << "\"" << "\n";
// totals
s_oss << indent0;
s_oss << "<totals " << "\n";
this->totals.dump_xml(s_oss, indent + 1);
// formula_totals
s_oss << indent0;
s_oss << "<formula_totals " << "\n";
this->formula_totals.dump_xml(s_oss, indent + 1);
}
#endif
void
cxxKineticsComp::dump_raw(std::ostream & s_oss, unsigned int indent) const
{
unsigned int i;
s_oss.precision(DBL_DIG - 1);
std::string indent0(""), indent1(""), indent2("");
for (i = 0; i < indent; ++i)
indent0.append(Utilities::INDENT);
for (i = 0; i < indent + 1; ++i)
indent1.append(Utilities::INDENT);
for (i = 0; i < indent + 2; ++i)
indent2.append(Utilities::INDENT);
// Kinetics_Comp element and attributes
s_oss << indent1 << "# KINETICS_MODIFY candidate identifiers #\n";
s_oss << indent1 << "-tol " << this->tol << "\n";
s_oss << indent1 << "-m " << this->m << "\n";
s_oss << indent1 << "-m0 " << this->m0 << "\n";
// namecoef
s_oss << indent1;
s_oss << "-namecoef" << "\n";
this->namecoef.dump_raw(s_oss, indent + 2);
// d_params
s_oss << indent1;
s_oss << "-d_params" << "\n";
{
int i = 0;
s_oss << indent2;
for (std::vector < LDBLE >::const_iterator it = d_params.begin();
it != d_params.end(); it++)
{
if (i++ == 5)
{
s_oss << "\n";
s_oss << indent2;
i = 0;
}
s_oss << *it << " ";
}
s_oss << "\n";
}
s_oss << indent1 << "# KineticsComp workspace variables #\n";
s_oss << indent1 << "-moles " << this->moles << "\n";
s_oss << indent1 << "-initial_moles " << this->initial_moles << "\n";
}
void
cxxKineticsComp::read_raw(CParser & parser, bool check)
{
std::string str;
static std::vector < std::string > vopts;
if (vopts.empty())
{
vopts.reserve(10);
vopts.push_back("rate_name_not_used"); // 0
vopts.push_back("tol"); // 1
vopts.push_back("m"); // 2
vopts.push_back("m0"); // 3
vopts.push_back("moles"); // 4
vopts.push_back("namecoef"); // 5
vopts.push_back("d_params"); // 6
vopts.push_back("initial_moles"); // 7
}
std::istream::pos_type ptr;
std::istream::pos_type next_char;
std::string token;
int opt_save;
std::vector < LDBLE > temp_d_params;
opt_save = CParser::OPT_ERROR;
bool tol_defined(false);
bool m_defined(false);
bool m0_defined(false);
bool moles_defined(false);
bool d_params_defined(false);
for (;;)
{
int opt = parser.get_option(vopts, next_char);
if (opt == CParser::OPT_DEFAULT)
{
opt = opt_save;
}
switch (opt)
{
case CParser::OPT_EOF:
break;
case CParser::OPT_KEYWORD:
break;
case CParser::OPT_DEFAULT:
case CParser::OPT_ERROR:
opt = CParser::OPT_KEYWORD;
// Allow return to Kinetics for more processing
break;
case 0: // rate_name not used
parser.warning_msg("Rate_name ignored. Define in -comp.");
break;
case 1: // tol
if (!(parser.get_iss() >> this->tol))
{
this->tol = 0;
parser.incr_input_error();
parser.error_msg("Expected numeric value for tol.",
PHRQ_io::OT_CONTINUE);
}
tol_defined = true;
break;
case 2: // m
if (!(parser.get_iss() >> this->m))
{
this->m = 0;
parser.incr_input_error();
parser.error_msg("Expected numeric value for m.",
PHRQ_io::OT_CONTINUE);
}
m_defined = true;
break;
case 3: // m0
if (!(parser.get_iss() >> this->m0))
{
this->m0 = 0;
parser.incr_input_error();
parser.error_msg("Expected numeric value for m0.",
PHRQ_io::OT_CONTINUE);
}
m0_defined = true;
break;
case 4: // moles
if (!(parser.get_iss() >> this->moles))
{
this->moles = 0;
parser.incr_input_error();
parser.error_msg("Expected numeric value for moles.",
PHRQ_io::OT_CONTINUE);
}
moles_defined = true;
break;
case 5: // namecoef
if (this->namecoef.read_raw(parser, next_char) !=
CParser::PARSER_OK)
{
parser.incr_input_error();
parser.
error_msg
("Expected element name and molality for namecoef.",
PHRQ_io::OT_CONTINUE);
}
opt_save = 5;
break;
case 6: // d_params
while (parser.copy_token(token, next_char) == CParser::TT_DIGIT)
{
double dd;
sscanf(token.c_str(), "%lf", &dd);
temp_d_params.push_back((LDBLE) dd);
d_params_defined = true;
}
opt_save = 6;
break;
case 7: // initial_moles
if (!(parser.get_iss() >> this->initial_moles))
{
this->moles = 0;
parser.incr_input_error();
parser.error_msg("Expected numeric value for initial_moles.",
PHRQ_io::OT_CONTINUE);
}
break;
}
if (opt == CParser::OPT_EOF || opt == CParser::OPT_KEYWORD)
break;
}
if (d_params_defined)
{
this->d_params = temp_d_params;
}
if (check)
{
// members that must be defined
if (tol_defined == false)
{
parser.incr_input_error();
parser.error_msg("Tol not defined for KineticsComp input.",
PHRQ_io::OT_CONTINUE);
}
if (m_defined == false)
{
parser.incr_input_error();
parser.error_msg("M not defined for KineticsComp input.",
PHRQ_io::OT_CONTINUE);
}
if (m0_defined == false)
{
parser.incr_input_error();
parser.error_msg("M0 not defined for KineticsComp input.",
PHRQ_io::OT_CONTINUE);
}
}
}
#ifdef USE_MPI
void
cxxKineticsComp::mpi_pack(std::vector < int >&ints,
std::vector < LDBLE >&doubles)
{
extern cxxDictionary dictionary;
ints.push_back(dictionary.string2int(this->rate_name));
this->namecoef.mpi_pack(ints, doubles);
doubles.push_back(this->tol);
doubles.push_back(this->m);
doubles.push_back(this->m0);
doubles.push_back(this->moles);
ints.push_back((int) this->d_params.size());
for (std::vector < LDBLE >::iterator it = this->d_params.begin();
it != this->d_params.end(); it++)
{
doubles.push_back(*it);
}
}
void
cxxKineticsComp::mpi_unpack(int *ints, int *ii, LDBLE *doubles, int *dd)
{
extern cxxDictionary dictionary;
int i = *ii;
int d = *dd;
this->rate_name = dictionary.int2stdstring(ints[i++]);
this->namecoef.mpi_unpack(ints, &i, doubles, &d);
this->tol = doubles[d++];
this->m = doubles[d++];
this->m0 = doubles[d++];
this->moles = doubles[d++];
int n = ints[i++];
this->d_params.clear();
for (int j = 0; j < n; j++)
{
this->d_params.push_back(doubles[d++]);
}
*ii = i;
*dd = d;
}
#endif
void
cxxKineticsComp::add(const cxxKineticsComp & addee, LDBLE extensive)
{
if (extensive == 0.0)
return;
if (addee.rate_name.size() == 0)
return;
// this and addee must have same name
// otherwise generate a new KineticsComp with multiply
if (this->rate_name.size() == 0 && addee.rate_name.size() == 0)
{
return;
}
assert(this->rate_name == addee.rate_name);
this->m += addee.m * extensive;
this->m0 += addee.m0 * extensive;
this->moles += addee.moles * extensive;
}
void
cxxKineticsComp::multiply(LDBLE extensive)
{
this->m *= extensive;
this->m0 *= extensive;
this->moles *= extensive;
}