Exemple #1
0
Mu0Poly* newMu0ThermoFromXML(const XML_Node& Mu0Node)
{
    bool dimensionlessMu0Values = false;

    doublereal h298 = 0.0;
    if (Mu0Node.hasChild("H298")) {
        h298 = getFloat(Mu0Node, "H298", "actEnergy");
    }

    size_t numPoints = 1;
    if (Mu0Node.hasChild("numPoints")) {
        numPoints = getInteger(Mu0Node, "numPoints");
    }

    vector_fp cValues(numPoints);
    const XML_Node* valNode_ptr = getByTitle(Mu0Node, "Mu0Values");
    if (!valNode_ptr) {
        throw CanteraError("installMu0ThermoFromXML", "missing Mu0Values");
    }
    getFloatArray(*valNode_ptr, cValues, true, "actEnergy");

    // Check to see whether the Mu0's were input in a dimensionless form. If
    // they were, then the assumed temperature needs to be adjusted from the
    // assumed T = 273.15
    if (valNode_ptr->attrib("units") == "Dimensionless") {
        dimensionlessMu0Values = true;
    }
    if (cValues.size() != numPoints) {
        throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent");
    }

    vector_fp cTemperatures(numPoints);
    const XML_Node* tempNode_ptr = getByTitle(Mu0Node, "Mu0Temperatures");
    if (!tempNode_ptr) {
        throw CanteraError("installMu0ThermoFromXML",
                           "missing Mu0Temperatures");
    }
    getFloatArray(*tempNode_ptr, cTemperatures, false);
    if (cTemperatures.size() != numPoints) {
        throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent");
    }

    // Fix up dimensionless Mu0 values if input
    if (dimensionlessMu0Values) {
        for (size_t i = 0; i < numPoints; i++) {
            cValues[i] *= cTemperatures[i] / 273.15;
        }
    }

    vector_fp c(2 + 2 * numPoints);
    c[0] = static_cast<double>(numPoints);
    c[1] = h298;
    for (size_t i = 0; i < numPoints; i++) {
        c[2+i*2] = cTemperatures[i];
        c[2+i*2+1] = cValues[i];
    }

    return new Mu0Poly(fpValue(Mu0Node["Tmin"]), fpValue(Mu0Node["Tmax"]),
                       fpValue(Mu0Node["Pref"]), &c[0]);
}
  static void installAdsorbateThermoFromXML(std::string speciesName,
					    SpeciesThermo& sp, int k, 
					    const XML_Node& f) { 		
    vector_fp freqs;
    doublereal tmin, tmax, pref = OneAtm;
    int nfreq = 0;
    tmin = fpValue(f["Tmin"]);
    tmax = fpValue(f["Tmax"]);
    if (f.hasAttrib("P0")) {
      pref = fpValue(f["P0"]);
    }
    if (f.hasAttrib("Pref")) {
      pref = fpValue(f["Pref"]);
    }
    if (tmax == 0.0) tmax = 1.0e30;

    if (f.hasChild("floatArray")) {
      getFloatArray(f.child("floatArray"), freqs, false);
      nfreq = freqs.size(); 
    }
    for (int n = 0; n < nfreq; n++) {
      freqs[n] *= 3.0e10;
    }
    vector_fp coeffs(nfreq + 2);
    coeffs[0] = nfreq;
    coeffs[1] = getFloat(f, "binding_energy", "toSI");
    copy(freqs.begin(), freqs.end(), coeffs.begin() + 2);
    //posc = new Adsorbate(k, tmin, tmax, pref,  
    //    DATA_PTR(coeffs)); 
    (&sp)->install(speciesName, k, ADSORBATE, &coeffs[0], tmin, tmax, pref);
  }
/*!
 * This is called if a 'Adsorbate' node is found in the XML input.
 *
 *  @param f            XML Node that contains the parameterization
 */
