void MineralEQ3::initThermoXML(XML_Node& phaseNode, const std::string& id_) { // Find the Thermo XML node if (!phaseNode.hasChild("thermo")) { throw CanteraError("HMWSoln::initThermoXML", "no thermo XML node"); } const XML_Node* xsp = speciesData()[0]; XML_Node* aStandardState = 0; if (xsp->hasChild("standardState")) { aStandardState = &xsp->child("standardState"); } else { throw CanteraError("MineralEQ3::initThermoXML", "no standard state mode"); } doublereal volVal = 0.0; if (aStandardState->attrib("model") != "constantVolume") { throw CanteraError("MineralEQ3::initThermoXML", "wrong standard state mode"); } if (aStandardState->hasChild("V0_Pr_Tr")) { XML_Node& aV = aStandardState->child("V0_Pr_Tr"); double Afactor = toSI("cm3/gmol"); if (aV.hasAttrib("units")) { Afactor = toSI(aV.attrib("units")); } volVal = getFloat(*aStandardState, "V0_Pr_Tr"); m_V0_pr_tr= volVal; volVal *= Afactor; } else { throw CanteraError("MineralEQ3::initThermoXML", "wrong standard state mode"); } setDensity(molecularWeight(0) / volVal); const XML_Node& MinEQ3node = xsp->child("thermo").child("MinEQ3"); m_deltaG_formation_pr_tr = getFloat(MinEQ3node, "DG0_f_Pr_Tr", "actEnergy") / actEnergyToSI("cal/gmol"); m_deltaH_formation_pr_tr = getFloat(MinEQ3node, "DH0_f_Pr_Tr", "actEnergy") / actEnergyToSI("cal/gmol"); m_Entrop_pr_tr = getFloat(MinEQ3node, "S0_Pr_Tr", "toSI") / toSI("cal/gmol/K"); m_a = getFloat(MinEQ3node, "a", "toSI") / toSI("cal/gmol/K"); m_b = getFloat(MinEQ3node, "b", "toSI") / toSI("cal/gmol/K2"); m_c = getFloat(MinEQ3node, "c", "toSI") / toSI("cal-K/gmol"); convertDGFormation(); }
/* * Returns a doublereal value for the child named 'name' of element 'parent'. If * 'type' is supplied and matches a known unit type, unit * conversion to SI will be done if the child element has an attribute * 'units'. * * * * Example: * * Code snipet: * @verbatim const XML_Node &State_XMLNode; doublereal pres = OneAtm; bool exists = getOptionalFloat(State_XMLNode, "pressure", pres, "toSI"); @endverbatim * * reads the corresponding XML file: * @verbatim <state> <pressure units="Pa"> 101325.0 </pressure> <\state> @endverbatim * * @param parent reference to the XML_Node object of the parent XML element * @param name Name of the XML child element * @param fltRtn Float Return. It will be overridden if the XML * element exists. * @param type String type. Currently known types are "toSI" * and "actEnergy", * and "" , for no conversion. The default value is "", * which implies that no conversion is allowed. * * @return returns true if the child element named "name" exists */ doublereal getFloatDefaultUnits(const Cantera::XML_Node& parent, std::string name, std::string defaultUnits, std::string type) { doublereal fctr = 1.0; if (defaultUnits == "") { throw CanteraError("getFloatDefaultUnits", "need to supply an actual value of defaultUnits"); } if (type == "actEnergy") { fctr = actEnergyToSI(defaultUnits); } else if (type == "toSI") { fctr = toSI(defaultUnits); } else if (defaultUnits == "temperature") { fctr = toSI(defaultUnits); } else if (type == "density") { fctr = toSI(defaultUnits); } else if (type == "pressure") { fctr = toSI(defaultUnits); } else { throw CanteraError("getFloatDefaultUnits", "type of units must be supplied and understood"); } doublereal val = getFloat(parent, name, type); val /= fctr; return val; }
/* * Returns a double value for the child named 'name' of element 'parent'. If * 'type' is supplied and matches a known unit type, unit * conversion to SI will be done if the child element has an attribute * 'units'. * * Note, it's an error for the child element not to exist. * * Example: * * Code snipet: * @verbatum const XML_Node &State_XMLNode; doublereal pres = OneAtm; if (state_XMLNode.hasChild("pressure")) { pres = getFloat(State_XMLNode, "pressure", "toSI"); } @endverbatum * * reads the corresponding XML file: * @verbatum <state> <pressure units="Pa"> 101325.0 </pressure> <\state> @endverbatum * * @param parent reference to the XML_Node object of the parent XML element * @param name Name of the XML child element * @param type String type. Currently known types are "toSI" and "actEnergy", * and "" , for no conversion. The default value is "" * which implies that no conversion is allowed. */ doublereal getFloat(const Cantera::XML_Node& parent, const std::string &name, const std::string type) { if (!parent.hasChild(name)) throw CanteraError("getFloat (called from XML Node \"" + parent.name() + "\"): ", "no child XML element named \"" + name + "\" exists"); const XML_Node& node = parent.child(name); doublereal x, x0, x1, fctr = 1.0; string units, vmin, vmax; x = atof(node().c_str()); x0 = Undef; x1 = Undef; units = node["units"]; vmin = node["min"]; vmax = node["max"]; if (vmin != "") { x0 = atof(vmin.c_str()); if (x < x0 - Tiny) { writelog("\nWarning: value "+node()+" is below lower limit of " +vmin+".\n"); } } if (node["max"] != "") { x1 = atof(vmax.c_str()); if (x > x1 + Tiny) { writelog("\nWarning: value "+node()+" is above upper limit of " +vmax+".\n"); } } // Note, most type's of converters default to toSI() type atm. // This may change and become more specific in the future. if (type == "actEnergy" && units != "") { fctr = actEnergyToSI(units); } else if (type == "toSI" && units != "") { fctr = toSI(units); } else if (type == "temperature" && units != "") { fctr = toSI(units); } else if (type == "density" && units != "") { fctr = toSI(units); } else if (type == "pressure" && units != "") { fctr = toSI(units); } else if (type != "" && units != "") { fctr = toSI(units); #ifdef DEBUG_MODE writelog("\nWarning: conversion toSI() was done on node value " + node.name() + "but wasn't explicity requested. Type was \"" + type + "\"\n"); #endif } // Note, below currently produces a lot of output due to transport blocks. // This needs to be addressed. #ifdef DEBUG_MODE_MORE else if (type == "" && units != "") { writelog("\nWarning: XML node " + node.name() + "has a units attribute, \"" + units + "\"," "but no conversion was done because the getFloat() command didn't have a type\n"); } #endif return fctr*x; }
doublereal getFloatCurrent(const XML_Node& node, const std::string& type) { doublereal fctr = 1.0; doublereal x = node.fp_value(); const string& units = node["units"]; const string& vmin = node["min"]; const string& vmax = node["max"]; if (vmin != "" && x < fpValue(vmin) - Tiny) { writelog("\nWarning: value "+node.value()+" is below lower limit of " +vmin+".\n"); } if (node["max"] != "" && x > fpValue(vmax) + Tiny) { writelog("\nWarning: value "+node.value()+" is above upper limit of " +vmax+".\n"); } // Note, most types of converters default to toSI() type atm. // This may change and become more specific in the future. if (type == "actEnergy" && units != "") { fctr = actEnergyToSI(units); } else if (type == "toSI" && units != "") { fctr = toSI(units); } else if (type == "temperature" && units != "") { fctr = toSI(units); } else if (type == "density" && units != "") { fctr = toSI(units); } else if (type == "pressure" && units != "") { fctr = toSI(units); } else if (type != "" && units != "") { fctr = toSI(units); #ifdef DEBUG_MODE writelog("\nWarning: conversion toSI() was done on node value " + node.name() + "but wasn't explicitly requested. Type was \"" + type + "\"\n"); #endif } // Note, below currently produces a lot of output due to transport blocks. // This needs to be addressed. #ifdef DEBUG_MODE_MORE else if (type == "" && units != "") { writelog("\nWarning: XML node " + node.name() + "has a units attribute, \"" + units + "\"," "but no conversion was done because the getFloat() command didn't have a type\n"); } #endif return fctr*x; }
/* * This function will read a child node to the current XML node, with the * name "floatArray". It will have a title attribute, and the body * of the XML node will be filled out with a comma separated list of * doublereals. * Get an array of floats from the XML Node. The argument field * is assumed to consist of an arbitrary number of comma * separated floats, with an arbitrary amount of white space * separating each field. * If the node array has an units attribute field, then * the units are used to convert the floats, iff convert is true. * * Example: * * Code snipet: * @verbatum const XML_Node &State_XMLNode; vector_fp v; bool convert = true; unitsString = ""; nodeName="floatArray"; getFloatArray(State_XMLNode, v, convert, unitsString, nodeName); @endverbatum * * reads the corresponding XML file: * * @verbatum <state> <floatArray units="m3"> 32.4, 1, 100. <\floatArray> <\state> @endverbatum * * Will produce the vector * * v[0] = 32.4 * v[1] = 1.0 * v[2] = 100. * * * @param node XML parent node of the floatArray * @param v Output vector of floats containing the floatArray information. * @param convert Conversion to SI is carried out if this boolean is * True. The default is true. * @param typeString String name of the type attribute. This is an optional * parameter. The default is to have an empty string. * The only string that is recognized is actEnergy. * Anything else has no effect. This affects what * units converter is used. * @param nodeName XML Name of the XML node to read. * The default value for the node name is floatArray */ void getFloatArray(const Cantera::XML_Node& node, vector_fp& v, const bool convert, const std::string unitsString, const std::string nodeName) { string::size_type icom; string numstr; doublereal dtmp; string nn = node.name(); if (nn != nodeName) throw CanteraError("getFloatArray", "wrong xml element type/name: was expecting " + nodeName + "but accessed " + node.name()); v.clear(); doublereal vmin = Undef, vmax = Undef; doublereal funit = 1.0; /* * Get the attributes field, units, from the XML node */ std::string units = node["units"]; if (units != "" && convert) { if (unitsString == "actEnergy" && units != "") { funit = actEnergyToSI(units); } else if (unitsString != "" && units != "") { funit = toSI(units); } } if (node["min"] != "") vmin = atofCheck(node["min"].c_str()); if (node["max"] != "") vmax = atofCheck(node["max"].c_str()); doublereal vv; std::string val = node.value(); while (1 > 0) { icom = val.find(','); if (icom != string::npos) { numstr = val.substr(0,icom); val = val.substr(icom+1,val.size()); dtmp = atofCheck(numstr.c_str()); v.push_back(dtmp); } else { /* * This little bit of code is to allow for the * possibility of a comma being the last * item in the value text. This was allowed in * previous versions of Cantera, even though it * would appear to be odd. So, we keep the * possibilty in for backwards compatibility. */ int nlen = strlen(val.c_str()); if (nlen > 0) { dtmp = atofCheck(val.c_str()); v.push_back(dtmp); } break; } vv = v.back(); if (vmin != Undef && vv < vmin - Tiny) { writelog("\nWarning: value "+fp2str(vv)+ " is below lower limit of " +fp2str(vmin)+".\n"); } if (vmax != Undef && vv > vmax + Tiny) { writelog("\nWarning: value "+fp2str(vv)+ " is above upper limit of " +fp2str(vmin)+".\n"); } } int nv = v.size(); for (int n = 0; n < nv; n++) { v[n] *= funit; } }
size_t getFloatArray(const XML_Node& node, std::vector<doublereal> & v, const bool convert, const std::string& unitsString, const std::string& nodeName) { const XML_Node* readNode = &node; if (node.name() != nodeName) { vector<XML_Node*> ll = node.getChildren(nodeName); if (ll.size() == 0) { throw CanteraError("getFloatArray", "wrong XML element type/name: was expecting " + nodeName + "but accessed " + node.name()); } else { readNode = ll[0]; ll = readNode->getChildren("floatArray"); if (ll.size() > 0) { readNode = ll[0]; } } } v.clear(); doublereal vmin = Undef, vmax = Undef; doublereal funit = 1.0; /* * Get the attributes field, units, from the XML node */ std::string units = readNode->attrib("units"); if (units != "" && convert) { if (unitsString == "actEnergy" && units != "") { funit = actEnergyToSI(units); } else if (unitsString != "" && units != "") { funit = toSI(units); } } if (readNode->attrib("min") != "") { vmin = fpValueCheck(readNode->attrib("min")); } if (readNode->attrib("max") != "") { vmax = fpValueCheck(readNode->attrib("max")); } std::string val = readNode->value(); while (true) { size_t icom = val.find(','); if (icom != string::npos) { string numstr = val.substr(0,icom); val = val.substr(icom+1,val.size()); v.push_back(fpValueCheck(numstr)); } else { /* * This little bit of code is to allow for the * possibility of a comma being the last * item in the value text. This was allowed in * previous versions of Cantera, even though it * would appear to be odd. So, we keep the * possibility in for backwards compatibility. */ if (!val.empty()) { v.push_back(fpValueCheck(val)); } break; } doublereal vv = v.back(); if (vmin != Undef && vv < vmin - Tiny) { writelog("\nWarning: value "+fp2str(vv)+ " is below lower limit of " +fp2str(vmin)+".\n"); } if (vmax != Undef && vv > vmax + Tiny) { writelog("\nWarning: value "+fp2str(vv)+ " is above upper limit of " +fp2str(vmin)+".\n"); } } for (size_t n = 0; n < v.size(); n++) { v[n] *= funit; } return v.size(); }