31 double thigh,
double pref,
const double* coeffs)
35 return new NasaPoly1(tlow, thigh, pref, coeffs);
42 return new Mu0Poly(tlow, thigh, pref, coeffs);
46 return new NasaPoly2(tlow, thigh, pref, coeffs);
51 "Unknown species thermo type: {}.", type);
56 double tlow,
double thigh,
double pref,
const double* coeffs)
60 if (type ==
"nasa2" || type ==
"nasa") {
62 }
else if (type ==
"const_cp" || type ==
"simple") {
64 }
else if (type ==
"shomate" || type ==
"shomate1") {
66 }
else if (type ==
"shomate2") {
68 }
else if (type ==
"nasa1") {
70 }
else if (type ==
"nasa9") {
72 }
else if (type ==
"nasa9multi") {
74 }
else if (type ==
"mu0") {
78 "Unknown species thermo type: '" + stype +
"'.");
94 bool dualRange = (nodes.size() > 1);
95 double tmin0 =
fpValue(f0[
"Tmin"]);
96 double tmax0 =
fpValue(f0[
"Tmax"]);
107 double tmin1 = tmax0;
108 double tmax1 = tmin1 + 0.0001;
110 tmin1 =
fpValue(nodes[1]->attrib(
"Tmin"));
111 tmax1 =
fpValue(nodes[1]->attrib(
"Tmax"));
115 doublereal tmin, tmid, tmax;
116 if (fabs(tmax0 - tmin1) < 0.01) {
128 }
else if (fabs(tmax1 - tmin0) < 0.01) {
137 "non-continuous temperature ranges.");
142 copy(c1.begin(), c1.begin()+7, c.begin() + 1);
143 copy(c0.begin(), c0.begin()+7, c.begin() + 8);
147 void setupSpeciesThermo(SpeciesThermoInterpType& thermo,
150 double Pref = node.convert(
"reference-pressure",
"Pa",
OneAtm);
151 thermo.setRefPressure(Pref);
154 void setupNasaPoly(NasaPoly2& thermo,
const AnyMap& node)
156 setupSpeciesThermo(thermo, node);
157 vector_fp Tranges = node.convertVector(
"temperature-ranges",
"K", 2, 3);
158 const auto& data = node[
"data"].asVector<
vector_fp>(Tranges.size()-1);
159 for (
const auto& poly : data) {
160 if (poly.size() != 7) {
161 throw CanteraError(
"setupNasaPoly",
"Wrong number of coefficients "
162 "for NASA polynomial. Expected 7, but got {}", poly.size());
165 thermo.setMinTemp(Tranges.front());
166 thermo.setMaxTemp(Tranges.back());
167 if (Tranges.size() == 3) {
168 thermo.setParameters(Tranges[1], data[0], data[1]);
170 thermo.setParameters(Tranges[1], data[0], data[0]);
184 vector<XML_Node*>& nodes)
186 bool dualRange =
false;
187 if (nodes.size() == 2) {
190 double tmin0 =
fpValue(nodes[0]->attrib(
"Tmin"));
191 double tmax0 =
fpValue(nodes[0]->attrib(
"Tmax"));
194 if (nodes[0]->hasAttrib(
"P0")) {
195 p0 =
fpValue(nodes[0]->attrib(
"P0"));
197 if (nodes[0]->hasAttrib(
"Pref")) {
198 p0 =
fpValue(nodes[0]->attrib(
"Pref"));
202 double tmin1 = tmax0;
203 double tmax1 = tmin1 + 0.0001;
205 tmin1 =
fpValue(nodes[1]->attrib(
"Tmin"));
206 tmax1 =
fpValue(nodes[1]->attrib(
"Tmax"));
210 doublereal tmin, tmid, tmax;
211 if (fabs(tmax0 - tmin1) < 0.01) {
222 "Shomate thermo requires 7 coefficients in float array.");
225 copy(c0.begin(), c0.begin()+7, c1.begin());
227 }
else if (fabs(tmax1 - tmin0) < 0.01) {
235 "non-continuous temperature ranges.");
237 if(c0.size() != 7 || c1.size() != 7)
240 "Shomate thermo requires 7 coefficients in float array.");
244 copy(c0.begin(), c0.begin()+7, c.begin() + 1);
245 copy(c1.begin(), c1.begin()+7, c.begin() + 8);
250 void setupShomatePoly(ShomatePoly2& thermo,
const AnyMap& node)
252 setupSpeciesThermo(thermo, node);
253 vector_fp Tranges = node.convertVector(
"temperature-ranges",
"K", 2, 3);
254 const auto& data = node[
"data"].asVector<
vector_fp>(Tranges.size()-1);
255 for (
const auto& poly : data) {
256 if (poly.size() != 7) {
257 throw CanteraError(
"setupShomatePoly",
"Wrong number of coefficients "
258 "for Shomate polynomial. Expected 7, but got {}", poly.size());
261 thermo.setMinTemp(Tranges.front());
262 thermo.setMaxTemp(Tranges.back());
263 if (Tranges.size() == 3) {
264 thermo.setParameters(Tranges[1], data[0], data[1]);
266 thermo.setParameters(Tranges[1], data[0], data[0]);
280 double tmin =
fpValue(f[
"Tmin"]);
281 double tmax =
fpValue(f[
"Tmax"]);
295 void setupConstCp(ConstCpPoly& thermo,
const AnyMap& node)
297 setupSpeciesThermo(thermo, node);
298 if (node.hasKey(
"T-min")) {
299 thermo.setMinTemp(node.convert(
"T-min",
"K"));
301 if (node.hasKey(
"T-max")) {
302 thermo.setMaxTemp(node.convert(
"T-max",
"K"));
304 double T0 = node.convert(
"T0",
"K", 298.15);
305 double h0 = node.convert(
"h0",
"J/kmol", 0.0);
306 double s0 = node.convert(
"s0",
"J/kmol/K", 0.0);
307 double cp0 = node.convert(
"cp0",
"J/kmol/K", 0.0);
308 thermo.setParameters(T0, h0, s0, cp0);
319 const std::vector<XML_Node*>& tp)
323 std::vector<Nasa9Poly1*> regionPtrs;
326 for (
size_t i = 0; i < tp.size(); i++) {
328 if (fptr.
name() ==
"NASA9" && fptr.
hasChild(
"floatArray")) {
329 double tmin =
fpValue(fptr[
"Tmin"]);
330 double tmax =
fpValue(fptr[
"Tmax"]);
339 if (cPoly.size() != 9) {
341 "Expected 9 coeff polynomial");
343 regionPtrs.push_back(
new Nasa9Poly1(tmin, tmax, pref, &cPoly[0]));
348 throw CanteraError(
"newNasa9ThermoFromXML",
"zero regions found");
349 }
else if (nRegions == 1) {
350 return regionPtrs[0];
357 void setupNasa9Poly(Nasa9PolyMultiTempRegion& thermo,
const AnyMap& node)
359 setupSpeciesThermo(thermo, node);
360 vector_fp Tranges = node.convertVector(
"temperature-ranges",
"K", 2, 999);
361 const auto& data = node[
"data"].asVector<
vector_fp>(Tranges.size()-1);
362 map<double, vector_fp> regions;
363 for (
size_t i = 0; i < data.size(); i++) {
364 if (data[i].size() != 9) {
365 throw CanteraError(
"setupNasa9Poly",
"Wrong number of coefficients "
366 "for NASA9 polynomial. Expected 9, but got {}", data[i].size());
368 regions[Tranges[i]] = data[i];
370 thermo.setMinTemp(Tranges.front());
371 thermo.setMaxTemp(Tranges.back());
372 thermo.setParameters(regions);
376 void setupMu0(Mu0Poly& thermo,
const AnyMap& node)
378 setupSpeciesThermo(thermo, node);
379 if (node.hasKey(
"T-min")) {
380 thermo.setMinTemp(node.convert(
"T-min",
"K"));
382 if (node.hasKey(
"T-max")) {
383 thermo.setMaxTemp(node.convert(
"T-max",
"K"));
385 bool dimensionless = node.getBool(
"dimensionless",
false);
386 double h0 = node.convert(
"h0",
"J/kmol", 0.0);
387 map<double, double> T_mu;
388 for (
const auto& item : node[
"data"]) {
389 double T = node.units().convert(
fpValueCheck(item.first),
"K");
391 T_mu[T] = item.second.asDouble() *
GasConstant * T;
393 T_mu[T] = node.units().convert(item.second,
"J/kmol");
396 thermo.setParameters(h0, T_mu);
402 if (model ==
"hkft" || model ==
"ionfromneutral") {
413 const std::vector<XML_Node*>& tpWC = thermo.
children();
414 std::vector<XML_Node*> tp;
415 for (
size_t i = 0; i < tpWC.size(); i++) {
416 if (!tpWC[i]->isComment()) {
417 tp.push_back(tpWC[i]);
421 std::string thermoType =
toLowerCopy(tp[0]->name());
423 for (
size_t i = 1; i < tp.size(); i++) {
426 "Encountered unsupported mixed species thermo "
427 "parameterizations, '{}' and '{}'", tp[i]->name(), thermoType);
430 if ((tp.size() > 2 && thermoType !=
"nasa9") ||
431 (tp.size() > 1 && (thermoType ==
"const_cp" ||
432 thermoType ==
"mu0"))) {
434 "Too many regions in thermo parameterization.");
437 if (thermoType ==
"shomate") {
439 }
else if (thermoType ==
"const_cp") {
441 }
else if (thermoType ==
"nasa") {
443 }
else if (thermoType ==
"mu0") {
445 }
else if (thermoType ==
"nasa9") {
449 "Unknown species thermo model '" + thermoType +
"'.");
456 std::string model = node[
"model"].asString();
457 if (model ==
"NASA7") {
458 unique_ptr<NasaPoly2> thermo(
new NasaPoly2());
459 setupNasaPoly(*thermo, node);
460 return unique_ptr<SpeciesThermoInterpType>(move(thermo));
461 }
else if (model ==
"Shomate") {
463 setupShomatePoly(*thermo, node);
464 return unique_ptr<SpeciesThermoInterpType>(move(thermo));
465 }
else if (model ==
"NASA9") {
467 setupNasa9Poly(*thermo, node);
468 return unique_ptr<SpeciesThermoInterpType>(move(thermo));
469 }
else if (model ==
"constant-cp") {
471 setupConstCp(*thermo, node);
472 return unique_ptr<SpeciesThermoInterpType>(move(thermo));
473 }
else if (model ==
"piecewise-Gibbs") {
474 unique_ptr<Mu0Poly> thermo(
new Mu0Poly());
475 setupMu0(*thermo, node);
476 return unique_ptr<SpeciesThermoInterpType>(move(thermo));
479 "Unknown thermo model '{}'", model);