static SpeciesThermoInterpType* newAdsorbateThermoFromXML(const XML_Node& f)
{
    vector_fp freqs;
    doublereal pref = OneAtm;
    double tmin = fpValue(f["Tmin"]);
    double tmax = fpValue(f["Tmax"]);
    if (f.hasAttrib("P0")) {
        pref = fpValue(f["P0"]);
    }
    if (f.hasAttrib("Pref")) {
        pref = fpValue(f["Pref"]);
    }
    if (tmax == 0.0) {
        tmax = 1.0e30;
    }

    if (f.hasChild("floatArray")) {
        getFloatArray(f.child("floatArray"), freqs, false);
    }
    for (size_t n = 0; n < freqs.size(); n++) {
        freqs[n] *= 3.0e10;
    }
    vector_fp coeffs(freqs.size() + 2);
    coeffs[0] = static_cast<double>(freqs.size());
    coeffs[1] = getFloat(f, "binding_energy", "toSI");
    copy(freqs.begin(), freqs.end(), coeffs.begin() + 2);
    return new Adsorbate(tmin, tmax, pref, &coeffs[0]);
}
Exemple #4
0
  /*
   *   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 getFunction(const Cantera::XML_Node& node, std::string& type, doublereal& xmin,
		   doublereal& xmax, Cantera::vector_fp& coeffs) {
    const XML_Node& c = node.child("floatArray");
    coeffs.clear();
    getFloatArray(c,coeffs);
    xmin = Cantera::Undef;
    xmin = Cantera::Undef;
    if (node["min"] != "") xmin = fpValue(node["min"]);
    if (node["max"] != "") xmax = fpValue(node["max"]);
    type = node["type"];
  }
  /** 
   * Install a NASA9 polynomial thermodynamic property
   * parameterization for species k into a SpeciesThermo instance.
   * This is called by method installThermoForSpecies if a NASA9
   * block is found in the XML input.
   */
  static void installNasa9ThermoFromXML(std::string speciesName,
					SpeciesThermo& sp, int k, 
					const std::vector<XML_Node*>& tp)
  { 				
    const XML_Node * fptr = tp[0];
    int nRegTmp = tp.size();
    int nRegions = 0;
    vector_fp cPoly;
    Nasa9Poly1 *np_ptr = 0; 
    std::vector<Nasa9Poly1 *> regionPtrs;
    doublereal tmin, tmax, pref = OneAtm;
    // Loop over all of the possible temperature regions
    for (int i = 0; i < nRegTmp; i++) {
      fptr = tp[i];
      if (fptr) {
	if (fptr->name() == "NASA9") {
	  if (fptr->hasChild("floatArray")) {

	    tmin = fpValue((*fptr)["Tmin"]);
	    tmax = fpValue((*fptr)["Tmax"]);
	    if ((*fptr).hasAttrib("P0")) {
	      pref = fpValue((*fptr)["P0"]);
	    }
	    if ((*fptr).hasAttrib("Pref")) {
	      pref = fpValue((*fptr)["Pref"]);
	    }

	    getFloatArray(fptr->child("floatArray"), cPoly, false);
	    if (cPoly.size() != 9) {
	      throw CanteraError("installNasa9ThermoFromXML",
				 "Expected 9 coeff polynomial");
	    }
	    np_ptr = new Nasa9Poly1(k, tmin, tmax, pref,
				    DATA_PTR(cPoly));
	    regionPtrs.push_back(np_ptr);
	    nRegions++;
	  } 
	}
      }
    }
    if (nRegions == 0) {
      throw UnknownSpeciesThermoModel("installThermoForSpecies", 
				      speciesName, "  " );
    } else if (nRegions == 1)  {
      sp.install_STIT(np_ptr);
    } else {
      Nasa9PolyMultiTempRegion*  npMulti_ptr = new  Nasa9PolyMultiTempRegion(regionPtrs);
      sp.install_STIT(npMulti_ptr);
    }
  }
  /** 
   * Install a Shomate polynomial thermodynamic property
   * parameterization for species k.
   */
  static void installShomateThermoFromXML(std::string speciesName, 
					  SpeciesThermo& sp, int k, 
					  const XML_Node* f0ptr, const XML_Node* f1ptr) {
    doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax;

    const XML_Node& f0 = *f0ptr;
    bool dualRange = false;
    if (f1ptr) {dualRange = true;}
    tmin0 = fpValue(f0["Tmin"]);
    tmax0 = fpValue(f0["Tmax"]);
    tmin1 = tmax0;
    tmax1 = tmin1 + 0.0001;
    if (dualRange) {
      tmin1 = fpValue((*f1ptr)["Tmin"]);
      tmax1 = fpValue((*f1ptr)["Tmax"]);
    }

    vector_fp c0, c1;
    if (fabs(tmax0 - tmin1) < 0.01) {
      tmin = tmin0;
      tmid = tmax0;
      tmax = tmax1;
      getFloatArray(f0.child("floatArray"), c0, false);
      if (dualRange)
	getFloatArray(f1ptr->child("floatArray"), c1, false);
      else {
	c1.resize(7,0.0);
	copy(c0.begin(), c0.begin()+7, c1.begin());
      }
    }
    else if (fabs(tmax1 - tmin0) < 0.01) {
      tmin = tmin1;
      tmid = tmax1;
      tmax = tmax0;
      getFloatArray(f1ptr->child("floatArray"), c0, false);
      getFloatArray(f0.child("floatArray"), c1, false);
    }
    else {
      throw CanteraError("installShomateThermoFromXML",
			 "non-continuous temperature ranges.");
    }
    array_fp c(15);
    c[0] = tmid;
    doublereal p0 = OneAtm;
    copy(c0.begin(), c0.begin()+7, c.begin() + 1);
    copy(c1.begin(), c1.begin()+7, c.begin() + 8);
    sp.install(speciesName, k, SHOMATE, &c[0], tmin, tmax, p0);
  }
