Cantera 2.6.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 https://cantera.org/license.txt for license and copyright information.
11
13#include "cantera/base/ctml.h"
15#include "cantera/base/AnyMap.h"
16
17using namespace std;
18
19namespace Cantera
20{
21Mu0Poly::Mu0Poly()
22 : SpeciesThermoInterpType(0.0, std::numeric_limits<double>::infinity(), 0.0)
23 , m_numIntervals(0)
24 , m_H298(0.0)
25{
26}
27
28Mu0Poly::Mu0Poly(double tlow, double thigh, double pref, const double* coeffs) :
29 SpeciesThermoInterpType(tlow, thigh, pref),
30 m_numIntervals(0),
31 m_H298(0.0)
32{
33 std::map<double, double> T_mu;
34 size_t nPoints = (size_t) coeffs[0];
35 for (size_t i = 0; i < nPoints; i++) {
36 T_mu[coeffs[2*i+2]] = coeffs[2*i+3];
37 }
38 setParameters(coeffs[1], T_mu);
39}
40
41void Mu0Poly::setParameters(double h0, const std::map<double, double>& T_mu)
42{
43 size_t nPoints = T_mu.size();
44 if (nPoints < 2) {
45 throw CanteraError("Mu0Poly::setParameters", "nPoints must be >= 2");
46 }
47 m_numIntervals = nPoints - 1;
48 m_H298 = h0 / GasConstant;
49
50 // Distribute the data into the internal arrays, and find the index of the
51 // point at 298.15 K.
52 size_t iT298 = npos;
53 for (const auto& row : T_mu) {
54 double T1 = row.first;
55 if (T1 == 298.15) {
56 iT298 = m_t0_int.size();
57 }
58 m_t0_int.push_back(T1);
59 m_mu0_R_int.push_back(row.second / GasConstant);
60 }
61 if (iT298 == npos) {
62 throw CanteraError("Mu0Poly::setParameters",
63 "One temperature has to be 298.15");
64 }
65
66 // Resize according to the number of points
67 m_h0_R_int.resize(nPoints);
68 m_s0_R_int.resize(nPoints);
69 m_cp0_R_int.resize(nPoints);
70
71 // Starting from the interval with T298, we go up
72 m_h0_R_int[iT298] = m_H298;
73 m_s0_R_int[iT298] = - (m_mu0_R_int[iT298] - m_h0_R_int[iT298]) / m_t0_int[iT298];
74 for (size_t i = iT298; i < m_numIntervals; i++) {
75 double T1 = m_t0_int[i];
76 double s1 = m_s0_R_int[i];
77 double T2 = m_t0_int[i+1];
78 double deltaMu = m_mu0_R_int[i+1] - m_mu0_R_int[i];
79 double deltaT = T2 - T1;
80 double cpi = (deltaMu - T1 * s1 + T2 * s1) / (deltaT - T2 * log(T2/T1));
81 m_cp0_R_int[i] = cpi;
82 m_h0_R_int[i+1] = m_h0_R_int[i] + cpi * deltaT;
83 m_s0_R_int[i+1] = s1 + cpi * log(T2/T1);
84 m_cp0_R_int[i+1] = cpi;
85 }
86
87 // Starting from the interval with T298, we go down
88 if (iT298 != 0) {
89 m_h0_R_int[iT298] = m_H298;
90 m_s0_R_int[iT298] = - (m_mu0_R_int[iT298] - m_h0_R_int[iT298]) / m_t0_int[iT298];
91 for (size_t i = iT298 - 1; i != npos; i--) {
92 double T1 = m_t0_int[i];
93 double T2 = m_t0_int[i+1];
94 double s2 = m_s0_R_int[i+1];
95 double deltaMu = m_mu0_R_int[i+1] - m_mu0_R_int[i];
96 double deltaT = T2 - T1;
97 double cpi = (deltaMu - T1 * s2 + T2 * s2) / (deltaT - T1 * log(T2/T1));
98 m_cp0_R_int[i] = cpi;
99 m_h0_R_int[i] = m_h0_R_int[i+1] - cpi * deltaT;
100 m_s0_R_int[i] = s2 - cpi * log(T2/T1);
101 if (i == (m_numIntervals-1)) {
102 m_cp0_R_int[i+1] = cpi;
103 }
104 }
105 }
106}
107
108void Mu0Poly::updateProperties(const doublereal* tt, doublereal* cp_R,
109 doublereal* h_RT, doublereal* s_R) const
110{
111 size_t j = m_numIntervals;
112 double T = *tt;
113 for (size_t i = 0; i < m_numIntervals; i++) {
114 double T2 = m_t0_int[i+1];
115 if (T <=T2) {
116 j = i;
117 break;
118 }
119 }
120 double T1 = m_t0_int[j];
121 double cp_Rj = m_cp0_R_int[j];
122 *cp_R = cp_Rj;
123 *h_RT = (m_h0_R_int[j] + (T - T1) * cp_Rj)/T;
124 *s_R = m_s0_R_int[j] + cp_Rj * (log(T/T1));
125}
126
127void Mu0Poly::updatePropertiesTemp(const doublereal T,
128 doublereal* cp_R,
129 doublereal* h_RT,
130 doublereal* s_R) const
131{
132 updateProperties(&T, cp_R, h_RT, s_R);
133}
134
135size_t Mu0Poly::nCoeffs() const
136{
137 return 2*m_numIntervals + 4;
138}
139
140void Mu0Poly::reportParameters(size_t& n, int& type,
141 doublereal& tlow, doublereal& thigh,
142 doublereal& pref,
143 doublereal* const coeffs) const
144{
145 n = 0;
146 type = MU0_INTERP;
147 tlow = m_lowT;
148 thigh = m_highT;
149 pref = m_Pref;
150 coeffs[0] = int(m_numIntervals)+1;
151 coeffs[1] = m_H298 * GasConstant;
152 int j = 2;
153 for (size_t i = 0; i < m_numIntervals+1; i++) {
154 coeffs[j] = m_t0_int[i];
155 coeffs[j+1] = m_mu0_R_int[i] * GasConstant;
156 j += 2;
157 }
158}
159
161{
163 thermo["model"] = "piecewise-Gibbs";
164 thermo["h0"].setQuantity(m_H298 * GasConstant, "J/kmol");
165 AnyMap data;
166 bool dimensionless = m_input.getBool("dimensionless", false);
167 if (dimensionless) {
168 thermo["dimensionless"] = true;
169 }
170 for (size_t i = 0; i < m_numIntervals+1; i++) {
171 if (dimensionless) {
172 data[fmt::format("{}", m_t0_int[i])] = m_mu0_R_int[i] / m_t0_int[i];
173 } else {
174 data[fmt::format("{}", m_t0_int[i])].setQuantity(
175 m_mu0_R_int[i] * GasConstant, "J/kmol");
176 }
177 }
178 thermo["data"] = std::move(data);
179}
180
182{
183 bool dimensionlessMu0Values = false;
184
185 doublereal h298 = 0.0;
186 if (Mu0Node.hasChild("H298")) {
187 h298 = getFloat(Mu0Node, "H298", "actEnergy");
188 }
189
190 size_t numPoints = 1;
191 if (Mu0Node.hasChild("numPoints")) {
192 numPoints = getInteger(Mu0Node, "numPoints");
193 }
194
195 vector_fp cValues(numPoints);
196 const XML_Node* valNode_ptr = getByTitle(Mu0Node, "Mu0Values");
197 if (!valNode_ptr) {
198 throw CanteraError("newMu0ThermoFromXML", "missing Mu0Values");
199 }
200 getFloatArray(*valNode_ptr, cValues, true, "actEnergy");
201
202 // Check to see whether the Mu0's were input in a dimensionless form. If
203 // they were, then the assumed temperature needs to be adjusted from the
204 // assumed T = 273.15
205 if (valNode_ptr->attrib("units") == "Dimensionless") {
206 dimensionlessMu0Values = true;
207 }
208 if (cValues.size() != numPoints) {
209 throw CanteraError("newMu0ThermoFromXML", "numPoints inconsistent");
210 }
211
212 vector_fp cTemperatures(numPoints);
213 const XML_Node* tempNode_ptr = getByTitle(Mu0Node, "Mu0Temperatures");
214 if (!tempNode_ptr) {
215 throw CanteraError("newMu0ThermoFromXML", "missing Mu0Temperatures");
216 }
217 getFloatArray(*tempNode_ptr, cTemperatures, false);
218 if (cTemperatures.size() != numPoints) {
219 throw CanteraError("newMu0ThermoFromXML", "numPoints inconsistent");
220 }
221
222 // Fix up dimensionless Mu0 values if input
223 if (dimensionlessMu0Values) {
224 for (size_t i = 0; i < numPoints; i++) {
225 cValues[i] *= cTemperatures[i] / 273.15;
226 }
227 }
228
229 vector_fp c(2 + 2 * numPoints);
230 c[0] = static_cast<double>(numPoints);
231 c[1] = h298;
232 for (size_t i = 0; i < numPoints; i++) {
233 c[2+i*2] = cTemperatures[i];
234 c[2+i*2+1] = cValues[i];
235 }
236
237 return new Mu0Poly(fpValue(Mu0Node["Tmin"]), fpValue(Mu0Node["Tmax"]),
238 fpValue(Mu0Node["Pref"]), &c[0]);
239}
240
241}
Header for a single-species standard state object derived from SpeciesThermoInterpType based on a pie...
A map of string keys to values whose type can vary at runtime.
Definition: AnyMap.h:399
bool getBool(const std::string &key, bool default_) const
If key exists, return it as a bool, otherwise return default_.
Definition: AnyMap.cpp:1487
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:61
The Mu0Poly class implements an interpolation of the Gibbs free energy based on a piecewise constant ...
Definition: Mu0Poly.h:75
doublereal m_H298
Value of the enthalpy at T = 298.15.
Definition: Mu0Poly.h:148
vector_fp m_mu0_R_int
Mu0's are primary input data.
Definition: Mu0Poly.h:155
virtual void getParameters(AnyMap &thermo) const
Store the parameters of the species thermo object such that an identical species thermo object could ...
Definition: Mu0Poly.cpp:160
vector_fp m_cp0_R_int
Heat capacity at the points.
Definition: Mu0Poly.h:164
void setParameters(double h0, const std::map< double, double > &T_mu)
Set parameters for .
Definition: Mu0Poly.cpp:41
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:127
virtual size_t nCoeffs() const
This utility function returns the number of coefficients for a given type of species parameterization...
Definition: Mu0Poly.cpp:135
virtual void reportParameters(size_t &n, int &type, doublereal &tlow, doublereal &thigh, doublereal &pref, doublereal *const coeffs) const
This utility function returns the type of parameterization and all of the parameters for the species.
Definition: Mu0Poly.cpp:140
vector_fp m_s0_R_int
Entropy at the points.
Definition: Mu0Poly.h:161
size_t m_numIntervals
Number of intervals in the interpolating linear approximation.
Definition: Mu0Poly.h:144
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:108
vector_fp m_t0_int
Points at which the standard state chemical potential are given.
Definition: Mu0Poly.h:151
vector_fp m_h0_R_int
Dimensionless Enthalpies at the temperature points.
Definition: Mu0Poly.h:158
Abstract Base class for the thermodynamic manager for an individual species' reference state.
virtual void getParameters(AnyMap &thermo) const
Store the parameters of the species thermo object such that an identical species thermo object could ...
doublereal m_lowT
lowest valid temperature
doublereal m_highT
Highest valid temperature.
doublereal m_Pref
Reference state pressure.
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:103
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:493
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:529
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data.
Mu0Poly * newMu0ThermoFromXML(const XML_Node &Mu0Node)
Install a Mu0 polynomial thermodynamic reference state.
Definition: Mu0Poly.cpp:181
Namespace for the Cantera kernel.
Definition: AnyMap.h:29
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:192
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:124
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:166
doublereal fpValue(const std::string &val)
Translate a string into one doublereal value.
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:184
const double GasConstant
Universal Gas Constant [J/kmol/K].
Definition: ct_defs.h:113
int getInteger(const XML_Node &parent, const std::string &name)
Get an integer value from a child element.
Definition: ctml.cpp:236
size_t getFloatArray(const XML_Node &node, vector_fp &v, const bool convert=true, const std::string &unitsString="", const std::string &nodeName="floatArray")
This function reads the current node or a child node of the current node with the default name,...
Definition: ctml.cpp:258
#define MU0_INTERP
piecewise interpolation of mu0.
Contains declarations for string manipulation functions within Cantera.