Beispiel #1
0
  /*
   * constructPDSSXML:
   *
   * Initialization of a PDSS_ConstVol object using an
   * xml file.
   *
   * This routine is a precursor to initThermo(XML_Node*)
   * routine, which does most of the work.
   *
   * @param infile XML file containing the description of the
   *        phase
   *
   * @param id  Optional parameter identifying the name of the
   *            phase. If none is given, the first XML
   *            phase element will be used.
   */
  void PDSS_ConstVol::constructPDSSXML(VPStandardStateTP *tp, int spindex,
				       const XML_Node& speciesNode, 
				       const XML_Node& phaseNode, bool spInstalled) {
    PDSS::initThermo();
    SpeciesThermo &sp = m_tp->speciesThermo();
    m_p0 = sp.refPressure(m_spindex);

    if (!spInstalled) {
      throw CanteraError("PDSS_ConstVol::constructPDSSXML", "spInstalled false not handled");
    }

    const XML_Node *ss = speciesNode.findByName("standardState");
    if (!ss) {
      throw CanteraError("PDSS_ConstVol::constructPDSSXML",
			 "no standardState Node for species " + speciesNode.name());
    }
    std::string model = (*ss)["model"];
    if (model != "constant_incompressible") {
      throw CanteraError("PDSS_ConstVol::initThermoXML",
			 "standardState model for species isn't constant_incompressible: " + speciesNode.name());
    }
  
    m_constMolarVolume = ctml::getFloat(*ss, "molarVolume", "toSI");
  
    std::string id = "";
    // initThermoXML(phaseNode, id);
  }
  /**
   * constructPDSSXML:
   *
   * Initialization of a PDSS_IonsFromNeutral object using an
   * xml file.
 
   * @param id  Optional parameter identifying the name of the
   *            phase. If none is given, the first XML
   *            phase element will be used.
   */
  void PDSS_IonsFromNeutral::constructPDSSXML(VPStandardStateTP *tp, int spindex, 
					      const XML_Node& speciesNode,
					      const XML_Node& phaseNode, std::string id) {
    const XML_Node *tn = speciesNode.findByName("thermo");
    if (!tn) {
      throw CanteraError("PDSS_IonsFromNeutral::constructPDSSXML",
                         "no thermo Node for species " + speciesNode.name());
    }
    std::string model = lowercase((*tn)["model"]);
    if (model != "ionfromneutral") {
      throw CanteraError("PDSS_IonsFromNeutral::constructPDSSXML",
                         "thermo model for species isn't IonsFromNeutral: "
                         + speciesNode.name());
    } 
    const XML_Node *nsm = tn->findByName("neutralSpeciesMultipliers");
    if (!nsm) {
      throw CanteraError("PDSS_IonsFromNeutral::constructPDSSXML",
                         "no Thermo::neutralSpeciesMultipliers Node for species " + speciesNode.name());
    }

    IonsFromNeutralVPSSTP *ionPhase = dynamic_cast<IonsFromNeutralVPSSTP *>(tp);
    if (!ionPhase) {
      throw CanteraError("PDSS_IonsFromNeutral::constructPDSSXML", "Dynamic cast failed");
    }
    neutralMoleculePhase_ = ionPhase->neutralMoleculePhase_;

    std::vector<std::string> key;
    std::vector<std::string> val;

    /*
     * 
     */
    numMult_ = ctml::getPairs(*nsm,  key, val);
    idNeutralMoleculeVec.resize(numMult_);
    factorVec.resize(numMult_);
    tmpNM.resize(neutralMoleculePhase_->nSpecies());

    for (int i = 0; i < numMult_; i++) {
      idNeutralMoleculeVec[i] = neutralMoleculePhase_->speciesIndex(key[i]);
      factorVec[i] =  fpValueCheck(val[i]);
    }
    specialSpecies_ = 0;
    const XML_Node *ss = tn->findByName("specialSpecies");
    if (ss) {
      specialSpecies_ = 1;
    }
   const XML_Node *sss = tn->findByName("secondSpecialSpecies");
    if (sss) {
      specialSpecies_ = 2;
    }
    add2RTln2_ = true;
    if (specialSpecies_ == 1) {
      add2RTln2_ = false;
    }
  
  }