Exemple #7
0
void installElements(Phase& th, const XML_Node& phaseNode)
{
    // get the declared element names
    if (!phaseNode.hasChild("elementArray")) {
        throw CanteraError("installElements",
                           "phase XML node doesn't have \"elementArray\" XML Node");
    }
    XML_Node& elements = phaseNode.child("elementArray");
    vector<string> enames;
    getStringArray(elements, enames);

    // // element database defaults to elements.xml
    string element_database = "elements.xml";
    if (elements.hasAttrib("datasrc")) {
        element_database = elements["datasrc"];
    }

    XML_Node* doc = get_XML_File(element_database);
    XML_Node* dbe = &doc->child("elementData");

    XML_Node& root = phaseNode.root();
    XML_Node* local_db = 0;
    if (root.hasChild("elementData")) {
        local_db = &root.child("elementData");
    }

    for (size_t i = 0; i < enames.size(); i++) {
        // Find the element data
        XML_Node* e = 0;
        if (local_db) {
            e = local_db->findByAttr("name",enames[i]);
        }
        if (!e) {
            e = dbe->findByAttr("name",enames[i]);
        }
        if (!e) {
            throw CanteraError("addElementsFromXML","no data for element "
                               +enames[i]);
        }

        // Add the element
        doublereal weight = 0.0;
        if (e->hasAttrib("atomicWt")) {
            weight = fpValue(e->attrib("atomicWt"));
        }
        int anum = 0;
        if (e->hasAttrib("atomicNumber")) {
            anum = intValue(e->attrib("atomicNumber"));
        }
        string symbol = e->attrib("name");
        doublereal entropy298 = ENTROPY298_UNKNOWN;
        if (e->hasChild("entropy298")) {
            XML_Node& e298Node = e->child("entropy298");
            if (e298Node.hasAttrib("value")) {
                entropy298 = fpValueCheck(e298Node["value"]);
            }
        }
        th.addElement(symbol, weight, anum, entropy298);
    }
}
  /** 
   * Install a constant-cp thermodynamic property
   * parameterization for species k.
   */
  static void installSimpleThermoFromXML(std::string speciesName, 
					 SpeciesThermo& sp, int k, 
					 const XML_Node& f) {
    doublereal tmin, tmax;
    tmin = fpValue(f["Tmin"]);
    tmax = fpValue(f["Tmax"]);
    if (tmax == 0.0) tmax = 1.0e30;

    vector_fp c(4);
    c[0] = getFloat(f, "t0", "toSI");
    c[1] = getFloat(f, "h0", "toSI");
    c[2] = getFloat(f, "s0", "toSI");
    c[3] = getFloat(f, "cp0", "toSI");
    doublereal p0 = OneAtm;
    sp.install(speciesName, k, SIMPLE, &c[0], tmin, tmax, p0);
  }
