// NameDouble.cxx: implementation of the cxxNameDouble class. // ////////////////////////////////////////////////////////////////////// #ifdef _DEBUG #pragma warning(disable : 4786) // disable truncation warning (Only used by debugger) #endif #include // assert #include // std::sort #include // std::sort #include // 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" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// cxxNameDouble::cxxNameDouble() // // default constructor for cxxNameDouble // { this->type = ND_ELT_MOLES; } cxxNameDouble::cxxNameDouble(const std::vector& 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 = "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]; strcpy(key, 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 &lhs, const std::pair &rhs) { return lhs.second > rhs.second; } }; std::vector< std::pair > cxxNameDouble::sort_second(void) { std::vector< std::pair > 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 &ints, std::vector &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++]; } } }