Cantera  2.4.0
Mu0Poly.cpp
Go to the documentation of this file.
1 /**
2  * @file Mu0Poly.cpp
3  * Definitions for a single-species standard state object derived
4  * from \link Cantera::SpeciesThermoInterpType SpeciesThermoInterpType\endlink based
5  * on a piecewise constant mu0 interpolation
6  * (see \ref spthermo and class \link Cantera::Mu0Poly Mu0Poly\endlink).
7  */
8 
9 // This file is part of Cantera. See License.txt in the top-level directory or
10 // at http://www.cantera.org/license.txt for license and copyright information.
11 
12 #include "cantera/thermo/Mu0Poly.h"
13 #include "cantera/base/ctml.h"
15 
16 using namespace std;
17 
18 namespace Cantera
19 {
20 
21 Mu0Poly::Mu0Poly(double tlow, double thigh, double pref, const double* coeffs) :
22  SpeciesThermoInterpType(tlow, thigh, pref),
23  m_numIntervals(0),
24  m_H298(0.0)
25 {
26  processCoeffs(coeffs);
27 }
28 
29 void Mu0Poly::updateProperties(const doublereal* tt, doublereal* cp_R,
30  doublereal* h_RT, doublereal* s_R) const
31 {
32  size_t j = m_numIntervals;
33  double T = *tt;
34  for (size_t i = 0; i < m_numIntervals; i++) {
35  double T2 = m_t0_int[i+1];
36  if (T <=T2) {
37  j = i;
38  break;
39  }
40  }
41  double T1 = m_t0_int[j];
42  double cp_Rj = m_cp0_R_int[j];
43  *cp_R = cp_Rj;
44  *h_RT = (m_h0_R_int[j] + (T - T1) * cp_Rj)/T;
45  *s_R = m_s0_R_int[j] + cp_Rj * (log(T/T1));
46 }
47 
48 void Mu0Poly::updatePropertiesTemp(const doublereal T,
49  doublereal* cp_R,
50  doublereal* h_RT,
51  doublereal* s_R) const
52 {
53  updateProperties(&T, cp_R, h_RT, s_R);
54 }
55 
56 void Mu0Poly::reportParameters(size_t& n, int& type,
57  doublereal& tlow, doublereal& thigh,
58  doublereal& pref,
59  doublereal* const coeffs) const
60 {
61  n = 0;
62  type = MU0_INTERP;
63  tlow = m_lowT;
64  thigh = m_highT;
65  pref = m_Pref;
66  coeffs[0] = int(m_numIntervals)+1;
67  coeffs[1] = m_H298 * GasConstant;
68  int j = 2;
69  for (size_t i = 0; i < m_numIntervals+1; i++) {
70  coeffs[j] = m_t0_int[i];
71  coeffs[j+1] = m_mu0_R_int[i] * GasConstant;
72  j += 2;
73  }
74 }
75 
77 {
78  bool dimensionlessMu0Values = false;
79 
80  doublereal h298 = 0.0;
81  if (Mu0Node.hasChild("H298")) {
82  h298 = getFloat(Mu0Node, "H298", "actEnergy");
83  }
84 
85  size_t numPoints = 1;
86  if (Mu0Node.hasChild("numPoints")) {
87  numPoints = getInteger(Mu0Node, "numPoints");
88  }
89 
90  vector_fp cValues(numPoints);
91  const XML_Node* valNode_ptr = getByTitle(Mu0Node, "Mu0Values");
92  if (!valNode_ptr) {
93  throw CanteraError("installMu0ThermoFromXML", "missing Mu0Values");
94  }
95  getFloatArray(*valNode_ptr, cValues, true, "actEnergy");
96 
97  // Check to see whether the Mu0's were input in a dimensionless form. If
98  // they were, then the assumed temperature needs to be adjusted from the
99  // assumed T = 273.15
100  if (valNode_ptr->attrib("units") == "Dimensionless") {
101  dimensionlessMu0Values = true;
102  }
103  if (cValues.size() != numPoints) {
104  throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent");
105  }
106 
107  vector_fp cTemperatures(numPoints);
108  const XML_Node* tempNode_ptr = getByTitle(Mu0Node, "Mu0Temperatures");
109  if (!tempNode_ptr) {
110  throw CanteraError("installMu0ThermoFromXML",
111  "missing Mu0Temperatures");
112  }
113  getFloatArray(*tempNode_ptr, cTemperatures, false);
114  if (cTemperatures.size() != numPoints) {
115  throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent");
116  }
117 
118  // Fix up dimensionless Mu0 values if input
119  if (dimensionlessMu0Values) {
120  for (size_t i = 0; i < numPoints; i++) {
121  cValues[i] *= cTemperatures[i] / 273.15;
122  }
123  }
124 
125  vector_fp c(2 + 2 * numPoints);
126  c[0] = static_cast<double>(numPoints);
127  c[1] = h298;
128  for (size_t i = 0; i < numPoints; i++) {
129  c[2+i*2] = cTemperatures[i];
130  c[2+i*2+1] = cValues[i];
131  }
132 
133  return new Mu0Poly(fpValue(Mu0Node["Tmin"]), fpValue(Mu0Node["Tmax"]),
134  fpValue(Mu0Node["Pref"]), &c[0]);
135 }
136 
137 void Mu0Poly::processCoeffs(const doublereal* coeffs)
138 {
139  size_t nPoints = (size_t) coeffs[0];
140  if (nPoints < 2) {
141  throw CanteraError("Mu0Poly",
142  "nPoints must be >= 2");
143  }
144  m_numIntervals = nPoints - 1;
145  m_H298 = coeffs[1] / GasConstant;
146  size_t iT298 = 0;
147 
148  // Resize according to the number of points
149  m_t0_int.resize(nPoints);
150  m_h0_R_int.resize(nPoints);
151  m_s0_R_int.resize(nPoints);
152  m_cp0_R_int.resize(nPoints);
153  m_mu0_R_int.resize(nPoints);
154 
155  // Calculate the T298 interval and make sure that the temperatures are
156  // strictly monotonic. Also distribute the data into the internal arrays.
157  bool ifound = false;
158  for (size_t i = 0, iindex = 2; i < nPoints; i++) {
159  double T1 = coeffs[iindex];
160  m_t0_int[i] = T1;
161  m_mu0_R_int[i] = coeffs[iindex+1] / GasConstant;
162  if (T1 == 298.15) {
163  iT298 = i;
164  ifound = true;
165  }
166  if (i < nPoints - 1 && coeffs[iindex+2] <= T1) {
167  throw CanteraError("Mu0Poly",
168  "Temperatures are not monotonic increasing");
169  }
170  iindex += 2;
171  }
172  if (!ifound) {
173  throw CanteraError("Mu0Poly",
174  "One temperature has to be 298.15");
175  }
176 
177  // Starting from the interval with T298, we go up
178  m_h0_R_int[iT298] = m_H298;
179  m_s0_R_int[iT298] = - (m_mu0_R_int[iT298] - m_h0_R_int[iT298]) / m_t0_int[iT298];
180  for (size_t i = iT298; i < m_numIntervals; i++) {
181  double T1 = m_t0_int[i];
182  double s1 = m_s0_R_int[i];
183  double T2 = m_t0_int[i+1];
184  double deltaMu = m_mu0_R_int[i+1] - m_mu0_R_int[i];
185  double deltaT = T2 - T1;
186  double cpi = (deltaMu - T1 * s1 + T2 * s1) / (deltaT - T2 * log(T2/T1));
187  m_cp0_R_int[i] = cpi;
188  m_h0_R_int[i+1] = m_h0_R_int[i] + cpi * deltaT;
189  m_s0_R_int[i+1] = s1 + cpi * log(T2/T1);
190  m_cp0_R_int[i+1] = cpi;
191  }
192 
193  // Starting from the interval with T298, we go down
194  if (iT298 != 0) {
195  m_h0_R_int[iT298] = m_H298;
196  m_s0_R_int[iT298] = - (m_mu0_R_int[iT298] - m_h0_R_int[iT298]) / m_t0_int[iT298];
197  for (size_t i = iT298 - 1; i != npos; i--) {
198  double T1 = m_t0_int[i];
199  double T2 = m_t0_int[i+1];
200  double s2 = m_s0_R_int[i+1];
201  double deltaMu = m_mu0_R_int[i+1] - m_mu0_R_int[i];
202  double deltaT = T2 - T1;
203  double cpi = (deltaMu - T1 * s2 + T2 * s2) / (deltaT - T1 * log(T2/T1));
204  m_cp0_R_int[i] = cpi;
205  m_h0_R_int[i] = m_h0_R_int[i+1] - cpi * deltaT;
206  m_s0_R_int[i] = s2 - cpi * log(T2/T1);
207  if (i == (m_numIntervals-1)) {
208  m_cp0_R_int[i+1] = cpi;
209  }
210  }
211  }
212 }
213 
214 }
doublereal fpValue(const std::string &val)
Translate a string into one doublereal value.
Header for a single-species standard state object derived from SpeciesThermoInterpType based on a pie...
Abstract Base class for the thermodynamic manager for an individual species&#39; reference state...
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
vector_fp m_s0_R_int
Entropy at the points.
Definition: Mu0Poly.h:144
size_t getFloatArray(const XML_Node &node, vector_fp &v, const bool convert, const std::string &unitsString, const std::string &nodeName)
This function reads the current node or a child node of the current node with the default name...
Definition: ctml.cpp:256
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
size_t m_numIntervals
Number of intervals in the interpolating linear approximation.
Definition: Mu0Poly.h:127
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:97
vector_fp m_cp0_R_int
Heat capacity at the points.
Definition: Mu0Poly.h:147
STL namespace.
The Mu0Poly class implements an interpolation of the Gibbs free energy based on a piecewise constant ...
Definition: Mu0Poly.h:73
doublereal m_H298
Value of the enthalpy at T = 298.15.
Definition: Mu0Poly.h:131
#define MU0_INTERP
piecewise interpolation of mu0.
virtual void updatePropertiesTemp(const doublereal temp, doublereal *cp_R, doublereal *h_RT, doublereal *s_R) const
Compute the reference-state property of one species.
Definition: Mu0Poly.cpp:48
virtual void updateProperties(const doublereal *tt, doublereal *cp_R, doublereal *h_RT, doublereal *s_R) const
Update the properties for this species, given a temperature polynomial.
Definition: Mu0Poly.cpp:29
doublereal m_highT
Highest valid temperature.
vector_fp m_mu0_R_int
Mu0&#39;s are primary input data.
Definition: Mu0Poly.h:138
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
doublereal m_lowT
lowest valid temperature
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:536
int getInteger(const XML_Node &parent, const std::string &name)
Get an integer value from a child element.
Definition: ctml.cpp:234
virtual void reportParameters(size_t &n, int &type, doublereal &tlow, doublereal &thigh, doublereal &pref, doublereal *const coeffs) const
This utility function reports back the type of parameterization and all of the parameters for the spe...
Definition: Mu0Poly.cpp:56
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:500
XML_Node * getByTitle(const XML_Node &node, const std::string &title)
Search the child nodes of the current node for an XML Node with a Title attribute of a given name...
Definition: ctml.cpp:122
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:157
const doublereal GasConstant
Universal Gas Constant. [J/kmol/K].
Definition: ct_defs.h:64
vector_fp m_t0_int
Points at which the standard state chemical potential are given.
Definition: Mu0Poly.h:134
Contains declarations for string manipulation functions within Cantera.
doublereal getFloat(const XML_Node &parent, const std::string &name, const std::string &type)
Get a floating-point value from a child element.
Definition: ctml.cpp:164
vector_fp m_h0_R_int
Dimensionless Enthalpies at the temperature points.
Definition: Mu0Poly.h:141
doublereal m_Pref
Reference state pressure.
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:8
Mu0Poly * newMu0ThermoFromXML(const XML_Node &Mu0Node)
Install a Mu0 polynomial thermodynamic reference state.
Definition: Mu0Poly.cpp:76
void processCoeffs(const doublereal *coeffs)
process the coefficients
Definition: Mu0Poly.cpp:137