Exemple #9
0
void Phase::addElement(const XML_Node& e)
{
    warn_deprecated("Phase::addElement(XML_Node&)",
                    "To be removed after Cantera 2.2.");
    doublereal weight = 0.0;
    if (e.hasAttrib("atomicWt")) {
        weight = fpValue(stripws(e["atomicWt"]));
    }
    int anum = 0;
    if (e.hasAttrib("atomicNumber")) {
        anum = atoi(stripws(e["atomicNumber"]).c_str());
    }
    string symbol = e["name"];
    doublereal entropy298 = ENTROPY298_UNKNOWN;
    if (e.hasChild("entropy298")) {
        XML_Node& e298Node = e.child("entropy298");
        if (e298Node.hasAttrib("value")) {
            entropy298 = fpValueCheck(stripws(e298Node["value"]));
        }
    }
    if (weight != 0.0) {
        addElement(symbol, weight, anum, entropy298);
    } else {
        addElement(symbol);
    }
}
/*!
 * This is called if a 'const_cp' XML node is found
 *
 *  @param f            'const_cp' XML node
 */
static SpeciesThermoInterpType* newConstCpThermoFromXML(XML_Node& f)
{
    double tmin = fpValue(f["Tmin"]);
    double tmax = fpValue(f["Tmax"]);
    if (tmax == 0.0) {
        tmax = 1.0e30;
    }

    vector_fp c(4);
    c[0] = getFloat(f, "t0", "toSI");
    c[1] = getFloat(f, "h0", "toSI");
    c[2] = getFloat(f, "s0", "toSI");
    c[3] = getFloat(f, "cp0", "toSI");
    doublereal p0 = OneAtm;
    return newSpeciesThermoInterpType(CONSTANT_CP, tmin, tmax, p0, &c[0]);
}
/*********************************************************************
 *    Utility Functions
 *********************************************************************/
void MaskellSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_)
{
    if (id_.size() > 0 && phaseNode.id() != id_) {
        throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
                           "phasenode and Id are incompatible");
    }

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

        /*
         * Parse the enthalpy of mixing constant
         */
        if (thNode.hasChild("h_mix")) {
            set_h_mix(fpValue(thNode.child("h_mix").value()));
        } else {
            throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
                               "Mixing enthalpy parameter not specified.");
        }

        if (thNode.hasChild("product_species")) {
            std::string product_species_name = thNode.child("product_species").value();
            product_species_index = speciesIndex(product_species_name);
            if (product_species_index == static_cast<int>(npos)) {
                throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
                                   "Species " + product_species_name + " not found.");
            }
            if (product_species_index == 0) {
                reactant_species_index = 1;
            } else {
                reactant_species_index = 0;
            }
        }
    } else {
        throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
                           "Unspecified thermo model");
    }


    // Confirm that the phase only contains 2 species
    if (m_kk != 2) {
        throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
                "MaskellSolidSolution model requires exactly 2 species.");
    }

    /*
     * Call the base initThermo, which handles setting the initial
     * state.
     */
    VPStandardStateTP::initThermoXML(phaseNode, id_);
}
Exemple #12
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;
}
/**
 * Create a stat mech based property solver for a species
 * @deprecated
 */
