Cantera  2.1.2
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  */
12 #include "cantera/base/xml.h"
13 #include "cantera/base/ctml.h"
15 
16 using namespace std;
17 using namespace ctml;
18 
19 namespace Cantera
20 {
21 Mu0Poly::Mu0Poly() : m_numIntervals(0),
22  m_H298(0.0)
23 {
24 }
25 
26 Mu0Poly::Mu0Poly(size_t n, doublereal tlow, doublereal thigh,
27  doublereal pref,
28  const doublereal* coeffs) :
29  SpeciesThermoInterpType(n, tlow, thigh, pref),
30  m_numIntervals(0),
31  m_H298(0.0)
32 {
33  processCoeffs(coeffs);
34 }
35 
38  m_numIntervals(b.m_numIntervals),
39  m_H298(b.m_H298),
40  m_t0_int(b.m_t0_int),
41  m_mu0_R_int(b.m_mu0_R_int),
42  m_h0_R_int(b.m_h0_R_int),
43  m_s0_R_int(b.m_s0_R_int),
44  m_cp0_R_int(b.m_cp0_R_int)
45 {
46 }
47 
49 {
50  if (&b != this) {
51  SpeciesThermoInterpType::operator=(b);
53  m_H298 = b.m_H298;
54  m_t0_int = b.m_t0_int;
59  }
60  return *this;
61 }
62 
65 {
66  return new Mu0Poly(*this);
67 }
68 
69 void Mu0Poly::
70 updateProperties(const doublereal* tt, doublereal* cp_R,
71  doublereal* h_RT, doublereal* s_R) const
72 {
73  size_t j = m_numIntervals;
74  double T = *tt;
75  for (size_t i = 0; i < m_numIntervals; i++) {
76  double T2 = m_t0_int[i+1];
77  if (T <=T2) {
78  j = i;
79  break;
80  }
81  }
82  double T1 = m_t0_int[j];
83  double cp_Rj = m_cp0_R_int[j];
84 
85  doublereal rt = 1.0/T;
86  cp_R[m_index] = cp_Rj;
87  h_RT[m_index] = rt*(m_h0_R_int[j] + (T - T1) * cp_Rj);
88  s_R[m_index] = m_s0_R_int[j] + cp_Rj * (log(T/T1));
89 }
90 
91 void Mu0Poly::
92 updatePropertiesTemp(const doublereal T,
93  doublereal* cp_R,
94  doublereal* h_RT,
95  doublereal* s_R) const
96 {
97  updateProperties(&T, cp_R, h_RT, s_R);
98 }
99 
100 void Mu0Poly::reportParameters(size_t& n, int& type,
101  doublereal& tlow, doublereal& thigh,
102  doublereal& pref,
103  doublereal* const coeffs) const
104 {
105  warn_deprecated("Mu0Poly::reportParameters");
106  n = m_index;
107  type = MU0_INTERP;
108  tlow = m_lowT;
109  thigh = m_highT;
110  pref = m_Pref;
111  coeffs[0] = int(m_numIntervals)+1;
112  coeffs[1] = m_H298 * GasConstant;
113  int j = 2;
114  for (size_t i = 0; i < m_numIntervals+1; i++) {
115  coeffs[j] = m_t0_int[i];
116  coeffs[j+1] = m_mu0_R_int[i] * GasConstant;
117  j += 2;
118  }
119 }
120 
121 void Mu0Poly::modifyParameters(doublereal* coeffs)
122 {
123  processCoeffs(coeffs);
124 }
125 
126 void installMu0ThermoFromXML(const std::string& speciesName,
127  SpeciesThermo& sp, size_t k,
128  const XML_Node* Mu0Node_ptr)
129 {
130 
131  doublereal tmin, tmax;
132  bool dimensionlessMu0Values = false;
133  const XML_Node& Mu0Node = *Mu0Node_ptr;
134 
135  tmin = fpValue(Mu0Node["Tmin"]);
136  tmax = fpValue(Mu0Node["Tmax"]);
137  doublereal pref = fpValue(Mu0Node["Pref"]);
138 
139  doublereal h298 = 0.0;
140  if (Mu0Node.hasChild("H298")) {
141  h298 = getFloat(Mu0Node, "H298", "actEnergy");
142  }
143 
144  size_t numPoints = 1;
145  if (Mu0Node.hasChild("numPoints")) {
146  numPoints = getInteger(Mu0Node, "numPoints");
147  }
148 
149  vector_fp cValues(numPoints);
150  const XML_Node* valNode_ptr =
151  getByTitle(const_cast<XML_Node&>(Mu0Node), "Mu0Values");
152  if (!valNode_ptr) {
153  throw CanteraError("installMu0ThermoFromXML",
154  "missing required while processing "
155  + speciesName);
156  }
157  getFloatArray(*valNode_ptr, cValues, true, "actEnergy");
158  /*
159  * Check to see whether the Mu0's were input in a dimensionless
160  * form. If they were, then the assumed temperature needs to be
161  * adjusted from the assumed T = 273.15
162  */
163  string uuu = (*valNode_ptr)["units"];
164  if (uuu == "Dimensionless") {
165  dimensionlessMu0Values = true;
166  }
167  size_t ns = cValues.size();
168  if (ns != numPoints) {
169  throw CanteraError("installMu0ThermoFromXML",
170  "numPoints inconsistent while processing "
171  + speciesName);
172  }
173 
174  vector_fp cTemperatures(numPoints);
175  const XML_Node* tempNode_ptr =
176  getByTitle(const_cast<XML_Node&>(Mu0Node), "Mu0Temperatures");
177  if (!tempNode_ptr) {
178  throw CanteraError("installMu0ThermoFromXML",
179  "missing required while processing + "
180  + speciesName);
181  }
182  getFloatArray(*tempNode_ptr, cTemperatures, false);
183  ns = cTemperatures.size();
184  if (ns != numPoints) {
185  throw CanteraError("installMu0ThermoFromXML",
186  "numPoints inconsistent while processing "
187  + speciesName);
188  }
189 
190  /*
191  * Fix up dimensionless Mu0 values if input
192  */
193  if (dimensionlessMu0Values) {
194  for (size_t i = 0; i < numPoints; i++) {
195  cValues[i] *= cTemperatures[i] / 273.15;
196  }
197  }
198 
199 
200  vector_fp c(2 + 2 * numPoints);
201 
202  c[0] = static_cast<double>(numPoints);
203  c[1] = h298;
204  for (size_t i = 0; i < numPoints; i++) {
205  c[2+i*2] = cTemperatures[i];
206  c[2+i*2+1] = cValues[i];
207  }
208 
209  sp.install(speciesName, k, MU0_INTERP, &c[0], tmin, tmax, pref);
210 }
211 
212 void Mu0Poly::processCoeffs(const doublereal* coeffs)
213 {
214  size_t i, iindex;
215  double T1, T2;
216  size_t nPoints = (size_t) coeffs[0];
217  if (nPoints < 2) {
218  throw CanteraError("Mu0Poly",
219  "nPoints must be >= 2");
220  }
221  m_numIntervals = nPoints - 1;
222  m_H298 = coeffs[1] / GasConstant;
223  size_t iT298 = 0;
224  /*
225  * Resize according to the number of points
226  */
227  m_t0_int.resize(nPoints);
228  m_h0_R_int.resize(nPoints);
229  m_s0_R_int.resize(nPoints);
230  m_cp0_R_int.resize(nPoints);
231  m_mu0_R_int.resize(nPoints);
232  /*
233  * Calculate the T298 interval and make sure that
234  * the temperatures are strictly monotonic.
235  * Also distribute the data into the internal arrays.
236  */
237  bool ifound = false;
238  for (i = 0, iindex = 2; i < nPoints; i++) {
239  T1 = coeffs[iindex];
240  m_t0_int[i] = T1;
241  m_mu0_R_int[i] = coeffs[iindex+1] / GasConstant;
242  if (T1 == 298.15) {
243  iT298 = i;
244  ifound = true;
245  }
246  if (i < nPoints - 1) {
247  T2 = coeffs[iindex+2];
248  if (T2 <= T1) {
249  throw CanteraError("Mu0Poly",
250  "Temperatures are not monotonic increasing");
251  }
252  }
253  iindex += 2;
254  }
255  if (!ifound) {
256  throw CanteraError("Mu0Poly",
257  "One temperature has to be 298.15");
258  }
259 
260  /*
261  * Starting from the interval with T298, we go up
262  */
263  doublereal mu2, s1, s2, h1, h2, cpi, deltaMu, deltaT;
264  T1 = m_t0_int[iT298];
265  doublereal mu1 = m_mu0_R_int[iT298];
266  m_h0_R_int[iT298] = m_H298;
267  m_s0_R_int[iT298] = - (mu1 - m_h0_R_int[iT298]) / T1;
268  for (i = iT298; i < m_numIntervals; i++) {
269  T1 = m_t0_int[i];
270  s1 = m_s0_R_int[i];
271  h1 = m_h0_R_int[i];
272  mu1 = m_mu0_R_int[i];
273  T2 = m_t0_int[i+1];
274  mu2 = m_mu0_R_int[i+1];
275  deltaMu = mu2 - mu1;
276  deltaT = T2 - T1;
277  cpi = (deltaMu - T1 * s1 + T2 * s1) / (deltaT - T2 * log(T2/T1));
278  h2 = h1 + cpi * deltaT;
279  s2 = s1 + cpi * log(T2/T1);
280  m_cp0_R_int[i] = cpi;
281  m_h0_R_int[i+1] = h2;
282  m_s0_R_int[i+1] = s2;
283  m_cp0_R_int[i+1] = cpi;
284  }
285 
286  /*
287  * Starting from the interval with T298, we go down
288  */
289  if (iT298 != 0) {
290  T2 = m_t0_int[iT298];
291  mu2 = m_mu0_R_int[iT298];
292  m_h0_R_int[iT298] = m_H298;
293  m_s0_R_int[iT298] = - (mu2 - m_h0_R_int[iT298]) / T2;
294  for (i = iT298 - 1; i != npos; i--) {
295  T1 = m_t0_int[i];
296  mu1 = m_mu0_R_int[i];
297  T2 = m_t0_int[i+1];
298  mu2 = m_mu0_R_int[i+1];
299  s2 = m_s0_R_int[i+1];
300  h2 = m_h0_R_int[i+1];
301  deltaMu = mu2 - mu1;
302  deltaT = T2 - T1;
303  cpi = (deltaMu - T1 * s2 + T2 * s2) / (deltaT - T1 * log(T2/T1));
304  h1 = h2 - cpi * deltaT;
305  s1 = s2 - cpi * log(T2/T1);
306  m_cp0_R_int[i] = cpi;
307  m_h0_R_int[i] = h1;
308  m_s0_R_int[i] = s1;
309  if (i == (m_numIntervals-1)) {
310  m_cp0_R_int[i+1] = cpi;
311  }
312  }
313  }
314 #ifdef DEBUG_HKM_NOT
315  printf(" Temp mu0(J/kmol) cp0(J/kmol/K) "
316  " h0(J/kmol) s0(J/kmol/K) \n");
317  for (i = 0; i < nPoints; i++) {
318  printf("%12.3g %12.5g %12.5g %12.5g %12.5g\n",
320  m_cp0_R_int[i]* GasConstant,
321  m_h0_R_int[i]* GasConstant,
322  m_s0_R_int[i]* GasConstant);
323  fflush(stdout);
324  }
325 #endif
326 }
327 
328 }
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...
Pure Virtual Base class for the thermodynamic manager for an individual species' 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:182
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:92
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:173
Mu0Poly()
Constructor.
Definition: Mu0Poly.cpp:21
size_t m_numIntervals
Number of intervals in the interpolating linear approximation.
Definition: Mu0Poly.h:161
virtual void install(const std::string &name, size_t index, int type, const doublereal *c, doublereal minTemp, doublereal maxTemp, doublereal refPressure)=0
Install a new species thermodynamic property parameterization for one species.
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:100
vector_fp m_cp0_R_int
Heat capacity at the points.
Definition: Mu0Poly.h:185
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:76
Virtual base class for the calculation of multiple-species thermodynamic reference-state property man...
doublereal getFloat(const Cantera::XML_Node &parent, const std::string &name, const std::string &type)
Get a floating-point value from a child element.
Definition: ctml.cpp:267
The Mu0Poly class implements an interpolation of the Gibbs free energy based on a piecewise constant ...
Definition: Mu0Poly.h:71
void installMu0ThermoFromXML(const std::string &speciesName, SpeciesThermo &sp, size_t k, const XML_Node *Mu0Node_ptr)
Install a Mu0 polynomial thermodynamic reference state.
Definition: Mu0Poly.cpp:126
Pure Virtual base class for the species thermo manager classes.
doublereal m_H298
Value of the enthalpy at T = 298.15.
Definition: Mu0Poly.h:167
XML_Node * getByTitle(const Cantera::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:152
#define MU0_INTERP
piecewise interpolation of mu0.
Contains const definitions for types of species reference-state thermodynamics managers (see Species ...
virtual void reportParameters(size_t &n, int &type, doublereal &tlow, doublereal &thigh, doublereal &pref, doublereal *const coeffs) const
Definition: Mu0Poly.cpp:100
Mu0Poly & operator=(const Mu0Poly &)
Assignment operator.
Definition: Mu0Poly.cpp:48
virtual SpeciesThermoInterpType * duplMyselfAsSpeciesThermoInterpType() const
duplicator
Definition: Mu0Poly.cpp:64
Classes providing support for XML data files.
doublereal m_highT
Highest valid temperature.
vector_fp m_mu0_R_int
Mu0's are primary input data.
Definition: Mu0Poly.h:176
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:68
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:574
virtual void modifyParameters(doublereal *coeffs)
Modify parameters for the standard state.
Definition: Mu0Poly.cpp:121
doublereal m_lowT
lowest valid temperature
virtual void updateProperties(const doublereal *tPoly, doublereal *cp_R, doublereal *h_RT, doublereal *s_R) const
Update the properties for this species, given a temperature polynomial.
Definition: Mu0Poly.cpp:70
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:165
const doublereal GasConstant
Universal Gas Constant. [J/kmol/K].
Definition: ct_defs.h:66
vector_fp m_t0_int
Points at which the standard state chemical potential are given.
Definition: Mu0Poly.h:170
Contains declarations for string manipulation functions within Cantera.
vector_fp m_h0_R_int
Dimensionless Enthalpies at the temperature points.
Definition: Mu0Poly.h:179
doublereal m_Pref
Reference state pressure.
int getInteger(const Cantera::XML_Node &parent, const std::string &name)
Get an integer value from a child element.
Definition: ctml.cpp:387
size_t getFloatArray(const Cantera::XML_Node &node, std::vector< doublereal > &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:419
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
void processCoeffs(const doublereal *coeffs)
process the coefficients
Definition: Mu0Poly.cpp:212