Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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  */
10 #include "cantera/base/ctml.h"
12 
13 using namespace std;
14 
15 namespace Cantera
16 {
17 Mu0Poly::Mu0Poly() : m_numIntervals(0),
18  m_H298(0.0)
19 {
20 }
21 
22 Mu0Poly::Mu0Poly(size_t n, doublereal tlow, doublereal thigh,
23  doublereal pref,
24  const doublereal* coeffs) :
25  SpeciesThermoInterpType(n, tlow, thigh, pref),
26  m_numIntervals(0),
27  m_H298(0.0)
28 {
29  processCoeffs(coeffs);
30 }
31 
32 Mu0Poly::Mu0Poly(double tlow, double thigh, double pref, const double* coeffs) :
33  SpeciesThermoInterpType(tlow, thigh, pref),
34  m_numIntervals(0),
35  m_H298(0.0)
36 {
37  processCoeffs(coeffs);
38 }
39 
42  m_numIntervals(b.m_numIntervals),
43  m_H298(b.m_H298),
44  m_t0_int(b.m_t0_int),
45  m_mu0_R_int(b.m_mu0_R_int),
46  m_h0_R_int(b.m_h0_R_int),
47  m_s0_R_int(b.m_s0_R_int),
48  m_cp0_R_int(b.m_cp0_R_int)
49 {
50 }
51 
53 {
54  if (&b != this) {
55  SpeciesThermoInterpType::operator=(b);
57  m_H298 = b.m_H298;
58  m_t0_int = b.m_t0_int;
63  }
64  return *this;
65 }
66 
68 Mu0Poly::duplMyselfAsSpeciesThermoInterpType() const
69 {
70  return new Mu0Poly(*this);
71 }
72 
73 void Mu0Poly::updateProperties(const doublereal* tt, doublereal* cp_R,
74  doublereal* h_RT, doublereal* s_R) const
75 {
76  size_t j = m_numIntervals;
77  double T = *tt;
78  for (size_t i = 0; i < m_numIntervals; i++) {
79  double T2 = m_t0_int[i+1];
80  if (T <=T2) {
81  j = i;
82  break;
83  }
84  }
85  double T1 = m_t0_int[j];
86  double cp_Rj = m_cp0_R_int[j];
87  cp_R[m_index] = cp_Rj;
88  h_RT[m_index] = (m_h0_R_int[j] + (T - T1) * cp_Rj)/T;
89  s_R[m_index] = m_s0_R_int[j] + cp_Rj * (log(T/T1));
90 }
91 
92 void Mu0Poly::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  n = m_index;
106  type = MU0_INTERP;
107  tlow = m_lowT;
108  thigh = m_highT;
109  pref = m_Pref;
110  coeffs[0] = int(m_numIntervals)+1;
111  coeffs[1] = m_H298 * GasConstant;
112  int j = 2;
113  for (size_t i = 0; i < m_numIntervals+1; i++) {
114  coeffs[j] = m_t0_int[i];
115  coeffs[j+1] = m_mu0_R_int[i] * GasConstant;
116  j += 2;
117  }
118 }
119 
120 void Mu0Poly::modifyParameters(doublereal* coeffs)
121 {
122  processCoeffs(coeffs);
123 }
124 
126 {
127  bool dimensionlessMu0Values = false;
128 
129  doublereal h298 = 0.0;
130  if (Mu0Node.hasChild("H298")) {
131  h298 = getFloat(Mu0Node, "H298", "actEnergy");
132  }
133 
134  size_t numPoints = 1;
135  if (Mu0Node.hasChild("numPoints")) {
136  numPoints = getInteger(Mu0Node, "numPoints");
137  }
138 
139  vector_fp cValues(numPoints);
140  const XML_Node* valNode_ptr = getByTitle(Mu0Node, "Mu0Values");
141  if (!valNode_ptr) {
142  throw CanteraError("installMu0ThermoFromXML", "missing Mu0Values");
143  }
144  getFloatArray(*valNode_ptr, cValues, true, "actEnergy");
145  /*
146  * Check to see whether the Mu0's were input in a dimensionless
147  * form. If they were, then the assumed temperature needs to be
148  * adjusted from the assumed T = 273.15
149  */
150  if (valNode_ptr->attrib("units") == "Dimensionless") {
151  dimensionlessMu0Values = true;
152  }
153  if (cValues.size() != numPoints) {
154  throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent");
155  }
156 
157  vector_fp cTemperatures(numPoints);
158  const XML_Node* tempNode_ptr = getByTitle(Mu0Node, "Mu0Temperatures");
159  if (!tempNode_ptr) {
160  throw CanteraError("installMu0ThermoFromXML",
161  "missing Mu0Temperatures");
162  }
163  getFloatArray(*tempNode_ptr, cTemperatures, false);
164  if (cTemperatures.size() != numPoints) {
165  throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent");
166  }
167 
168  /*
169  * Fix up dimensionless Mu0 values if input
170  */
171  if (dimensionlessMu0Values) {
172  for (size_t i = 0; i < numPoints; i++) {
173  cValues[i] *= cTemperatures[i] / 273.15;
174  }
175  }
176 
177 
178  vector_fp c(2 + 2 * numPoints);
179 
180  c[0] = static_cast<double>(numPoints);
181  c[1] = h298;
182  for (size_t i = 0; i < numPoints; i++) {
183  c[2+i*2] = cTemperatures[i];
184  c[2+i*2+1] = cValues[i];
185  }
186 
187  return new Mu0Poly(fpValue(Mu0Node["Tmin"]), fpValue(Mu0Node["Tmax"]),
188  fpValue(Mu0Node["Pref"]), &c[0]);
189 }
190 
191 void Mu0Poly::processCoeffs(const doublereal* coeffs)
192 {
193  size_t nPoints = (size_t) coeffs[0];
194  if (nPoints < 2) {
195  throw CanteraError("Mu0Poly",
196  "nPoints must be >= 2");
197  }
198  m_numIntervals = nPoints - 1;
199  m_H298 = coeffs[1] / GasConstant;
200  size_t iT298 = 0;
201  /*
202  * Resize according to the number of points
203  */
204  m_t0_int.resize(nPoints);
205  m_h0_R_int.resize(nPoints);
206  m_s0_R_int.resize(nPoints);
207  m_cp0_R_int.resize(nPoints);
208  m_mu0_R_int.resize(nPoints);
209  /*
210  * Calculate the T298 interval and make sure that
211  * the temperatures are strictly monotonic.
212  * Also distribute the data into the internal arrays.
213  */
214  bool ifound = false;
215  for (size_t i = 0, iindex = 2; i < nPoints; i++) {
216  double T1 = coeffs[iindex];
217  m_t0_int[i] = T1;
218  m_mu0_R_int[i] = coeffs[iindex+1] / GasConstant;
219  if (T1 == 298.15) {
220  iT298 = i;
221  ifound = true;
222  }
223  if (i < nPoints - 1) {
224  if (coeffs[iindex+2] <= T1) {
225  throw CanteraError("Mu0Poly",
226  "Temperatures are not monotonic increasing");
227  }
228  }
229  iindex += 2;
230  }
231  if (!ifound) {
232  throw CanteraError("Mu0Poly",
233  "One temperature has to be 298.15");
234  }
235 
236  /*
237  * Starting from the interval with T298, we go up
238  */
239  m_h0_R_int[iT298] = m_H298;
240  m_s0_R_int[iT298] = - (m_mu0_R_int[iT298] - m_h0_R_int[iT298]) / m_t0_int[iT298];
241  for (size_t i = iT298; i < m_numIntervals; i++) {
242  double T1 = m_t0_int[i];
243  double s1 = m_s0_R_int[i];
244  double T2 = m_t0_int[i+1];
245  double deltaMu = m_mu0_R_int[i+1] - m_mu0_R_int[i];
246  double deltaT = T2 - T1;
247  double cpi = (deltaMu - T1 * s1 + T2 * s1) / (deltaT - T2 * log(T2/T1));
248  m_cp0_R_int[i] = cpi;
249  m_h0_R_int[i+1] = m_h0_R_int[i] + cpi * deltaT;
250  m_s0_R_int[i+1] = s1 + cpi * log(T2/T1);
251  m_cp0_R_int[i+1] = cpi;
252  }
253 
254  /*
255  * Starting from the interval with T298, we go down
256  */
257  if (iT298 != 0) {
258  m_h0_R_int[iT298] = m_H298;
259  m_s0_R_int[iT298] = - (m_mu0_R_int[iT298] - m_h0_R_int[iT298]) / m_t0_int[iT298];
260  for (size_t i = iT298 - 1; i != npos; i--) {
261  double T1 = m_t0_int[i];
262  double T2 = m_t0_int[i+1];
263  double s2 = m_s0_R_int[i+1];
264  double deltaMu = m_mu0_R_int[i+1] - m_mu0_R_int[i];
265  double deltaT = T2 - T1;
266  double cpi = (deltaMu - T1 * s2 + T2 * s2) / (deltaT - T1 * log(T2/T1));
267  m_cp0_R_int[i] = cpi;
268  m_h0_R_int[i] = m_h0_R_int[i+1] - cpi * deltaT;
269  m_s0_R_int[i] = s2 - cpi * log(T2/T1);
270  if (i == (m_numIntervals-1)) {
271  m_cp0_R_int[i+1] = cpi;
272  }
273  }
274  }
275 #ifdef DEBUG_HKM_NOT
276  printf(" Temp mu0(J/kmol) cp0(J/kmol/K) "
277  " h0(J/kmol) s0(J/kmol/K) \n");
278  for (i = 0; i < nPoints; i++) {
279  printf("%12.3g %12.5g %12.5g %12.5g %12.5g\n",
281  m_cp0_R_int[i]* GasConstant,
282  m_h0_R_int[i]* GasConstant,
283  m_s0_R_int[i]* GasConstant);
284  fflush(stdout);
285  }
286 #endif
287 }
288 
289 }
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...
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:527
vector_fp m_s0_R_int
Entropy at the points.
Definition: Mu0Poly.h:209
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:165
Mu0Poly()
Constructor.
Definition: Mu0Poly.cpp:17
size_t m_numIntervals
Number of intervals in the interpolating linear approximation.
Definition: Mu0Poly.h:188
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:212
Virtual base class for the calculation of multiple-species thermodynamic reference-state property man...
The Mu0Poly class implements an interpolation of the Gibbs free energy based on a piecewise constant ...
Definition: Mu0Poly.h:71
doublereal m_H298
Value of the enthalpy at T = 298.15.
Definition: Mu0Poly.h:194
#define MU0_INTERP
piecewise interpolation of mu0.
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:100
Mu0Poly & operator=(const Mu0Poly &)
Assignment operator.
Definition: Mu0Poly.cpp:52
doublereal m_highT
Highest valid temperature.
vector_fp m_mu0_R_int
Mu0's are primary input data.
Definition: Mu0Poly.h:203
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:563
virtual void modifyParameters(doublereal *coeffs)
Modify parameters for the standard state.
Definition: Mu0Poly.cpp:120
doublereal m_lowT
lowest valid temperature
int getInteger(const XML_Node &parent, const std::string &name)
Get an integer value from a child element.
Definition: ctml.cpp:301
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:73
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:133
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
size_t getFloatArray(const 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:323
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:197
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:194
vector_fp m_h0_R_int
Dimensionless Enthalpies at the temperature points.
Definition: Mu0Poly.h:206
doublereal m_Pref
Reference state pressure.
Mu0Poly * newMu0ThermoFromXML(const XML_Node &Mu0Node)
Install a Mu0 polynomial thermodynamic reference state.
Definition: Mu0Poly.cpp:125
void processCoeffs(const doublereal *coeffs)
process the coefficients
Definition: Mu0Poly.cpp:191