static StatMech* newStatMechThermoFromXML(const std::string& speciesName, XML_Node& f)
{
    doublereal tmin = fpValue(f["Tmin"]);
    doublereal tmax = fpValue(f["Tmax"]);
    doublereal pref = OneAtm;
    if (f.hasAttrib("P0")) {
        pref = fpValue(f["P0"]);
    }
    if (f.hasAttrib("Pref")) {
        pref = fpValue(f["Pref"]);
    }

    // set properties
    tmin = 0.1;
    vector_fp coeffs(1);
    coeffs[0] = 0.0;
    return new StatMech(0, tmin, tmax, pref, &coeffs[0], speciesName);
}
  /** 
   * Install a NASA96 polynomial thermodynamic property
   * parameterization for species k into a SpeciesThermo instance.
   */
  static void installNasa96ThermoFromXML(std::string speciesName,
					 SpeciesThermo& sp, int k, 
					 const XML_Node* f0ptr, const XML_Node* f1ptr) {
    doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax;

    const XML_Node& f0 = *f0ptr;
    bool dualRange = false;
    if (f1ptr) {dualRange = true;}
    tmin0 = fpValue(f0["Tmin"]);
    tmax0 = fpValue(f0["Tmax"]);
    tmin1 = tmax0;
    tmax1 = tmin1 + 0.0001;
    if (dualRange) {
      tmin1 = fpValue((*f1ptr)["Tmin"]);
      tmax1 = fpValue((*f1ptr)["Tmax"]);
    }


    doublereal p0 = OneAtm;
    if (f0.hasAttrib("P0")) {
      p0 = fpValue(f0["P0"]);
    }
    if (f0.hasAttrib("Pref")) {
      p0 = fpValue(f0["Pref"]);
    }

    vector_fp c0, c1;
    if (fabs(tmax0 - tmin1) < 0.01) {
      tmin = tmin0;
      tmid = tmax0;
      tmax = tmax1;
      getFloatArray(f0.child("floatArray"), c0, false);
      if (dualRange)
	getFloatArray(f1ptr->child("floatArray"), c1, false);
      else {
	c1.resize(7,0.0);
	copy(c0.begin(), c0.end(), c1.begin());
      }
    }
    else if (fabs(tmax1 - tmin0) < 0.01) {
      tmin = tmin1;
      tmid = tmax1;
      tmax = tmax0;
      getFloatArray(f1ptr->child("floatArray"), c0, false);
      getFloatArray(f0.child("floatArray"), c1, false);
    }
    else {
      throw CanteraError("installNasaThermo",
			 "non-continuous temperature ranges.");
    }
    array_fp c(15);
    c[0] = tmid;
    c[1] = c0[5];
    c[2] = c0[6];
    copy(c0.begin(), c0.begin()+5, c.begin() + 3);
    c[8] = c1[5];
    c[9] = c1[6];
    copy(c1.begin(), c1.begin()+5, c.begin() + 10);
    sp.install(speciesName, k, NASA, &c[0], tmin, tmax, p0);
  }
/*!
 * This is called if a 'NASA' node is found in the XML input.
 *
 *  @param speciesName  name of the species
 *  @param nodes        vector of 1 or 2 'NASA' XML_Nodes, each defining the
 *      coefficients for a temperature range
 */
static SpeciesThermoInterpType* newNasaThermoFromXML(
    const std::string& speciesName, vector<XML_Node*> nodes)
{
    const XML_Node& f0 = *nodes[0];
    bool dualRange = (nodes.size() > 1);

    double tmin0 = fpValue(f0["Tmin"]);
    double tmax0 = fpValue(f0["Tmax"]);

    doublereal p0 = OneAtm;
    if (f0.hasAttrib("P0")) {
        p0 = fpValue(f0["P0"]);
    }
    if (f0.hasAttrib("Pref")) {
        p0 = fpValue(f0["Pref"]);
    }
    p0 = OneAtm;

    double tmin1 = tmax0;
    double tmax1 = tmin1 + 0.0001;
    if (dualRange) {
        tmin1 = fpValue(nodes[1]->attrib("Tmin"));
        tmax1 = fpValue(nodes[1]->attrib("Tmax"));
    }

    vector_fp c0, c1;
    doublereal tmin, tmid, tmax;
    if (fabs(tmax0 - tmin1) < 0.01) {
        // f0 has the lower T data, and f1 the higher T data
        tmin = tmin0;
        tmid = tmax0;
        tmax = tmax1;
        getFloatArray(f0.child("floatArray"), c0, false);
        if (dualRange) {
            getFloatArray(nodes[1]->child("floatArray"), c1, false);
        } else {
            // if there is no higher range data, then copy c0 to c1.
            c1.resize(7,0.0);
            copy(c0.begin(), c0.end(), c1.begin());
        }
    } else if (fabs(tmax1 - tmin0) < 0.01) {
        // f1 has the lower T data, and f0 the higher T data
        tmin = tmin1;
        tmid = tmax1;
        tmax = tmax0;
        getFloatArray(nodes[1]->child("floatArray"), c0, false);
        getFloatArray(f0.child("floatArray"), c1, false);
    } else {
        throw CanteraError("installNasaThermo",
                           "non-continuous temperature ranges.");
    }

    vector_fp c(15);
    c[0] = tmid;
    copy(c1.begin(), c1.begin()+7, c.begin() + 1); // high-T coefficients
    copy(c0.begin(), c0.begin()+7, c.begin() + 8); // low-T coefficients
    return newSpeciesThermoInterpType(NASA, tmin, tmax, p0, &c[0]);
}
/*!
 *  This is called if a 'NASA9' Node is found in the XML input.
 *
 *  @param speciesName  name of the species
 *  @param tp           Vector of XML Nodes that make up the parameterization
 */