Beispiel #3
0
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;
}
Beispiel #4
0
doublereal getFloat(const 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);
    return getFloatCurrent(node, type);
}
Beispiel #5
0
  /*
   * constructPDSSXML:
   *
   * Initialization of a PDSS_SSVol object using an
   * xml file.
   *
   * This routine is a precursor to initThermo(XML_Node*)
   * routine, which does most of the work.
   *
   * @param infile XML file containing the description of the
   *        phase
   *
   * @param id  Optional parameter identifying the name of the
   *            phase. If none is given, the first XML
   *            phase element will be used.
   */
  void PDSS_SSVol::constructPDSSXML(VPStandardStateTP *tp, int spindex,
				       const XML_Node& speciesNode, 
				       const XML_Node& phaseNode, bool spInstalled) {
    PDSS::initThermo();
    SpeciesThermo &sp = m_tp->speciesThermo();
    m_p0 = sp.refPressure(m_spindex);

    if (!spInstalled) {
      throw CanteraError("PDSS_SSVol::constructPDSSXML", "spInstalled false not handled");
    }

    const XML_Node *ss = speciesNode.findByName("standardState");
    if (!ss) {
      throw CanteraError("PDSS_SSVol::constructPDSSXML",
			 "no standardState Node for species " + speciesNode.name());
    }
    std::string model = (*ss)["model"];
    if (model == "constant_incompressible" || model == "constant") {
      volumeModel_ = cSSVOLUME_CONSTANT; 
      m_constMolarVolume = ctml::getFloat(*ss, "molarVolume", "toSI");
    } else if (model == "temperature_polynomial") {
      volumeModel_ = cSSVOLUME_TPOLY;
      int num = ctml::getFloatArray(*ss, TCoeff_, true, "toSI", "volumeTemperaturePolynomial");
      if (num != 4) {
	throw CanteraError("PDSS_SSVol::constructPDSSXML",
			   " Didn't get 4 density polynomial numbers for species " + speciesNode.name());
      }
    } else if (model == "density_temperature_polynomial") {
      volumeModel_ = cSSVOLUME_DENSITY_TPOLY;
      int num = ctml::getFloatArray(*ss, TCoeff_, true, "toSI", "densityTemperaturePolynomial");
      if (num != 4) {
	throw CanteraError("PDSS_SSVol::constructPDSSXML",
			   " Didn't get 4 density polynomial numbers for species " + speciesNode.name());
      }
    } else {
      throw CanteraError("PDSS_SSVol::constructPDSSXML",
			 "standardState model for species isn't constant_incompressible: " + speciesNode.name());
    }
    std::string id = "";
 
  }
Beispiel #6
0
void getString(const XML_Node& node, const std::string& titleString, std::string& valueString,
               std::string& typeString)
{
    XML_Node* s = getByTitle(node, titleString);
    if (s && s->name() == "string") {
        valueString = s->value();
        typeString = s->attrib("type");
    } else {
        valueString = "";
        typeString = "";
    }
}
Beispiel #7
0
  /* 
   *   This function will read a child node to the current XML node, with the
   *   name "string". It must have a title attribute, named titleString, and the body
   *   of the XML node will be read into the valueString output argument.
   *
   *  Example:  
   *
   * Code snipet:
   *       @verbatum
   const XML_Node &node;
   getString(XML_Node& node, std::string titleString, std::string valueString, 
   std::string typeString);
   @endverbatum
   *
   *  Reads the following the snippet in the XML file:
   *  @verbatum
   <string title="titleString" type="typeString">
     valueString
   <\string>
   @endverbatum
   *
   *   @param node          reference to the XML_Node object of the parent XML element
   *   @param titleString   String name of the title attribute of the child node
   *   @param valueString   Value string that is found in the child node. output variable
   *   @param typeString    String type. This is an optional output variable
   */
  void getString(const Cantera::XML_Node& node, const std::string &titleString, std::string& valueString, 
		 std::string& typeString) {
    valueString = "";
    typeString = "";
    XML_Node* s = getByTitle(node, titleString);
    if (s) 
      if (s->name() == "string") {
	valueString = (*s).value();
	typeString = (*s)["type"];
	return;
      }
  }
Beispiel #8
0
/* The transport property is constructed from the XML node,
 *  \verbatim <propNode>, \endverbatim that is a child of the
 *  \verbatim <transport> \endverbatim node and specifies a type of
 *  transport property (like viscosity)
 */
