예제 #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 = getFloat(*ss, "molarVolume", "toSI");

    std::string id = "";
    // initThermoXML(phaseNode, id);
}
예제 #2
0
  /**
   * 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;
    }
  
  }
void LatticePhase::initThermoXML(XML_Node& phaseNode, const std::string& id_)
{
    if (!id_.empty() && id_ != phaseNode.id()) {
        throw CanteraError("LatticePhase::initThermoXML",
                           "ids don't match");
    }

    // Check on the thermo field. Must have:
    // <thermo model="Lattice" />
    if (phaseNode.hasChild("thermo")) {
        XML_Node& thNode = phaseNode.child("thermo");
        std::string mString = thNode.attrib("model");
        if (lowercase(mString) != "lattice") {
            throw CanteraError("LatticePhase::initThermoXML",
                               "Unknown thermo model: " + mString);
        }
    } else {
        throw CanteraError("LatticePhase::initThermoXML",
                           "Unspecified thermo model");
    }

    // Now go get the molar volumes. use the default if not found
    XML_Node& speciesList = phaseNode.child("speciesArray");
    XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], &phaseNode.root());

    for (size_t k = 0; k < m_kk; k++) {
        m_speciesMolarVolume[k] = m_site_density;
        XML_Node* s = speciesDB->findByAttr("name", speciesName(k));
        if (!s) {
            throw CanteraError(" LatticePhase::initThermoXML", "database problems");
        }
        XML_Node* ss = s->findByName("standardState");
        if (ss && ss->findByName("molarVolume")) {
            m_speciesMolarVolume[k] = getFloat(*ss, "molarVolume", "toSI");
        }
    }

    // Call the base initThermo, which handles setting the initial state.
    ThermoPhase::initThermoXML(phaseNode, id_);
}
예제 #4
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 = "";
 
  }
예제 #5
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");
}
예제 #6
0
    TransportFromScratch()
        : sH2(new Species("H2", parseCompString("H:2")))
        , sO2(new Species("O2", parseCompString("O:2")))
        , sH2O(new Species("H2O", parseCompString("H:2 O:1")))
        , tH2(new GasTransportData())
        , tO2(new GasTransportData())
        , tH2O(new GasTransportData())
    {
        sH2->thermo.reset(new NasaPoly2(200, 3500, 101325, h2_nasa_coeffs));
        sO2->thermo.reset(new NasaPoly2(200, 3500, 101325, o2_nasa_coeffs));
        sH2O->thermo.reset(new NasaPoly2(200, 3500, 101325, h2o_nasa_coeffs));

        tH2->setCustomaryUnits("linear", 2.92, 38.0, 0.0, 0.79, 280.0);
        tO2->setCustomaryUnits("linear", 3.46, 107.40, 0.0, 1.60, 3.80);
        tH2O->setCustomaryUnits("nonlinear", 2.60, 572.4, 1.84, 0.0, 4.00);

        sH2->transport = tH2;
        sO2->transport = tO2;
        sH2O->transport = tH2O;

        std::string phase_def = "ideal_gas(name='test', elements='O H',"
            "species='gri30: H2 O2 H2O')";

        XML_Node* fxml = get_XML_from_string(phase_def);
        ref.reset(newPhase(*fxml->findByName("phase")));
        test.reset(new IdealGasPhase());

        test->addElement("O");
        test->addElement("H");
        test->addSpecies(sH2);
        test->addSpecies(sO2);
        test->addSpecies(sH2O);
        test->initThermo();

        ref->setState_TPX(400, 5e5, "H2:0.5, O2:0.3, H2O:0.2");
        test->setState_TPX(400, 5e5, "H2:0.5, O2:0.3, H2O:0.2");
    }
예제 #7
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);
}
예제 #8
0
void IdealSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_)
{
    if (id_.size() > 0 && phaseNode.id() != id_) {
        throw CanteraError("IdealSolidSolnPhase::initThermoXML",
                           "phasenode and Id are incompatible");
    }

    /*
     * Check on the thermo field. Must have:
     * <thermo model="IdealSolidSolution" />
     */
    if (phaseNode.hasChild("thermo")) {
        XML_Node& thNode = phaseNode.child("thermo");
        string mString = thNode.attrib("model");
        if (lowercase(mString) != "idealsolidsolution") {
            throw CanteraError("IdealSolidSolnPhase::initThermoXML",
                               "Unknown thermo model: " + mString);
        }
    } else {
        throw CanteraError("IdealSolidSolnPhase::initThermoXML",
                           "Unspecified thermo model");
    }

    /*
     * Form of the standard concentrations. Must have one of:
     *
     *     <standardConc model="unity" />
     *     <standardConc model="molar_volume" />
     *     <standardConc model="solvent_volume" />
     */
    if (phaseNode.hasChild("standardConc")) {
        XML_Node& scNode = phaseNode.child("standardConc");
        string formStringa = scNode.attrib("model");
        string formString = lowercase(formStringa);
        if (formString == "unity") {
            m_formGC = 0;
        } else if (formString == "molar_volume") {
            m_formGC = 1;
        } else if (formString == "solvent_volume") {
            m_formGC = 2;
        } else {
            throw CanteraError("IdealSolidSolnPhase::initThermoXML",
                               "Unknown standardConc model: " + formStringa);
        }
    } else {
        throw CanteraError("IdealSolidSolnPhase::initThermoXML",
                           "Unspecified standardConc model");
    }

    /*
     * Initialize all of the lengths now that we know how many species
     * there are in the phase.
     */
    initLengths();
    /*
     * Now go get the molar volumes
     */
    XML_Node& speciesList = phaseNode.child("speciesArray");
    XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"],
                                         &phaseNode.root());

    for (size_t k = 0; k < m_kk; k++) {
        XML_Node* s = speciesDB->findByAttr("name", speciesName(k));
        XML_Node* ss = s->findByName("standardState");
        m_speciesMolarVolume[k] = getFloat(*ss, "molarVolume", "toSI");
    }

    /*
     * Call the base initThermo, which handles setting the initial
     * state.
     */
    ThermoPhase::initThermoXML(phaseNode, id_);
}
 void setup(const std::string& elements="H C O N Ar") {
     XML_Node* phase = get_XML_from_string(
         "ideal_gas(elements='" + elements + "', species='gri30: CH C2H2')");
     gas.reset(newPhase(*phase->findByName("phase")));
     gas->setState_TPX(1000, 1e5, "C2H2:0.9, CH:0.1");
 }