static SpeciesThermoInterpType* newNasa9ThermoFromXML(
    const std::string& speciesName, const std::vector<XML_Node*>& tp)
{
    int nRegions = 0;
    vector_fp cPoly;
    std::vector<Nasa9Poly1*> regionPtrs;
    doublereal pref = OneAtm;
    // Loop over all of the possible temperature regions
    for (size_t i = 0; i < tp.size(); i++) {
        const XML_Node& fptr = *tp[i];
        if (fptr.name() == "NASA9" && fptr.hasChild("floatArray")) {
            double tmin = fpValue(fptr["Tmin"]);
            double tmax = fpValue(fptr["Tmax"]);
            if (fptr.hasAttrib("P0")) {
                pref = fpValue(fptr["P0"]);
            }
            if (fptr.hasAttrib("Pref")) {
                pref = fpValue(fptr["Pref"]);
            }

            getFloatArray(fptr.child("floatArray"), cPoly, false);
            if (cPoly.size() != 9) {
                throw CanteraError("installNasa9ThermoFromXML",
                                   "Expected 9 coeff polynomial");
            }
            regionPtrs.push_back(new Nasa9Poly1(tmin, tmax, pref, &cPoly[0]));
            nRegions++;
        }
    }
    if (nRegions == 0) {
        throw UnknownSpeciesThermoModel("installThermoForSpecies",
                                        speciesName, "  ");
    } else if (nRegions == 1)  {
        return regionPtrs[0];
    } else {
        return new Nasa9PolyMultiTempRegion(regionPtrs);
    }
}
Exemple #17
0
doublereal fpValueCheck(const std::string& val)
{
    std::string str = ba::trim_copy(val);
    if (str.empty()) {
        throw CanteraError("fpValueCheck", "string has zero length");
    }
    int numDot = 0;
    int numExp = 0;
    char ch;
    int istart = 0;
    ch = str[0];
    if (ch == '+' || ch == '-') {
        istart = 1;
    }
    for (size_t i = istart; i < str.size(); i++) {
        ch = str[i];
        if (isdigit(ch)) {
        } else if (ch == '.') {
            numDot++;
            if (numDot > 1) {
                throw CanteraError("fpValueCheck",
                                   "string has more than one .");
            }
            if (numExp > 0) {
                throw CanteraError("fpValueCheck",
                                   "string has decimal point in exponent");
            }
        } else if (ch == 'e' || ch == 'E' || ch == 'd' || ch == 'D') {
            numExp++;
            str[i] = 'E';
            if (numExp > 1) {
                throw CanteraError("fpValueCheck",
                                   "string has more than one exp char");
            }
            ch = str[i+1];
            if (ch == '+' || ch == '-') {
                i++;
            }
        } else {
            throw CanteraError("fpValueCheck",
                               "Trouble processing string, " + str);
        }
    }
    return fpValue(str);
}
void MaskellSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_)
{
    if (id_.size() > 0 && phaseNode.id() != id_) {
        throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
                           "phasenode and Id are incompatible");
    }

    // Check on the thermo field. Must have:
    // <thermo model="MaskellSolidSolution" />
    if (phaseNode.hasChild("thermo")) {
        XML_Node& thNode = phaseNode.child("thermo");
        if (!ba::iequals(thNode["model"], "maskellsolidsolnphase")) {
            throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
                               "Unknown thermo model: " + thNode["model"]);
        }

        // Parse the enthalpy of mixing constant
        if (thNode.hasChild("h_mix")) {
            set_h_mix(fpValue(thNode.child("h_mix").value()));
        } else {
            throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
                               "Mixing enthalpy parameter not specified.");
        }

        if (thNode.hasChild("product_species")) {
            setProductSpecies(thNode.child("product_species").value());
        } else {
            setProductSpecies(speciesName(0)); // default
        }
    } else {
        throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
                           "Unspecified thermo model");
    }

    // Confirm that the phase only contains 2 species
    if (m_kk != 2) {
        throw CanteraError("MaskellSolidSolnPhase::initThermoXML",
                "MaskellSolidSolution model requires exactly 2 species.");
    }

    // Call the base initThermo, which handles setting the initial state.
    VPStandardStateTP::initThermoXML(phaseNode, id_);
}
Exemple #19
0
void installMu0ThermoFromXML(const std::string& speciesName, SpeciesThermo<ValAndDerivType>& sp, size_t k,
                             const XML_Node* Mu0Node_ptr)
{

    doublereal tmin, tmax;
    bool dimensionlessMu0Values = false;
    const XML_Node& Mu0Node = *Mu0Node_ptr;

    tmin = fpValue(Mu0Node["Tmin"]);
    tmax = fpValue(Mu0Node["Tmax"]);
    doublereal pref = fpValue(Mu0Node["Pref"]);

    doublereal h298 = 0.0;
    if (Mu0Node.hasChild("H298")) {
        h298 = getFloat(Mu0Node, "H298", "actEnergy");
    }

    size_t numPoints = 1;
    if (Mu0Node.hasChild("numPoints")) {
        numPoints = getInteger(Mu0Node, "numPoints");
    }

    vector_fp cValues(numPoints);
    const XML_Node* valNode_ptr = getByTitle(const_cast<XML_Node&>(Mu0Node), "Mu0Values");
    if (!valNode_ptr) {
        throw CanteraError("installMu0ThermoFromXML", "missing required while processing " + speciesName);
    }
    getFloatArray(*valNode_ptr, cValues, true, "actEnergy");
    /*
     * Check to see whether the Mu0's were input in a dimensionless
     * form. If they were, then the assumed temperature needs to be
     * adjusted from the assumed T = 273.15
     */
    string uuu = (*valNode_ptr)["units"];
    if (uuu == "Dimensionless") {
        dimensionlessMu0Values = true;
    }
    size_t ns = cValues.size();
    if (ns != numPoints) {
        throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent while processing " + speciesName);
    }

    vector_fp cTemperatures(numPoints);
    const XML_Node* tempNode_ptr = getByTitle(const_cast<XML_Node&>(Mu0Node), "Mu0Temperatures");
    if (!tempNode_ptr) {
        throw CanteraError("installMu0ThermoFromXML", "missing required while processing + " + speciesName);
    }
    getFloatArray(*tempNode_ptr, cTemperatures, false);
    ns = cTemperatures.size();
    if (ns != numPoints) {
        throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent while processing " + speciesName);
    }

    /*
     * Fix up dimensionless Mu0 values if input
     */
    if (dimensionlessMu0Values) {
        for (size_t i = 0; i < numPoints; i++) {
            cValues[i] *= cTemperatures[i] / 273.15;
        }
    }

    vector_fp c(2 + 2 * numPoints);

    c[0] = static_cast<double>(numPoints);
    c[1] = h298;
    for (size_t i = 0; i < numPoints; i++) {
        c[2 + i * 2] = cTemperatures[i];
        c[2 + i * 2 + 1] = cValues[i];
    }

    sp.install(speciesName, k, MU0_INTERP, &c[0], tmin, tmax, pref);
}
  /** 
   * Install a NASA polynomial thermodynamic property
   * parameterization for species k into a SpeciesThermo instance.
   * This is called by method installThermoForSpecies if a NASA
   * block is found in the XML input.
   */
  static void installNasaThermoFromXML(std::string speciesName,
				       SpeciesThermo& sp, int k, 
				       const XML_Node* f0ptr, const XML_Node* f1ptr) {
    doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax;

    const XML_Node& f0 = *f0ptr;

    // default to a single temperature range
    bool dualRange = false;

    // but if f1ptr is suppled, then it is a two-range
    // parameterization
    if (f1ptr) {dualRange = true;}

    tmin0 = fpValue(f0["Tmin"]);
    tmax0 = fpValue(f0["Tmax"]);

    doublereal p0 = OneAtm;
    if (f0.hasAttrib("P0")) {
      p0 = fpValue(f0["P0"]);
    }
    if (f0.hasAttrib("Pref")) {
      p0 = fpValue(f0["Pref"]);
    }
    p0 = OneAtm;

    tmin1 = tmax0;
    tmax1 = tmin1 + 0.0001;
    if (dualRange) {
      tmin1 = fpValue((*f1ptr)["Tmin"]);
      tmax1 = fpValue((*f1ptr)["Tmax"]);
    }

    vector_fp c0, c1;
    if (fabs(tmax0 - tmin1) < 0.01) {
      // f0 has the lower T data, and f1 the higher T data
      tmin = tmin0;
      tmid = tmax0;
      tmax = tmax1;
      getFloatArray(f0.child("floatArray"), c0, false);
      if (dualRange)
	getFloatArray(f1ptr->child("floatArray"), c1, false);
      else {
	// if there is no higher range data, then copy c0 to c1.
	c1.resize(7,0.0);
	copy(c0.begin(), c0.end(), c1.begin());
      }
    }
    else if (fabs(tmax1 - tmin0) < 0.01) {
      // f1 has the lower T data, and f0 the higher T data
      tmin = tmin1;
      tmid = tmax1;
      tmax = tmax0;
      getFloatArray(f1ptr->child("floatArray"), c0, false);
      getFloatArray(f0.child("floatArray"), c1, false);
    }
    else {
      throw CanteraError("installNasaThermo",
			 "non-continuous temperature ranges.");
    }

    // The NasaThermo species property manager expects the
    // coefficients in a different order, so rearrange them.
    array_fp c(15);
    c[0] = tmid;
   
    c[1] = c0[5];
    c[2] = c0[6];
    copy(c0.begin(), c0.begin()+5, c.begin() + 3);
    c[8] = c1[5];
    c[9] = c1[6];
    copy(c1.begin(), c1.begin()+5, c.begin() + 10);
    sp.install(speciesName, k, NASA, &c[0], tmin, tmax, p0);
  }
