iphreeqc/phreeqcpp/NameDouble.cxx
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

538 lines
12 KiB
C++

// NameDouble.cxx: implementation of the cxxNameDouble class.
//
//////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
#pragma warning(disable : 4786) // disable truncation warning (Only used by debugger)
#endif
#include <cassert> // assert
#include <algorithm> // std::sort
#include <map> // std::sort
#include <iostream> // std::cout std::cerr
#include "Utils.h" // define first
#include "Phreeqc.h"
#include "NameDouble.h"
#include "Dictionary.h"
//#include "Dictionary.h"
#include "phqalloc.h"
#include "ISolutionComp.h"
#if defined(PHREEQCI_GUI)
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
cxxNameDouble::cxxNameDouble()
//
// default constructor for cxxNameDouble
//
{
this->type = ND_ELT_MOLES;
}
cxxNameDouble::cxxNameDouble(const std::vector<class elt_list>& el)
// constructor for cxxNameDouble from vector of elt_list
{
size_t i;
const class elt_list* elt_list_ptr = &el[0];
for (i = 0; elt_list_ptr[i].elt != NULL; i++)
{
(*this)[elt_list_ptr[i].elt->name] = elt_list_ptr[i].coef;
}
this->type = ND_ELT_MOLES;
}
cxxNameDouble::cxxNameDouble(const cxxNameDouble & old, LDBLE factor)
//
// constructor for cxxNameDouble from list of elt_list
//
{
for (cxxNameDouble::const_iterator it = old.begin(); it != old.end();
it++)
{
if (old.type == ND_ELT_MOLES)
{
if (it->second * factor > 0)
{
(*this)[(it->first)] = it->second * factor;
}
}
else
{
(*this)[(it->first)] = it->second * factor;
}
}
this->type = old.type;
}
cxxNameDouble::cxxNameDouble(std::map < std::string, cxxISolutionComp > &comps)
//
// constructor for cxxNameDouble from map of cxxISolutionComp
//
{
std::map < std::string, cxxISolutionComp >::iterator it;
for (it = comps.begin(); it != comps.end(); it++)
{
(*this)[it->first] = it->second.Get_moles();
}
this->type = ND_ELT_MOLES;
}
cxxNameDouble::cxxNameDouble(class name_coef *nc, int count)
//
// constructor for cxxNameDouble from list of elt_list
//
{
int i;
for (i = 0; i < count; i++)
{
if (nc[i].name == NULL)
continue;
if ((*this).find(nc[i].name) == (*this).end())
{
(*this)[nc[i].name] = nc[i].coef;
}
else
{
(*this)[nc[i].name] = (*this).find(nc[i].name)->second + nc[i].coef;
}
}
this->type = ND_NAME_COEF;
}
cxxNameDouble::~cxxNameDouble()
{
}
void
cxxNameDouble::dump_xml(std::ostream & s_oss, unsigned int indent) const
{
unsigned int i;
s_oss.precision(DBL_DIG - 1);
std::string indent0(""), indent1("");
for (i = 0; i < indent; ++i)
indent0.append(Utilities::INDENT);
for (i = 0; i < indent + 1; ++i)
indent1.append(Utilities::INDENT);
std::string xmlElement, xmlAtt1, xmlAtt2;
switch ((*this).type)
{
case cxxNameDouble::ND_SPECIES_LA:
xmlElement = "<soln_m_a ";
xmlAtt1 = " m_a_desc=\"";
xmlAtt1 = " m_a_la=\"";
break;
case cxxNameDouble::ND_SPECIES_GAMMA:
xmlElement = "<soln_s_g ";
xmlAtt1 = " m_a_desc=\"";
xmlAtt1 = " m_a_la=\"";
break;
case cxxNameDouble::ND_ELT_MOLES:
xmlElement = "<soln_total ";
xmlAtt1 = " conc_desc=\"";
xmlAtt1 = " conc_moles=\"";
break;
case cxxNameDouble::ND_NAME_COEF:
xmlElement = "<NameCoef ";
xmlAtt1 = " name=\"";
xmlAtt1 = " coef=\"";
break;
}
for (const_iterator it = (*this).begin(); it != (*this).end(); it++)
{
s_oss << indent0;
s_oss << xmlElement << xmlAtt1 << it->first << xmlAtt2 << it->
second << "/>" << "\n";
}
}
void
cxxNameDouble::dump_raw(std::ostream & s_oss, unsigned int indent) const
{
unsigned int i;
s_oss.precision(DBL_DIG - 1);
std::string indent0("");
for (i = 0; i < indent; ++i)
indent0.append(Utilities::INDENT);
for (const_iterator it = (*this).begin(); it != (*this).end(); it++)
{
s_oss << indent0;
if (it->first.size() < 29 - indent0.size())
{
s_oss << Utilities::pad_right(it->first, 29 - indent0.size()) << it->second << "\n";
}
else
{
s_oss << Utilities::pad_right(it->first, it->first.size() + indent0.size()) << " " << it->second << "\n";
}
}
}
CParser::STATUS_TYPE cxxNameDouble::read_raw(CParser & parser,
std::istream::pos_type & pos)
{
std::string token;
LDBLE
d;
CParser::TOKEN_TYPE j;
j = parser.copy_token(token, pos);
if (j == CParser::TT_EMPTY)
return CParser::PARSER_OK;
if (!(parser.get_iss() >> d))
{
return CParser::PARSER_ERROR;
}
(*this)[token.c_str()] = d;
return CParser::PARSER_OK;
}
void
cxxNameDouble::add_extensive(const cxxNameDouble & addee, LDBLE factor)
//
// Sums two name doubles, this + factor*nd2
//
{
if (factor == 0)
return;
for (cxxNameDouble::const_iterator it = addee.begin(); it != addee.end();
it++)
{
cxxNameDouble::iterator current = (*this).find(it->first);
if (current != (*this).end())
{
(*this)[it->first] = current->second + it->second * factor;
}
else
{
(*this)[it->first] = it->second * factor;
}
}
}
void
cxxNameDouble::add_intensive(const cxxNameDouble & addee, LDBLE f1,
LDBLE f2)
//
// Sums two name doubles, this*f1 + f2*nd2
//
{
assert(f1 >= 0 && f2 >= 0);
for (cxxNameDouble::const_iterator it = addee.begin(); it != addee.end();
it++)
{
cxxNameDouble::iterator current = (*this).find(it->first);
if (current != (*this).end())
{
(*this)[it->first] = f1 * current->second + f2 * it->second;
}
else
{
(*this)[it->first] = f2 * it->second;
}
}
}
void
cxxNameDouble::add_log_activities(const cxxNameDouble & addee, LDBLE f1,
LDBLE f2)
//
// Sums two name doubles, this*f1 + f2*nd2, assuming log values
//
{
assert(f1 >= 0 && f2 >= 0);
for (cxxNameDouble::const_iterator it = addee.begin(); it != addee.end();
it++)
{
cxxNameDouble::iterator current = (*this).find(it->first);
if (current != (*this).end())
{
LDBLE a1 = pow((LDBLE) 10., current->second);
LDBLE a2 = pow((LDBLE) 10., it->second);
(*this)[it->first] = log10(f1 * a1 + f2 * a2);
}
else
{
(*this)[it->first] = it->second + log10(f2);
}
}
}
cxxNameDouble
cxxNameDouble::Simplify_redox(void) const
{
cxxNameDouble const &nd = *this;
std::basic_string < char >::size_type indexCh;
cxxNameDouble new_totals;
new_totals.type = cxxNameDouble::ND_ELT_MOLES;
{
std::string current_ename;
std::string const *ename_ptr;
cxxNameDouble::const_iterator it;
// make list of elements in new_totals
for (it = nd.begin(); it != nd.end(); ++it)
{
current_ename = it->first;
if (it->first.size() < 4)
{
ename_ptr = &(it->first);
}
else
{
indexCh = it->first.find("(");
if (indexCh != std::string::npos)
{
current_ename = it->first.substr(0, indexCh);
ename_ptr = &(current_ename);
}
else
{
ename_ptr = &(it->first);
}
}
if (current_ename == "H" || current_ename == "O" || current_ename == "Charge")
continue;
new_totals[*ename_ptr] = 0;
}
}
// sum totals for elements
{
cxxNameDouble::const_iterator old_it = nd.begin();
cxxNameDouble::iterator new_it = new_totals.begin();
std::string old_ename;
std::string const *old_ename_ptr;
while (old_it != nd.end() && new_it != new_totals.end())
{
if (old_it->first.size() < 4)
{
old_ename_ptr = &old_it->first;
}
else
{
indexCh = old_it->first.find("(");
if (indexCh != std::string::npos)
{
old_ename = old_it->first.substr(0, indexCh);
old_ename_ptr = &old_ename;
}
else
{
old_ename_ptr = &old_it->first;
}
}
int j = strcmp(new_it->first.c_str(), old_ename_ptr->c_str());
if (j < 0)
{
new_it++;
}
else if (j == 0)
{
new_it->second += old_it->second;
old_it++;
}
else
{
old_it++;
}
}
}
return new_totals;
}
void
cxxNameDouble::Multiply_activities_redox(std::string str, LDBLE f)
{
// update original master_activities using just computed factors
cxxNameDouble::iterator it;
LDBLE lg_f = log10(f);
std::string redox_name = str;
redox_name.append("(");
for (it = this->begin(); it != this->end(); it++)
{
if (str[0] > it->first[0]) continue;
if (it->first == str)
{
// Found exact match
it->second += lg_f;
}
else
{
// no exact match, current is element name, need to find all valences
if (strstr(it->first.c_str(), redox_name.c_str()) == it->first.c_str())
{
it->second += lg_f;
}
}
if (str[0] < it->first[0]) break;
}
}
LDBLE
cxxNameDouble::Get_total_element(const char *string) const
{
cxxNameDouble::const_iterator it;
LDBLE d = 0.0;
for (it = this->begin(); it != this->end(); ++it)
{
// C++ way to do it
std::string ename(string);
std::string current_ename(it->first);
std::basic_string < char >::size_type indexCh;
indexCh = current_ename.find("(");
if (indexCh != std::string::npos)
{
current_ename = current_ename.substr(0, indexCh);
}
if (current_ename == ename)
{
d += it->second;
}
}
return (d);
}
void
cxxNameDouble::add(const char *token, LDBLE total)
//
// add to total for a specified element
//
{
char key[MAX_LENGTH];
Utilities::strcpy_safe(key, MAX_LENGTH, token);
cxxNameDouble::iterator current = (*this).find(key);
if (current != (*this).end())
{
(*this)[key] = current->second + total;
}
else
{
(*this)[key] = total;
}
}
void
cxxNameDouble::multiply(LDBLE extensive)
{
//
// Multiplies by extensive
//
for (cxxNameDouble::iterator it = this->begin(); it != this->end(); it++)
{
it->second *= extensive;
}
}
void
cxxNameDouble::merge_redox(const cxxNameDouble & source)
//
// Merges source into this
// Accounts for possible conflicts between redox state and
// totals
//
{
for (cxxNameDouble::const_iterator sit = source.begin(); sit != source.end(); sit++)
{
std::string redox_name = sit->first;
std::string elt_name;
size_t pos = redox_name.find("(");
bool redox;
if (pos != std::string::npos)
{
redox = true;
elt_name = redox_name.substr(0, pos - 1);
}
else
{
redox = false;
elt_name = redox_name;
}
if (redox)
{
// Remove elt_name, if present
if ((*this).find(elt_name) != (*this).end())
{
(*this).erase((*this).find(elt_name));
}
// Put in redox name
(*this)[redox_name] = sit->second;
}
else
{
std::string substring;
substring.append(elt_name);
substring.append("(");
// Remove all redox
bool deleted = true;
while (deleted)
{
deleted = false;
cxxNameDouble::iterator current = (*this).begin();
for ( ; current != (*this).end(); current++)
{
if (current->first.find(substring) == 0)
{
(*this).erase(current);
deleted = true;
break;
}
}
}
// Put in elt name
(*this)[elt_name] = sit->second;
}
}
}
struct DblCmp {
bool operator()(const std::pair<std::string, LDBLE> &lhs, const std::pair<std::string, LDBLE> &rhs)
{
return lhs.second > rhs.second;
}
};
std::vector< std::pair<std::string, LDBLE> >
cxxNameDouble::sort_second(void)
{
std::vector< std::pair<std::string, LDBLE> > myvec(this->begin(), this->end());
std::sort(myvec.begin(), myvec.end(), DblCmp());
return myvec;
}
void
cxxNameDouble::Serialize(Dictionary &dictionary, std::vector < int >&ints,
std::vector < double >&doubles)
{
ints.push_back((int) (*this).size());
for (const_iterator it = (*this).begin(); it != (*this).end(); it++)
{
int n = dictionary.Find(it->first);
ints.push_back(n);
doubles.push_back(it->second);
}
}
void
cxxNameDouble::Deserialize(Dictionary &dictionary, std::vector<int> &ints, std::vector<double> &doubles, int &ii, int &dd)
{
this->clear();
int count = ints[ii++];
for (int j = 0; j < count; j++)
{
int n = ints[ii++];
assert(n >= 0);
std::string str = dictionary.GetWords()[n];
if (str.size() != 0)
{
(*this)[str] = doubles[dd++];
}
}
}