LTPspecies_Const::LTPspecies_Const(const XML_Node& propNode, const std::string name,
                                   TransportPropertyType tp_ind, const thermo_t* const thermo) :
    LTPspecies(&propNode, name, tp_ind, thermo)
{
    m_model = LTP_TD_CONSTANT;
    double A_k = getFloatCurrent(propNode, "toSI");
    if (A_k > 0.0) {
        m_coeffs.push_back(A_k);
    } else {
        throw LTPError("negative or zero " + propNode.name());
    }
}
Beispiel #9
0
LTPspecies_Arrhenius::LTPspecies_Arrhenius(const XML_Node& propNode, const std::string name,
        TransportPropertyType tp_ind, const thermo_t* thermo) :
    LTPspecies(&propNode, name, tp_ind, thermo)
{
    m_model = LTP_TD_ARRHENIUS;
    m_temp = 0.0;
    m_prop = 0.0;

    doublereal A_k, n_k, Tact_k;
    getArrhenius(propNode, A_k, n_k, Tact_k);
    if (A_k <= 0.0) {
        throw LTPError("negative or zero " + propNode.name());
    }
    m_coeffs.push_back(A_k);
    m_coeffs.push_back(n_k);
    m_coeffs.push_back(Tact_k);
    m_coeffs.push_back(log(A_k));
}
Beispiel #10
0
int getInteger(const XML_Node& parent, const std::string& name)
{
    if (!parent.hasChild(name)) {
        throw CanteraError("getInteger (called from XML Node \"" +
                           parent.name() + "\"): ",
                           "no child XML element named " + name);
    }
    const XML_Node& node = parent.child(name);
    int x = node.int_value();
    const string& vmin = node["min"];
    const string& vmax = node["max"];
    if (vmin != "" && x < intValue(vmin)) {
        writelog("\nWarning: value "+node.value()+" is below lower limit of "
                 +vmin+".\n");
    }
    if (node["max"] != "" && x > intValue(vmax)) {
        writelog("\nWarning: value "+node.value()+" is above upper limit of "
                 +vmax+".\n");
    }
    return x;
}
Beispiel #11
0
void PDSS_ConstVol::constructPDSSXML(VPStandardStateTP* tp, size_t spindex,
                                     const XML_Node& speciesNode,
                                     const XML_Node& phaseNode, bool spInstalled)
{
    PDSS::initThermo();
    m_p0 = m_tp->speciesThermo().refPressure(m_spindex);

    if (!spInstalled) {
        throw CanteraError("PDSS_ConstVol::constructPDSSXML", "spInstalled false not handled");
    }

    const XML_Node* ss = speciesNode.findByName("standardState");
    if (!ss) {
        throw CanteraError("PDSS_ConstVol::constructPDSSXML",
                           "no standardState Node for species " + speciesNode.name());
    }
    if (ss->attrib("model") != "constant_incompressible") {
        throw CanteraError("PDSS_ConstVol::initThermoXML",
                           "standardState model for species isn't constant_incompressible: " + speciesNode.name());
    }

    m_constMolarVolume = getFloat(*ss, "molarVolume", "toSI");
}
void RedlichKisterVPSSTP::readXMLBinarySpecies(XML_Node& xmLBinarySpecies)
{
    std::string xname = xmLBinarySpecies.name();
    if (xname != "binaryNeutralSpeciesParameters") {
        throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies",
                           "Incorrect name for processing this routine: " + xname);
    }
    size_t Npoly = 0;
    vector_fp hParams, sParams;
    std::string iName = xmLBinarySpecies.attrib("speciesA");
    if (iName == "") {
        throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "no speciesA attrib");
    }
    std::string jName = xmLBinarySpecies.attrib("speciesB");
    if (jName == "") {
        throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "no speciesB attrib");
    }
    /*
     * Find the index of the species in the current phase. It's not
     * an error to not find the species. This means that the interaction doesn't occur for the current
     * implementation of the phase.
     */
    size_t iSpecies = speciesIndex(iName);
    if (iSpecies == npos) {
        return;
    }
    string ispName = speciesName(iSpecies);
    if (charge(iSpecies) != 0) {
        throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "speciesA charge problem");
    }
    size_t jSpecies = speciesIndex(jName);
    if (jSpecies == npos) {
        return;
    }
    std::string jspName = speciesName(jSpecies);
    if (charge(jSpecies) != 0) {
        throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "speciesB charge problem");
    }
    /*
     *  Ok we have found a valid interaction
     */
    numBinaryInteractions_++;
    size_t iSpot = numBinaryInteractions_ - 1;
    m_pSpecies_A_ij.resize(numBinaryInteractions_);
    m_pSpecies_B_ij.resize(numBinaryInteractions_);
    m_pSpecies_A_ij[iSpot] = iSpecies;
    m_pSpecies_B_ij[iSpot] = jSpecies;

    for (size_t iChild = 0; iChild < xmLBinarySpecies.nChildren(); iChild++) {
        XML_Node& xmlChild = xmLBinarySpecies.child(iChild);
        string nodeName = lowercase(xmlChild.name());
        /*
         * Process the binary species interaction child elements
         */
        if (nodeName == "excessenthalpy") {
            /*
             * Get the string containing all of the values
             */
            getFloatArray(xmlChild, hParams, true, "toSI", "excessEnthalpy");
            Npoly = std::max(hParams.size(), Npoly);
        }

        if (nodeName == "excessentropy") {
            /*
             * Get the string containing all of the values
             */
            getFloatArray(xmlChild, sParams, true, "toSI", "excessEntropy");
            Npoly = std::max(sParams.size(), Npoly);
        }
    }
    hParams.resize(Npoly, 0.0);
    sParams.resize(Npoly, 0.0);
    m_HE_m_ij.push_back(hParams);
    m_SE_m_ij.push_back(sParams);
    m_N_ij.push_back(Npoly);
    resizeNumInteractions(numBinaryInteractions_);
}
void MolarityIonicVPSSTP::readXMLBinarySpecies(XML_Node& xmLBinarySpecies)
{
    std::string xname = xmLBinarySpecies.name();
}
Beispiel #14
0
bool importPhase(XML_Node& phase, ThermoPhase* th,
                 SpeciesThermoFactory* spfactory)
{
    // Check the the supplied XML node in fact represents a phase.
    if (phase.name() != "phase") {
        throw CanteraError("importPhase",
                           "Current const XML_Node named, " + phase.name() +
                           ", is not a phase element.");
    }

    /*
     * In this section of code, we get the reference to the
     * phase xml tree within the ThermoPhase object. Then,
     * we clear it and fill it with the current information that
     * we are about to use to construct the object. We will then
     * be able to resurrect the information later by calling xml().
     */
    th->setXMLdata(phase);

    // set the id attribute of the phase to the 'id' attribute in the XML tree.
    th->setID(phase.id());
    th->setName(phase.id());

    // Number of spatial dimensions. Defaults to 3 (bulk phase)
    if (phase.hasAttrib("dim")) {
        int idim = intValue(phase["dim"]);
        if (idim < 1 || idim > 3)
            throw CanteraError("importPhase",
                               "phase, " + th->id() +
                               ", has unphysical number of dimensions: " + phase["dim"]);
        th->setNDim(idim);
    } else {
        th->setNDim(3);     // default
    }

    // Set equation of state parameters. The parameters are
    // specific to each subclass of ThermoPhase, so this is done
    // by method setParametersFromXML in each subclass.
    const XML_Node& eos = phase.child("thermo");
    if (phase.hasChild("thermo")) {
        th->setParametersFromXML(eos);
    } else {
        throw CanteraError("importPhase",
                           " phase, " + th->id() +
                           ", XML_Node does not have a \"thermo\" XML_Node");
    }

    VPStandardStateTP* vpss_ptr = 0;
    int ssConvention = th->standardStateConvention();
    if (ssConvention == cSS_CONVENTION_VPSS) {
        vpss_ptr = dynamic_cast <VPStandardStateTP*>(th);
        if (vpss_ptr == 0) {
            throw CanteraError("importPhase",
                               "phase, " + th->id() + ", was VPSS, but dynamic cast failed");
        }
    }

    // if no species thermo factory was supplied, use the default one.
    if (!spfactory) {
        spfactory = SpeciesThermoFactory::factory();
    }

    /***************************************************************
     * Add the elements.
     ***************************************************************/
    if (ssConvention != cSS_CONVENTION_SLAVE) {
        installElements(*th, phase);
    }

    /***************************************************************
     * Add the species.
     *
     * Species definitions may be imported from multiple
     * sources. For each one, a speciesArray element must be
     * present.
     ***************************************************************/
    vector<XML_Node*> sparrays;
    phase.getChildren("speciesArray", sparrays);
    if (ssConvention != cSS_CONVENTION_SLAVE) {
        if (sparrays.empty()) {
            throw CanteraError("importPhase",
                               "phase, " + th->id() + ", has zero \"speciesArray\" XML nodes.\n"
                               + " There must be at least one speciesArray nodes "
                               "with one or more species");
        }
    }
    vector<XML_Node*> dbases;
    vector_int sprule(sparrays.size(),0);

    // loop over the speciesArray elements
    for (size_t jsp = 0; jsp < sparrays.size(); jsp++) {

        const XML_Node& speciesArray = *sparrays[jsp];

        // If the speciesArray element has a child element
        //
        //   <skip element="undeclared">
        //
        // then set sprule[jsp] to 1, so that any species with an undeclared
        // element will be quietly skipped when importing species. Additionally,
        // if the skip node has the following attribute:
        //
        // <skip species="duplicate">
        //
        // then duplicate species names will not cause Cantera to throw an
        // exception. Instead, the duplicate entry will be discarded.
        if (speciesArray.hasChild("skip")) {
            const XML_Node& sk = speciesArray.child("skip");
            string eskip = sk["element"];
            if (eskip == "undeclared") {
                sprule[jsp] = 1;
            }
            string dskip = sk["species"];
            if (dskip == "duplicate") {
                sprule[jsp] += 10;
            }
        }

        // Get a pointer to the node containing the species
        // definitions for the species declared in this
        // speciesArray element. This may be in the local file
        // containing the phase element, or may be in another
        // file.
        XML_Node* db = get_XML_Node(speciesArray["datasrc"], &phase.root());
        if (db == 0) {
            throw CanteraError("importPhase()",
                               " Can not find XML node for species database: "
                               + speciesArray["datasrc"]);
        }

        // add this node to the list of species database nodes.
        dbases.push_back(db);
    }

    // Now, collect all the species names and all the XML_Node * pointers
    // for those species in a single vector. This is where we decide what
    // species are to be included in the phase.
    // The logic is complicated enough that we put it in a separate routine.
    std::vector<XML_Node*>  spDataNodeList;
    std::vector<std::string> spNamesList;
    std::vector<int> spRuleList;
    formSpeciesXMLNodeList(spDataNodeList, spNamesList, spRuleList,
                           sparrays, dbases, sprule);

    // Decide whether the the phase has a variable pressure ss or not
    SpeciesThermo* spth = 0;
    VPSSMgr* vp_spth = 0;
    if (ssConvention == cSS_CONVENTION_TEMPERATURE) {
        // Create a new species thermo manager.  Function
        // 'newSpeciesThermoMgr' looks at the species in the database
        // to see what thermodynamic property parameterizations are
        // used, and selects a class that can handle the
        // parameterizations found.
        spth = newSpeciesThermoMgr(spDataNodeList);

        // install it in the phase object
        th->setSpeciesThermo(spth);
    } else if (ssConvention == cSS_CONVENTION_SLAVE) {
        /*
         * No species thermo manager for this type
         */
    } else if (ssConvention == cSS_CONVENTION_VPSS) {
        vp_spth = newVPSSMgr(vpss_ptr, &phase, spDataNodeList);
        vpss_ptr->setVPSSMgr(vp_spth);
        spth = vp_spth->SpeciesThermoMgr();
        th->setSpeciesThermo(spth);
    } else {
        throw CanteraError("importPhase()", "unknown convention");
    }


    size_t k = 0;

    size_t nsp = spDataNodeList.size();
    if (ssConvention == cSS_CONVENTION_SLAVE) {
        if (nsp > 0) {
            throw CanteraError("importPhase()", "For Slave standard states, number of species must be zero: "
                               + int2str(nsp));
        }
    }
    for (size_t i = 0; i < nsp; i++) {
        XML_Node* s = spDataNodeList[i];
        AssertTrace(s != 0);
        bool ok = installSpecies(k, *s, *th, spth, spRuleList[i],
                                 &phase, vp_spth, spfactory);
        if (ok) {
            th->saveSpeciesData(k, s);
            ++k;
        }
    }

    if (ssConvention == cSS_CONVENTION_SLAVE) {
        th->installSlavePhases(&phase);
    }

    // Done adding species. Perform any required subclass-specific
    // initialization.
    th->initThermo();

    // Perform any required subclass-specific initialization
    // that requires the XML phase object
    std::string id = "";
    th->initThermoXML(phase, id);

    return true;
}
Beispiel #15
0
bool installSpecies(size_t k, const XML_Node& s, thermo_t& th,
                    SpeciesThermo* spthermo_ptr, int rule,
                    XML_Node* phaseNode_ptr,
                    VPSSMgr* vpss_ptr,
                    SpeciesThermoFactory* factory)
{
    std::string xname = s.name();
    if (xname != "species") {
        throw CanteraError("installSpecies",
                           "Unexpected XML name of species XML_Node: " + xname);
    }

    if (rule) {
        th.ignoreUndefinedElements();
    }

    // get the composition of the species
    const XML_Node& a = s.child("atomArray");
    map<string,string> comp;
    getMap(a, comp);

    // construct a vector of atom numbers for each element in phase th. Elements
    // not declared in the species (i.e., not in map comp) will have zero
    // entries in the vector.
    size_t nel = th.nElements();
    vector_fp ecomp(nel, 0.0);
    compositionMap comp_map = parseCompString(a.value());
    for (size_t m = 0; m < nel; m++) {
        std::string& es = comp[th.elementName(m)];
        if (!es.empty()) {
            ecomp[m] = fpValueCheck(es);
        }
    }

    // get the species charge, if any. Note that the charge need
    // not be explicitly specified if special element 'E'
    // (electron) is one of the elements.
    doublereal chrg = 0.0;
    if (s.hasChild("charge")) {
        chrg = getFloat(s, "charge");
    }

    // get the species size, if any. (This is used by surface
    // phases to represent how many sites a species occupies.)
    doublereal sz = 1.0;
    if (s.hasChild("size")) {
        sz = getFloat(s, "size");
    }

    if (vpss_ptr) {
        th.addUniqueSpecies(s["name"], &ecomp[0], chrg, sz);
        VPStandardStateTP* vp_ptr = dynamic_cast<VPStandardStateTP*>(&th);
        vp_ptr->createInstallPDSS(k, s, phaseNode_ptr);
    } else {
        SpeciesThermoInterpType* st = newSpeciesThermoInterpType(s);
        Species sp(s["name"], comp_map, st, chrg, sz);

        // Read gas-phase transport data, if provided
        if (s.hasChild("transport") &&
                s.child("transport")["model"] == "gas_transport") {
            XML_Node& tr = s.child("transport");

            string geometry, dummy;
            getString(tr, "geometry", geometry, dummy);

            double diam = getFloat(tr, "LJ_diameter");
            double welldepth = getFloat(tr, "LJ_welldepth");

            double dipole = 0.0;
            getOptionalFloat(tr, "dipoleMoment", dipole);

            double polar = 0.0;
            getOptionalFloat(tr, "polarizability", polar);

            double rot = 0.0;
            getOptionalFloat(tr, "rotRelax", rot);
            double acentric = 0.0;
            getOptionalFloat(tr, "acentric_factor", acentric);

            GasTransportData* gastran = new GasTransportData;
            gastran->setCustomaryUnits(sp.name, geometry, diam, welldepth,
                                       dipole, polar, rot, acentric);
            sp.transport.reset(gastran);
            gastran->validate(sp);
        }
        th.addSpecies(sp);
    }

    return true;
}
void MixedSolventElectrolyte::readXMLBinarySpecies(XML_Node& xmLBinarySpecies)
{
    string xname = xmLBinarySpecies.name();
    if (xname != "binaryNeutralSpeciesParameters") {
        throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies",
                           "Incorrect name for processing this routine: " + xname);
    }
    string stemp;
    size_t nParamsFound;
    vector_fp vParams;
    string iName = xmLBinarySpecies.attrib("speciesA");
    if (iName == "") {
        throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "no speciesA attrib");
    }
    string jName = xmLBinarySpecies.attrib("speciesB");
    if (jName == "") {
        throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "no speciesB attrib");
    }
    /*
     * Find the index of the species in the current phase. It's not
     * an error to not find the species
     */
    size_t iSpecies = speciesIndex(iName);
    if (iSpecies == npos) {
        return;
    }
    string ispName = speciesName(iSpecies);
    if (charge(iSpecies) != 0) {
        throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "speciesA charge problem");
    }
    size_t jSpecies = speciesIndex(jName);
    if (jSpecies == npos) {
        return;
    }
    string jspName = speciesName(jSpecies);
    if (charge(jSpecies) != 0) {
        throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "speciesB charge problem");
    }

    resizeNumInteractions(numBinaryInteractions_ + 1);
    size_t iSpot = numBinaryInteractions_ - 1;
    m_pSpecies_A_ij[iSpot] = iSpecies;
    m_pSpecies_B_ij[iSpot] = jSpecies;

    size_t num = xmLBinarySpecies.nChildren();
    for (size_t iChild = 0; iChild < num; iChild++) {
        XML_Node& xmlChild = xmLBinarySpecies.child(iChild);
        stemp = xmlChild.name();
        string nodeName = lowercase(stemp);
        /*
         * Process the binary species interaction child elements
         */
        if (nodeName == "excessenthalpy") {
            /*
             * Get the string containing all of the values
             */
            ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessEnthalpy");
            nParamsFound = vParams.size();

            if (nParamsFound != 2) {
                throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessEnthalpy for " + ispName
                                   + "::" + jspName,
                                   "wrong number of params found");
            }
            m_HE_b_ij[iSpot] = vParams[0];
            m_HE_c_ij[iSpot] = vParams[1];
        }

        if (nodeName == "excessentropy") {
            /*
             * Get the string containing all of the values
             */
            ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessEntropy");
            nParamsFound = vParams.size();

            if (nParamsFound != 2) {
                throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessEntropy for " + ispName
                                   + "::" + jspName,
                                   "wrong number of params found");
            }
            m_SE_b_ij[iSpot] = vParams[0];
            m_SE_c_ij[iSpot] = vParams[1];
        }

        if (nodeName == "excessvolume_enthalpy") {
            /*
             * Get the string containing all of the values
             */
            ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Enthalpy");
            nParamsFound = vParams.size();

            if (nParamsFound != 2) {
                throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessVolume_Enthalpy for " + ispName
                                   + "::" + jspName,
                                   "wrong number of params found");
            }
            m_VHE_b_ij[iSpot] = vParams[0];
            m_VHE_c_ij[iSpot] = vParams[1];
        }

        if (nodeName == "excessvolume_entropy") {
            /*
             * Get the string containing all of the values
             */
            ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Entropy");
            nParamsFound = vParams.size();

            if (nParamsFound != 2) {
                throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessVolume_Entropy for " + ispName
                                   + "::" + jspName,
                                   "wrong number of params found");
            }
            m_VSE_b_ij[iSpot] = vParams[0];
            m_VSE_c_ij[iSpot] = vParams[1];
        }
    }
}
Beispiel #17
0
void importPhase(XML_Node& phase, ThermoPhase* th)
{
    // Check the the supplied XML node in fact represents a phase.
    if (phase.name() != "phase") {
        throw CanteraError("importPhase",
                           "Current const XML_Node named, " + phase.name() +
                           ", is not a phase element.");
    }

    // In this section of code, we get the reference to the phase XML tree
    // within the ThermoPhase object. Then, we clear it and fill it with the
    // current information that we are about to use to construct the object. We
    // will then be able to resurrect the information later by calling xml().
    th->setXMLdata(phase);

    // set the id attribute of the phase to the 'id' attribute in the XML tree.
    th->setID(phase.id());
    th->setName(phase.id());

    // Number of spatial dimensions. Defaults to 3 (bulk phase)
    if (phase.hasAttrib("dim")) {
        int idim = intValue(phase["dim"]);
        if (idim < 1 || idim > 3) {
            throw CanteraError("importPhase",
                               "phase, " + th->id() +
                               ", has unphysical number of dimensions: " + phase["dim"]);
        }
        th->setNDim(idim);
    } else {
        th->setNDim(3); // default
    }

    // Set equation of state parameters. The parameters are specific to each
    // subclass of ThermoPhase, so this is done by method setParametersFromXML
    // in each subclass.
    const XML_Node& eos = phase.child("thermo");
    if (phase.hasChild("thermo")) {
        th->setParametersFromXML(eos);
    } else {
        throw CanteraError("importPhase",
                           " phase, " + th->id() +
                           ", XML_Node does not have a \"thermo\" XML_Node");
    }

    VPStandardStateTP* vpss_ptr = 0;
    int ssConvention = th->standardStateConvention();
    if (ssConvention == cSS_CONVENTION_VPSS) {
        vpss_ptr = dynamic_cast <VPStandardStateTP*>(th);
        if (vpss_ptr == 0) {
            throw CanteraError("importPhase",
                               "phase, " + th->id() + ", was VPSS, but dynamic cast failed");
        }
    }

    // Add the elements.
    if (ssConvention != cSS_CONVENTION_SLAVE) {
        installElements(*th, phase);
    }

    // Add the species.
    //
    // Species definitions may be imported from multiple sources. For each one,
    // a speciesArray element must be present.
    vector<XML_Node*> sparrays = phase.getChildren("speciesArray");
    if (ssConvention != cSS_CONVENTION_SLAVE && sparrays.empty()) {
        throw CanteraError("importPhase",
                           "phase, " + th->id() + ", has zero \"speciesArray\" XML nodes.\n"
                           + " There must be at least one speciesArray nodes "
                           "with one or more species");
    }
    vector<XML_Node*> dbases;
    vector_int sprule(sparrays.size(),0);

    // Default behavior when importing from CTI/XML is for undefined elements to
    // be treated as an error
    th->throwUndefinedElements();

    // loop over the speciesArray elements
    for (size_t jsp = 0; jsp < sparrays.size(); jsp++) {
        const XML_Node& speciesArray = *sparrays[jsp];

        // If the speciesArray element has a child element
        //
        //   <skip element="undeclared">
        //
        // then set sprule[jsp] to 1, so that any species with an undeclared
        // element will be quietly skipped when importing species. Additionally,
        // if the skip node has the following attribute:
        //
        // <skip species="duplicate">
        //
        // then duplicate species names will not cause Cantera to throw an
        // exception. Instead, the duplicate entry will be discarded.
        if (speciesArray.hasChild("skip")) {
            const XML_Node& sk = speciesArray.child("skip");
            string eskip = sk["element"];
            if (eskip == "undeclared") {
                sprule[jsp] = 1;
            }
            string dskip = sk["species"];
            if (dskip == "duplicate") {
                sprule[jsp] += 10;
            }
        }

        // Get a pointer to the node containing the species definitions for the
        // species declared in this speciesArray element. This may be in the
        // local file containing the phase element, or may be in another file.
        XML_Node* db = get_XML_Node(speciesArray["datasrc"], &phase.root());
        if (db == 0) {
            throw CanteraError("importPhase()",
                               " Can not find XML node for species database: "
                               + speciesArray["datasrc"]);
        }

        // add this node to the list of species database nodes.
        dbases.push_back(db);
    }

    // Now, collect all the species names and all the XML_Node * pointers for
    // those species in a single vector. This is where we decide what species
    // are to be included in the phase. The logic is complicated enough that we
    // put it in a separate routine.
    std::vector<XML_Node*> spDataNodeList;
    std::vector<std::string> spNamesList;
    vector_int spRuleList;
    formSpeciesXMLNodeList(spDataNodeList, spNamesList, spRuleList,
                           sparrays, dbases, sprule);

    size_t nsp = spDataNodeList.size();
    if (ssConvention == cSS_CONVENTION_SLAVE && nsp > 0) {
        throw CanteraError("importPhase()", "For Slave standard states, "
            "number of species must be zero: {}", nsp);
    }
    for (size_t k = 0; k < nsp; k++) {
        XML_Node* s = spDataNodeList[k];
        AssertTrace(s != 0);
        if (spRuleList[k]) {
           th->ignoreUndefinedElements();
        }
        th->addSpecies(newSpecies(*s));
        if (vpss_ptr) {
            const XML_Node* const ss = s->findByName("standardState");
            std::string ss_model = (ss) ? ss->attrib("model") : "ideal-gas";
            unique_ptr<PDSS> kPDSS(newPDSS(ss_model));
            kPDSS->setParametersFromXML(*s);
            vpss_ptr->installPDSS(k, std::move(kPDSS));
        }
        th->saveSpeciesData(k, s);
    }

    // Done adding species. Perform any required subclass-specific
    // initialization.
    th->initThermo();

    // Perform any required subclass-specific initialization that requires the
    // XML phase object
    std::string id = "";
    th->initThermoXML(phase, id);
}
void MargulesVPSSTP::readXMLBinarySpecies(XML_Node& xmLBinarySpecies)
{
    string xname = xmLBinarySpecies.name();
    if (xname != "binaryNeutralSpeciesParameters") {
        throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies",
                           "Incorrect name for processing this routine: " + xname);
    }
    string aName = xmLBinarySpecies.attrib("speciesA");
    if (aName == "") {
        throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies", "no speciesA attrib");
    }
    string bName = xmLBinarySpecies.attrib("speciesB");
    if (bName == "") {
        throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies", "no speciesB attrib");
    }

    vector_fp vParams;
    double h0 = 0.0;
    double h1 = 0.0;
    double s0 = 0.0;
    double s1 = 0.0;
    double vh0 = 0.0;
    double vh1 = 0.0;
    double vs0 = 0.0;
    double vs1 = 0.0;

    for (size_t iChild = 0; iChild < xmLBinarySpecies.nChildren(); iChild++) {
        XML_Node& xmlChild = xmLBinarySpecies.child(iChild);
        string nodeName = toLowerCopy(xmlChild.name());

        // Process the binary species interaction parameters.
        // They are in subblocks labeled:
        //           excessEnthalpy
        //           excessEntropy
        //           excessVolume_Enthalpy
        //           excessVolume_Entropy
        // Other blocks are currently ignored.
        // @TODO determine a policy about ignoring blocks that should or shouldn't be there.
        if (nodeName == "excessenthalpy") {
            // Get the string containing all of the values
            getFloatArray(xmlChild, vParams, true, "toSI", "excessEnthalpy");
            if (vParams.size() != 2) {
                throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies"
                    "excessEnthalpy for {} : {}: wrong number of params found."
                    " Need 2", aName, bName);
            }
            h0 = vParams[0];
            h1 = vParams[1];
        } else if (nodeName == "excessentropy") {
            // Get the string containing all of the values
            getFloatArray(xmlChild, vParams, true, "toSI", "excessEntropy");
            if (vParams.size() != 2) {
                throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies"
                    "excessEntropy for {} : {}: wrong number of params found."
                    " Need 2", aName, bName);
            }
            s0 = vParams[0];
            s1 = vParams[1];
        } else if (nodeName == "excessvolume_enthalpy") {
            // Get the string containing all of the values
            getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Enthalpy");
            if (vParams.size() != 2) {
                throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies"
                    "excessVolume_Enthalpy for {} : {}: wrong number of params"
                    "  found. Need 2", aName, bName);
            }
            vh0 = vParams[0];
            vh1 = vParams[1];
        } else if (nodeName == "excessvolume_entropy") {
            // Get the string containing all of the values
            getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Entropy");
            if (vParams.size() != 2) {
                throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies"
                    "excessVolume_Entropy for {} : {}: wrong number of params"
                    " found. Need 2", aName, bName);
            }
            vs0 = vParams[0];
            vs1 = vParams[1];
        }
    }
    addBinaryInteraction(aName, bName, h0, h1, s0, s1, vh0, vh1, vs0, vs1);
}
Beispiel #19
0
bool installSpecies(size_t k, const XML_Node& s, thermo_t& th,
                    SpeciesThermo* spthermo_ptr, int rule,
                    XML_Node* phaseNode_ptr,
                    VPSSMgr* vpss_ptr,
                    SpeciesThermoFactory* factory)
{
    std::string xname = s.name();
    if (xname != "species") {
        throw CanteraError("installSpecies",
                           "Unexpected XML name of species XML_Node: " + xname);
    }
    // get the composition of the species
    const XML_Node& a = s.child("atomArray");
    map<string,string> comp;
    getMap(a, comp);

    // check that all elements in the species exist in 'p'. If rule != 0,
    // quietly skip this species if some elements are undeclared; otherwise,
    // throw an exception
    map<string,string>::const_iterator _b = comp.begin();
    for (; _b != comp.end(); ++_b) {
        if (th.elementIndex(_b->first) == npos) {
            if (rule == 0) {
                throw CanteraError("installSpecies",
                                   "Species " + s["name"] +
                                   " contains undeclared element " + _b->first);
            } else {
                return false;
            }
        }
    }

    // construct a vector of atom numbers for each element in phase th. Elements
    // not declared in the species (i.e., not in map comp) will have zero
    // entries in the vector.
    size_t nel = th.nElements();
    vector_fp ecomp(nel, 0.0);
    for (size_t m = 0; m < nel; m++) {
        std::string& es = comp[th.elementName(m)];
        if (!es.empty()) {
            ecomp[m] = fpValueCheck(es);
        }
    }


    // get the species charge, if any. Note that the charge need
    // not be explicitly specified if special element 'E'
    // (electron) is one of the elements.
    doublereal chrg = 0.0;
    if (s.hasChild("charge")) {
        chrg = getFloat(s, "charge");
    }

    // get the species size, if any. (This is used by surface
    // phases to represent how many sites a species occupies.)
    doublereal sz = 1.0;
    if (s.hasChild("size")) {
        sz = getFloat(s, "size");
    }

    // add the species to phase th
    th.addUniqueSpecies(s["name"], &ecomp[0], chrg, sz);

    if (vpss_ptr) {
        VPStandardStateTP* vp_ptr = dynamic_cast<VPStandardStateTP*>(&th);
        factory->installVPThermoForSpecies(k, s, vp_ptr, phaseNode_ptr);
    } else {
        // install the thermo parameterization for this species into
        // the species thermo manager for phase th
        factory->installThermoForSpecies(k, s, &th, *spthermo_ptr, phaseNode_ptr);
    }

    return true;
}
Beispiel #20
0
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();
}