Exemple #21
0
void Phase::addElement(const XML_Node& e)
{
    doublereal weight = fpValue(e["atomicWt"]);
    string symbol = e["name"];
    addElement(symbol, weight);
}
/*!
 *  This is called if a 'Shomate' node is found in the XML input.
 *
 *  @param nodes        vector of 1 or 2 'Shomate' XML_Nodes, each defining the
 *      coefficients for a temperature range
 */
static SpeciesThermoInterpType* newShomateThermoFromXML(
    vector<XML_Node*>& nodes)
{
    bool dualRange = false;
    if (nodes.size() == 2) {
        dualRange = true;
    }
    double tmin0 = fpValue(nodes[0]->attrib("Tmin"));
    double tmax0 = fpValue(nodes[0]->attrib("Tmax"));

    doublereal p0 = OneAtm;
    if (nodes[0]->hasAttrib("P0")) {
        p0 = fpValue(nodes[0]->attrib("P0"));
    }
    if (nodes[0]->hasAttrib("Pref")) {
        p0 = fpValue(nodes[0]->attrib("Pref"));
    }
    p0 = OneAtm;

    double tmin1 = tmax0;
    double tmax1 = tmin1 + 0.0001;
    if (dualRange) {
        tmin1 = fpValue(nodes[1]->attrib("Tmin"));
        tmax1 = fpValue(nodes[1]->attrib("Tmax"));
    }

    vector_fp c0, c1;
    doublereal tmin, tmid, tmax;
    if (fabs(tmax0 - tmin1) < 0.01) {
        tmin = tmin0;
        tmid = tmax0;
        tmax = tmax1;
        getFloatArray(nodes[0]->child("floatArray"), c0, false);
        if (dualRange) {
            getFloatArray(nodes[1]->child("floatArray"), c1, false);
        } else {
            if(c0.size() != 7)
            {
              throw CanteraError("installShomateThermoFromXML",
                                 "Shomate thermo requires 7 coefficients in float array.");
            }
            c1.resize(7,0.0);
            copy(c0.begin(), c0.begin()+7, c1.begin());
        }
    } else if (fabs(tmax1 - tmin0) < 0.01) {
        tmin = tmin1;
        tmid = tmax1;
        tmax = tmax0;
        getFloatArray(nodes[1]->child("floatArray"), c0, false);
        getFloatArray(nodes[0]->child("floatArray"), c1, false);
    } else {
        throw CanteraError("installShomateThermoFromXML",
                           "non-continuous temperature ranges.");
    }
    if(c0.size() != 7 || c1.size() != 7)
    {
      throw CanteraError("installShomateThermoFromXML",
                         "Shomate thermo requires 7 coefficients in float array.");
    }
    vector_fp c(15);
    c[0] = tmid;
    copy(c0.begin(), c0.begin()+7, c.begin() + 1);
    copy(c1.begin(), c1.begin()+7, c.begin() + 8);
    return newSpeciesThermoInterpType(SHOMATE, tmin, tmax, p0, &c[0]);
}