34 if (!elementDefs.empty()) {
35 root[
"elements"] = std::move(elementDefs);
37 vector<AnyMap> speciesDefs;
40 speciesDefs.emplace_back(
species(
name)->parameters(
this));
42 root[
"species"] = std::move(speciesDefs);
52 explicit PhaseEquilGuard(
ThermoPhase& phase) : m_phase(phase)
54 m_phase.beginEquilibrate();
59 m_phase.endEquilibrate();
66void checkTemperatureLimits(
const string& method,
const ThermoPhase& phase)
68 if (phase.temperature() > phase.maxTemp() + 1.0
69 || phase.temperature() < phase.minTemp() - 1.0) {
70 if (phase.temperatureLimitsEnforced()) {
71 throw CanteraError(method,
72 "Temperature ({} K) outside valid range of {} K to {} K",
73 phase.temperature(), phase.minTemp(), phase.maxTemp());
76 "Temperature ({} K) outside valid range of {} K to {} K",
77 phase.temperature(), phase.minTemp(), phase.maxTemp());
87 for (
size_t k = 0; k <
nSpecies(); k++) {
107 return Units(1.0, 0, -
static_cast<double>(
nDim()), 0, 0, 0, 1);
118 for (
size_t k = 0; k <
nSpecies(); k++) {
126 for (
size_t k = 0; k <
m_kk; k++) {
127 lnac[k] = std::log(lnac[k]);
135 for (
size_t k = 0; k <
m_kk; k++) {
142 vector<double> vbar(
m_kk);
146 for (
size_t k = 0; k <
m_kk; k++) {
147 ubar[k] -= pi_t * vbar[k];
194 }
catch (std::exception&) {
206 }
catch (std::exception&) {
219 }
catch (std::exception&) {
227 AnyMap state = input_state;
230 if (state.
hasKey(
"mass-fractions")) {
231 state[
"Y"] = state[
"mass-fractions"];
232 state.
erase(
"mass-fractions");
234 if (state.
hasKey(
"mole-fractions")) {
235 state[
"X"] = state[
"mole-fractions"];
236 state.
erase(
"mole-fractions");
238 if (state.
hasKey(
"temperature")) {
239 state[
"T"] = state[
"temperature"];
241 if (state.
hasKey(
"pressure")) {
242 state[
"P"] = state[
"pressure"];
244 if (state.
hasKey(
"enthalpy")) {
245 state[
"H"] = state[
"enthalpy"];
247 if (state.
hasKey(
"int-energy")) {
248 state[
"U"] = state[
"int-energy"];
250 if (state.
hasKey(
"internal-energy")) {
251 state[
"U"] = state[
"internal-energy"];
253 if (state.
hasKey(
"specific-volume")) {
254 state[
"V"] = state[
"specific-volume"];
256 if (state.
hasKey(
"entropy")) {
257 state[
"S"] = state[
"entropy"];
259 if (state.
hasKey(
"density")) {
260 state[
"D"] = state[
"density"];
262 if (state.
hasKey(
"vapor-fraction")) {
263 state[
"Q"] = state[
"vapor-fraction"];
268 if (state[
"X"].is<string>()) {
274 }
else if (state.
hasKey(
"Y")) {
275 if (state[
"Y"].is<string>()) {
283 if (state.
size() == 0) {
286 double T = state.
convert(
"T",
"K");
287 double P = state.
convert(
"P",
"Pa");
323 }
else if (state.
hasKey(
"T")) {
325 }
else if (state.
hasKey(
"P")) {
329 "'state' did not specify a recognized set of properties.\n"
330 "Keys provided were: {}", input_state.
keys_str());
343 double rtol,
bool doUV)
353 "Input specific volume is too small or negative. v = {}", v);
359 "Input pressure is too small or negative. p = {}", p);
377 }
else if (Tnew < Tmin) {
391 bool ignoreBounds =
false;
394 bool unstablePhase =
false;
397 double Tunstable = -1.0;
398 bool unstablePhaseNew =
false;
401 for (
int n = 0; n < 500; n++) {
406 unstablePhase =
true;
410 dt =
clip((Htarget - Hold)/cpd, -100.0, 100.0);
417 if ((dt > 0.0 && unstablePhase) || (dt <= 0.0 && !unstablePhase)) {
418 if (Hbot < Htarget && Tnew < (0.75 * Tbot + 0.25 * Told)) {
419 dt = 0.75 * (Tbot - Told);
422 }
else if (Htop > Htarget && Tnew > (0.75 * Ttop + 0.25 * Told)) {
423 dt = 0.75 * (Ttop - Told);
428 if (Tnew > Tmax && !ignoreBounds) {
431 if (Hmax >= Htarget) {
432 if (Htop < Htarget) {
441 "Target {} = {} cannot be reached within the temperature "
442 "bounds of {} K to {} K.",
443 doUV ?
"internal energy" :
"enthalpy", Htarget, Tmin, Tmax);
449 if (Tnew < Tmin && !ignoreBounds) {
452 if (Hmin <= Htarget) {
453 if (Hbot > Htarget) {
462 "Target {} = {} cannot be reached within the temperature "
463 "bounds of {} K to {} K.",
464 doUV ?
"internal energy" :
"enthalpy", Htarget, Tmin, Tmax);
474 for (
int its = 0; its < 10; its++) {
476 if (Tnew < Told / 3.0) {
478 dt = -2.0 * Told / 3.0;
489 unstablePhaseNew =
true;
492 unstablePhaseNew =
false;
495 if (unstablePhase ==
false && unstablePhaseNew ==
true) {
500 if (Hnew == Htarget) {
501 checkTemperatureLimits(
502 doUV ?
"ThermoPhase::setState_UV" :
"ThermoPhase::setState_HP",
505 }
else if (Hnew > Htarget && (Htop < Htarget || Hnew < Htop)) {
508 }
else if (Hnew < Htarget && (Hbot > Htarget || Hnew > Hbot)) {
513 double Herr = Htarget - Hnew;
514 double acpd = std::max(fabs(cpd), 1.0E-5);
515 double denom = std::max(fabs(Htarget), acpd * Tnew);
516 double HConvErr = fabs((Herr)/denom);
517 if (HConvErr < rtol || fabs(dt/Tnew) < rtol) {
518 checkTemperatureLimits(
519 doUV ?
"ThermoPhase::setState_UV" :
"ThermoPhase::setState_HP",
528 string ErrString =
"No convergence in 500 iterations\n";
530 ErrString += fmt::format(
531 "\tTarget Internal Energy = {}\n"
532 "\tCurrent Specific Volume = {}\n"
533 "\tStarting Temperature = {}\n"
534 "\tCurrent Temperature = {}\n"
535 "\tCurrent Internal Energy = {}\n"
536 "\tCurrent Delta T = {}\n",
537 Htarget, v, Tinit, Tnew, Hnew, dt);
539 ErrString += fmt::format(
540 "\tTarget Enthalpy = {}\n"
541 "\tCurrent Pressure = {}\n"
542 "\tStarting Temperature = {}\n"
543 "\tCurrent Temperature = {}\n"
544 "\tCurrent Enthalpy = {}\n"
545 "\tCurrent Delta T = {}\n",
546 Htarget, p, Tinit, Tnew, Hnew, dt);
549 ErrString += fmt::format(
550 "\t - The phase became unstable (Cp < 0) T_unstable_last = {}\n",
554 throw CanteraError(
"ThermoPhase::setState_HPorUV (UV)", ErrString);
556 throw CanteraError(
"ThermoPhase::setState_HPorUV (HP)", ErrString);
566 }
catch (std::exception&) {
579 }
catch (std::exception&) {
586 double rtol,
bool doSV)
594 "Input specific volume is too small or negative. v = {}", v);
600 "Input pressure is too small or negative. p = {}", p);
618 }
else if (Tnew < Tmin) {
632 bool ignoreBounds =
false;
635 bool unstablePhase =
false;
636 double Tunstable = -1.0;
637 bool unstablePhaseNew =
false;
640 for (
int n = 0; n < 500; n++) {
645 unstablePhase =
true;
649 dt =
clip((Starget - Sold)*Told/cpd, -100.0, 100.0);
653 if ((dt > 0.0 && unstablePhase) || (dt <= 0.0 && !unstablePhase)) {
654 if (Sbot < Starget && Tnew < Tbot) {
655 dt = 0.75 * (Tbot - Told);
658 }
else if (Stop > Starget && Tnew > Ttop) {
659 dt = 0.75 * (Ttop - Told);
664 if (Tnew > Tmax && !ignoreBounds) {
667 if (Smax >= Starget) {
668 if (Stop < Starget) {
677 "Target entropy = {} cannot be reached within the temperature "
678 "bounds of {} K to {} K.", Starget, Tmin, Tmax);
683 }
else if (Tnew < Tmin && !ignoreBounds) {
686 if (Smin <= Starget) {
687 if (Sbot > Starget) {
696 "Target entropy = {} cannot be reached within the temperature "
697 "bounds of {} K to {} K.", Starget, Tmin, Tmax);
707 for (
int its = 0; its < 10; its++) {
713 unstablePhaseNew =
true;
716 unstablePhaseNew =
false;
719 if (unstablePhase ==
false && unstablePhaseNew ==
true) {
724 if (Snew == Starget) {
725 checkTemperatureLimits(
726 doSV ?
"ThermoPhase::setState_SV" :
"ThermoPhase::setState_SP",
729 }
else if (Snew > Starget && (Stop < Starget || Snew < Stop)) {
732 }
else if (Snew < Starget && (Sbot > Starget || Snew > Sbot)) {
737 double Serr = Starget - Snew;
738 double acpd = std::max(fabs(cpd), 1.0E-5);
739 double denom = std::max(fabs(Starget), acpd * Tnew);
740 double SConvErr = fabs((Serr * Tnew)/denom);
741 if (SConvErr < rtol || fabs(dt/Tnew) < rtol) {
742 checkTemperatureLimits(
743 doSV ?
"ThermoPhase::setState_SV" :
"ThermoPhase::setState_SP",
752 string ErrString =
"No convergence in 500 iterations\n";
754 ErrString += fmt::format(
755 "\tTarget Entropy = {}\n"
756 "\tCurrent Specific Volume = {}\n"
757 "\tStarting Temperature = {}\n"
758 "\tCurrent Temperature = {}\n"
759 "\tCurrent Entropy = {}\n"
760 "\tCurrent Delta T = {}\n",
761 Starget, v, Tinit, Tnew, Snew, dt);
763 ErrString += fmt::format(
764 "\tTarget Entropy = {}\n"
765 "\tCurrent Pressure = {}\n"
766 "\tStarting Temperature = {}\n"
767 "\tCurrent Temperature = {}\n"
768 "\tCurrent Entropy = {}\n"
769 "\tCurrent Delta T = {}\n",
770 Starget, p, Tinit, Tnew, Snew, dt);
773 ErrString += fmt::format(
"\t - The phase became unstable (Cp < 0) T_unstable_last = {}\n",
777 throw CanteraError(
"ThermoPhase::setState_SPorSV (SV)", ErrString);
779 throw CanteraError(
"ThermoPhase::setState_SPorSV (SP)", ErrString);
793 for (
size_t k = 0; k !=
m_kk; ++k) {
797 o2req += x *
nAtoms(k, iC);
800 o2req += x *
nAtoms(k, iS);
803 o2req += x * 0.25 *
nAtoms(k, iH);
808 "No composition specified");
819 for (
size_t k = 0; k !=
m_kk; ++k) {
825 "No composition specified");
827 return 0.5 * o2pres / sum;
843 parseCompString(fuelComp.find(
":") != string::npos ? fuelComp : fuelComp+
":1.0"),
844 parseCompString(oxComp.find(
":") != string::npos ? oxComp : oxComp+
":1.0"),
849 span<const double> oxComp,
852 vector<double> fuel, ox;
853 if (basis == ThermoBasis::molar) {
865 if (o2_required_fuel < 0.0 || o2_required_ox > 0.0) {
867 "Fuel composition contains too much oxygen or "
868 "oxidizer contains not enough oxygen. "
869 "Fuel and oxidizer composition mixed up?");
872 if (o2_required_ox == 0.0) {
873 return std::numeric_limits<double>::infinity();
876 return o2_required_fuel / (-o2_required_ox);
884 "Equivalence ratio phi must be >= 0");
889 vector<double> fuel, ox;
890 if (basis == ThermoBasis::molar) {
900 double sum_f = std::accumulate(fuelComp.begin(), fuelComp.end(), 0.0);
901 double sum_o = std::accumulate(oxComp.begin(), oxComp.end(), 0.0);
903 vector<double> y(
m_kk);
904 for (
size_t k = 0; k !=
m_kk; ++k) {
905 y[k] = phi * fuelComp[k]/sum_f + AFR_st * oxComp[k]/sum_o;
916 parseCompString(fuelComp.find(
":") != string::npos ? fuelComp : fuelComp+
":1.0"),
917 parseCompString(oxComp.find(
":") != string::npos ? oxComp : oxComp+
":1.0"),
935 if (o2_present == 0.0) {
936 return std::numeric_limits<double>::infinity();
939 return o2_required / o2_present;
955 parseCompString(fuelComp.find(
":") != string::npos ? fuelComp : fuelComp+
":1.0"),
956 parseCompString(oxComp.find(
":") != string::npos ? oxComp : oxComp+
":1.0"),
961 span<const double> oxComp,
ThermoBasis basis)
const
970 return std::numeric_limits<double>::infinity();
973 vector<double> fuel, ox;
974 if (basis == ThermoBasis::molar) {
985 return std::max(Z / (1.0 - Z) * AFR_st, 0.0);
1000 parseCompString(fuelComp.find(
":") != string::npos ? fuelComp : fuelComp+
":1.0"),
1001 parseCompString(oxComp.find(
":") != string::npos ? oxComp : oxComp+
":1.0"),
1010 if (mixFrac < 0.0 || mixFrac > 1.0) {
1012 "Mixture fraction must be between 0 and 1");
1015 vector<double> fuel, ox;
1016 if (basis == ThermoBasis::molar) {
1025 double sum_yf = std::accumulate(fuelComp.begin(), fuelComp.end(), 0.0);
1026 double sum_yo = std::accumulate(oxComp.begin(), oxComp.end(), 0.0);
1028 if (sum_yf == 0.0 || sum_yo == 0.0) {
1030 "No fuel and/or oxidizer composition specified");
1035 vector<double> y(
m_kk);
1037 for (
size_t k = 0; k !=
m_kk; ++k) {
1038 y[k] = mixFrac * fuelComp[k]/sum_yf + (1.0-mixFrac) * oxComp[k]/sum_yo;
1048 const string& element)
const
1059 parseCompString(fuelComp.find(
":") != string::npos ? fuelComp : fuelComp+
":1.0"),
1060 parseCompString(oxComp.find(
":") != string::npos ? oxComp : oxComp+
":1.0"),
1065 span<const double> oxComp,
1070 vector<double> fuel, ox;
1071 if (basis == ThermoBasis::molar) {
1080 if (element ==
"Bilger")
1087 if (o2_required_fuel < 0.0 || o2_required_ox > 0.0) {
1089 "Fuel composition contains too much oxygen or "
1090 "oxidizer contains not enough oxygen. "
1091 "Fuel and oxidizer composition mixed up?");
1094 double denominator = o2_required_fuel - o2_required_ox;
1096 if (denominator == 0.0) {
1098 "Fuel and oxidizer have the same composition");
1101 double Z = (o2_required_mix - o2_required_ox) / denominator;
1103 return std::min(std::max(Z, 0.0), 1.0);
1106 double sum_yf = std::accumulate(fuelComp.begin(), fuelComp.end(), 0.0);
1107 double sum_yo = std::accumulate(oxComp.begin(), oxComp.end(), 0.0);
1109 if (sum_yf == 0.0 || sum_yo == 0.0) {
1111 "No fuel and/or oxidizer composition specified");
1114 auto elementalFraction = [
this](
size_t m, span<const double> y) {
1116 for (
size_t k = 0; k !=
m_kk; ++k) {
1123 double Z_m_fuel = elementalFraction(m, fuelComp)/sum_yf;
1124 double Z_m_ox = elementalFraction(m, oxComp)/sum_yo;
1127 if (Z_m_fuel == Z_m_ox) {
1129 "Fuel and oxidizer have the same composition for element {}",
1132 double Z = (Z_m_mix - Z_m_ox) / (Z_m_fuel - Z_m_ox);
1133 return std::min(std::max(Z, 0.0), 1.0);
1150 if (inputFile.empty()) {
1154 size_t dot = inputFile.find_last_of(
".");
1157 extension = inputFile.substr(
dot+1);
1159 if (extension ==
"xml" || extension ==
"cti") {
1161 "The CTI and XML formats are no longer supported.");
1165 auto& phase =
root[
"phases"].getMapWhere(
"name",
id);
1174 "Missing species thermo data");
1186 "Temperature ({}), pressure ({}) and vapor fraction ({}) "
1187 "are inconsistent, above the critical temperature.",
1193 if (std::abs(Psat / P - 1) < 1e-6) {
1195 }
else if ((Q == 0 && P >= Psat) || (Q == 1 && P <= Psat)) {
1199 "Temperature ({}), pressure ({}) and vapor fraction ({}) "
1200 "are inconsistent.\nPsat at this T: {}\n"
1201 "Consider specifying the state using two fully independent "
1202 "properties (for example, temperature and density)",
1209 if (!spec->thermo) {
1211 "Species {} has no thermo data", spec->name);
1215 spec->thermo->validate(spec->name);
1223 if (!spec->thermo) {
1225 "Species {} has no thermo data", spec->name);
1230 "New species '{}' does not match existing species '{}' at index {}",
1233 spec->thermo->validate(spec->name);
1254 phaseNode[
"name"] =
name();
1257 for (
size_t i = 0; i <
nElements(); i++) {
1265 if (stateVars.count(
"T")) {
1269 if (stateVars.count(
"D")) {
1270 state[
"density"].setQuantity(
density(),
"kg/m^3");
1271 }
else if (stateVars.count(
"P")) {
1272 state[
"P"].setQuantity(
pressure(),
"Pa");
1275 if (stateVars.count(
"Y")) {
1276 map<string, double> Y;
1277 for (
size_t k = 0; k <
m_kk; k++) {
1285 }
else if (stateVars.count(
"X")) {
1286 map<string, double> X;
1287 for (
size_t k = 0; k <
m_kk; k++) {
1297 phaseNode[
"state"] = std::move(state);
1301 phaseNode[
"__type__"] =
"Phase";
1321 double rtol,
int max_steps,
int max_iter,
1322 int estimate_equil,
int log_level)
1324 if (solver ==
"auto" || solver ==
"element_potential") {
1325 vector<double> initial_state(
stateSize());
1327 debuglog(
"Trying ChemEquil solver\n", log_level);
1329 PhaseEquilGuard guard(*
this);
1334 int ret = E.
equilibrate(*
this, XY.c_str(), log_level-1);
1337 "ChemEquil solver failed. Return code: {}", ret);
1339 debuglog(
"ChemEquil solver succeeded\n", log_level);
1341 }
catch (std::exception& err) {
1342 debuglog(
"ChemEquil solver failed.\n", log_level);
1345 if (solver ==
"auto") {
1352 if (solver ==
"auto" || solver ==
"vcs" || solver ==
"gibbs") {
1358 M.
equilibrate(XY, solver, rtol, max_steps, max_iter,
1359 estimate_equil, log_level);
1363 if (solver !=
"auto") {
1365 "Invalid solver specified: '{}'", solver);
1372 for (
size_t m = 0; m <
m_kk; m++) {
1373 for (
size_t k = 0; k <
m_kk; k++) {
1374 dlnActCoeffdlnN[ld * k + m] = 0.0;
1380void ThermoPhase::getdlnActCoeffdlnN_numderiv(
const size_t ld,
1381 span<double> dlnActCoeffdlnN)
1384 dlnActCoeffdlnN.size(), ld*
m_kk);
1385 double deltaMoles_j = 0.0;
1389 vector<double> ActCoeff_Base(
m_kk);
1391 vector<double> Xmol_Base(
m_kk);
1395 vector<double> ActCoeff(
m_kk);
1396 vector<double> Xmol(
m_kk);
1397 double v_totalMoles = 1.0;
1398 double TMoles_base = v_totalMoles;
1401 for (
size_t j = 0; j <
m_kk; j++) {
1407 double moles_j_base = v_totalMoles * Xmol_Base[j];
1408 deltaMoles_j = 1.0E-7 * moles_j_base + v_totalMoles * 1.0E-13 + 1.0E-150;
1412 v_totalMoles = TMoles_base + deltaMoles_j;
1413 for (
size_t k = 0; k <
m_kk; k++) {
1414 Xmol[k] = Xmol_Base[k] * TMoles_base / v_totalMoles;
1416 Xmol[j] = (moles_j_base + deltaMoles_j) / v_totalMoles;
1424 span<double> lnActCoeffCol = dlnActCoeffdlnN.subspan(ld * j,
m_kk);
1425 for (
size_t k = 0; k <
m_kk; k++) {
1426 lnActCoeffCol[k] = (2*moles_j_base + deltaMoles_j) *(ActCoeff[k] - ActCoeff_Base[k]) /
1427 ((ActCoeff[k] + ActCoeff_Base[k]) * deltaMoles_j);
1430 v_totalMoles = TMoles_base;
1439 if (
type() ==
"none") {
1441 "Not implemented for thermo model 'none'");
1444 fmt::memory_buffer b;
1446 int name_width = 18;
1448 string blank_leader = fmt::format(
"{:{}}",
"", name_width);
1450 string string_property = fmt::format(
"{{:>{}}} {{}}\n", name_width);
1452 string one_property = fmt::format(
"{{:>{}}} {{:<.5g}} {{}}\n", name_width);
1454 constexpr auto two_prop_header =
"{} {:^15} {:^15}\n";
1455 string kg_kmol_header = fmt::format(
1456 two_prop_header, blank_leader,
"1 kg",
"1 kmol"
1458 string Y_X_header = fmt::format(
1459 two_prop_header, blank_leader,
"mass frac. Y",
"mole frac. X"
1461 string two_prop_sep = fmt::format(
1462 "{} {:-^15} {:-^15}\n", blank_leader,
"",
""
1464 string two_property = fmt::format(
1465 "{{:>{}}} {{:15.5g}} {{:15.5g}} {{}}\n", name_width
1468 string three_prop_header = fmt::format(
1469 "{} {:^15} {:^15} {:^15}\n", blank_leader,
"mass frac. Y",
1470 "mole frac. X",
"chem. pot. / RT"
1472 string three_prop_sep = fmt::format(
1473 "{} {:-^15} {:-^15} {:-^15}\n", blank_leader,
"",
"",
""
1475 string three_property = fmt::format(
1476 "{{:>{}}} {{:15.5g}} {{:15.5g}} {{:15.5g}}\n", name_width
1481 fmt_append(b,
"\n {}:\n",
name());
1483 fmt_append(b,
"\n");
1484 fmt_append(b, one_property,
"temperature",
temperature(),
"K");
1485 fmt_append(b, one_property,
"pressure",
pressure(),
"Pa");
1486 fmt_append(b, one_property,
"density",
density(),
"kg/m^3");
1487 fmt_append(b, one_property,
1492 fmt_append(b, one_property,
"potential", phi,
"V");
1495 fmt_append(b, string_property,
"phase of matter",
phaseOfMatter());
1498 fmt_append(b,
"\n");
1499 fmt_append(b, kg_kmol_header);
1500 fmt_append(b, two_prop_sep);
1501 fmt_append(b, two_property,
1503 fmt_append(b, two_property,
1505 fmt_append(b, two_property,
1507 fmt_append(b, two_property,
1509 fmt_append(b, two_property,
1512 fmt_append(b, two_property,
1515 fmt_append(b, string_property,
1516 "heat capacity c_v",
"<not implemented>");
1520 vector<double> x(
m_kk);
1521 vector<double> y(
m_kk);
1522 vector<double> mu(
m_kk);
1527 double xMinor = 0.0;
1528 double yMinor = 0.0;
1529 fmt_append(b,
"\n");
1531 fmt_append(b, three_prop_header);
1532 fmt_append(b, three_prop_sep);
1533 for (
size_t k = 0; k <
m_kk; k++) {
1534 if (abs(x[k]) >= threshold) {
1536 fmt_append(b, three_property,
1539 fmt_append(b, two_property,
speciesName(k), y[k], x[k],
"");
1548 fmt_append(b, Y_X_header);
1549 fmt_append(b, two_prop_sep);
1550 for (
size_t k = 0; k <
m_kk; k++) {
1551 if (abs(x[k]) >= threshold) {
1552 fmt_append(b, two_property,
speciesName(k), y[k], x[k],
"");
1561 string minor = fmt::format(
"[{:+5d} minor]", nMinor);
1562 fmt_append(b, two_property, minor, yMinor, xMinor,
"");
1565 return to_string(b) + err.
what();
1567 return to_string(b);
Headers for the MultiPhase object that is used to set up multiphase equilibrium problems (see Chemica...
Pure Virtual Base class for individual species reference state thermodynamic managers and text for th...
Declaration for class Cantera::Species.
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
Header file for class ThermoPhase, the base class for phases with thermodynamic properties,...
A map of string keys to values whose type can vary at runtime.
size_t size() const
Returns the number of elements in this map.
bool hasKey(const string &key) const
Returns true if the map contains an item named key.
void applyUnits()
Use the supplied UnitSystem to set the default units, and recursively process overrides from nodes na...
double convert(const string &key, const string &units) const
Convert the item stored by the given key to the units specified in units.
void setFlowStyle(bool flow=true)
Use "flow" style when outputting this AnyMap to YAML.
void erase(const string &key)
Erase the value held by key.
static AnyMap fromYamlFile(const string &name, const string &parent_name="")
Create an AnyMap from a YAML file.
void update(const AnyMap &other, bool keepExisting=true)
Add items from other to this AnyMap.
static bool addOrderingRules(const string &objectType, const vector< vector< string > > &specs)
Add global rules for setting the order of elements when outputting AnyMap objects to YAML.
string keys_str() const
Return a string listing the keys in this AnyMap, for use in error messages, for example.
Base class for exceptions thrown by Cantera classes.
const char * what() const override
Get a description of the error.
Class ChemEquil implements a chemical equilibrium solver for single-phase solutions.
int equilibrate(ThermoPhase &s, const char *XY, int loglevel=0)
Equilibrate a phase, holding the elemental composition fixed at the initial value found within the Th...
EquilOpt options
Options controlling how the calculation is carried out.
bool enforceTemperatureLimits
Enforce temperature validity limits during equilibrium solver iterations.
double relTolerance
Relative tolerance.
int maxIterations
Maximum number of iterations.
string canonicalize(const string &name)
Get the canonical name registered for a type.
A class for multiphase mixtures.
void init()
Process phases and build atomic composition array.
void addPhase(shared_ptr< ThermoPhase > p, double moles)
Add a phase to the mixture.
A species thermodynamic property manager for a phase.
bool ready(size_t nSpecies)
Check if data for all species (0 through nSpecies-1) has been installed.
virtual void install_STIT(size_t index, shared_ptr< SpeciesThermoInterpType > stit)
Install a new species thermodynamic property parameterization for one species.
virtual void modifySpecies(size_t index, shared_ptr< SpeciesThermoInterpType > spec)
Modify the species thermodynamic property parameterization for a species.
virtual void resetHf298(const size_t k)
Restore the original heat of formation of one or more species.
An error indicating that an unimplemented function has been called.
void getMoleFractions(span< double > x) const
Get the species mole fraction vector.
void getMassFractions(span< double > y) const
Get the species mass fractions.
double massFraction(size_t k) const
Return the mass fraction of a single species.
virtual bool addSpecies(shared_ptr< Species > spec)
Add a Species to this Phase.
void assertCompressible(const string &setter) const
Ensure that phase is compressible.
size_t nSpecies() const
Returns the number of species in the phase.
virtual map< string, size_t > nativeState() const
Return a map of properties defining the native state of a substance.
size_t m_kk
Number of species in the phase.
virtual void modifySpecies(size_t k, shared_ptr< Species > spec)
Modify the thermodynamic data associated with a species.
size_t nDim() const
Returns the number of spatial dimensions (1, 2, or 3)
span< const double > molecularWeights() const
Return a const reference to the internal vector of molecular weights.
void setState_TD(double t, double rho)
Set the internally stored temperature (K) and density (kg/m^3)
double temperature() const
Temperature (K).
virtual void setPressure(double p)
Set the internally stored pressure (Pa) at constant temperature and composition.
double meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
virtual void restorePartialState(span< const double > state)
Set the internal thermodynamic state of the phase, excluding composition.
span< const double > massFractions() const
Return a view of the mass fraction array.
void setMassFractionsByName(const Composition &yMap)
Set the species mass fractions by name.
string speciesName(size_t k) const
Name of the species with index k.
void moleFractionsToMassFractions(span< const double > X, span< double > Y) const
Converts a mixture composition from mass fractions to mole fractions.
virtual void setDensity(const double density_)
Set the internally stored density (kg/m^3) of the phase.
virtual size_t stateSize() const
Return size of vector defining internal state of the phase.
vector< double > getCompositionFromMap(const Composition &comp) const
Converts a Composition to a vector with entries for each species Species that are not specified are s...
void setMoleFractionsByName(const Composition &xMap)
Set the species mole fractions by name.
vector< AnyMap > elementDefinitions() const
Return explicit element definitions needed to reconstruct this phase.
double moleFraction(size_t k) const
Return the mole fraction of a single species.
const vector< string > & elementNames() const
Return a read-only reference to the vector of element names.
virtual double density() const
Density (kg/m^3).
double nAtoms(size_t k, size_t m) const
Number of atoms of element m in species k.
virtual void setTemperature(double temp)
Set the internally stored temperature of the phase (K).
size_t nElements() const
Number of elements.
virtual void setMoleFractions(span< const double > x)
Set the mole fractions to the specified values.
const vector< string > & speciesNames() const
Return a const reference to the vector of species names.
size_t elementIndex(const string &name, bool raise=true) const
Return the index of element named 'name'.
virtual void setMassFractions(span< const double > y)
Set the mass fractions to the specified values and normalize them.
double molecularWeight(size_t k) const
Molecular weight of species k.
shared_ptr< Species > species(const string &name) const
Return the Species object for the named species.
virtual void invalidateCache()
Invalidate any cached values which are normally updated only when a change in state is detected.
virtual void setMassFractions_NoNorm(span< const double > y)
Set the mass fractions to the specified values without normalizing.
virtual size_t partialStateSize() const
Get the size of the partial state vector of the phase.
virtual void savePartialState(span< double > state) const
Save the current thermodynamic state of the phase, excluding composition.
virtual void restoreState(span< const double > state)
Restore the state of the phase from a previously saved state vector.
virtual double pressure() const
Return the thermodynamic pressure (Pa).
string elementName(size_t m) const
Name of the element with index m.
double charge(size_t k) const
Dimensionless electrical charge of a single molecule of species k The charge is normalized by the the...
string name() const
Return the name of the phase.
virtual void saveState(span< double > state) const
Write to array 'state' the current internal state.
static ThermoFactory * factory()
Static function that creates a static instance of the factory.
Base class for a phase with thermodynamic properties.
int m_ssConvention
Contains the standard state convention.
virtual double critTemperature() const
Critical temperature (K).
virtual void setState_HP(double h, double p, double tol=1e-9)
Set the internally stored specific enthalpy (J/kg) and pressure (Pa) of the phase.
virtual void getPartialMolarVolumes(span< double > vbar) const
Return an array of partial molar volumes for the species in the mixture.
double electricPotential() const
Returns the electric potential of this phase (V).
virtual void setState_UV(double u, double v, double tol=1e-9)
Set the specific internal energy (J/kg) and specific volume (m^3/kg).
virtual double cp_mole() const
Molar heat capacity at constant pressure and composition [J/kmol/K].
double equivalenceRatio() const
Compute the equivalence ratio for the current mixture from available oxygen and required oxygen.
virtual void setParameters(const AnyMap &phaseNode, const AnyMap &rootNode=AnyMap())
Set equation of state parameters from an AnyMap phase description.
virtual void getParameters(AnyMap &phaseNode) const
Store the parameters of a ThermoPhase object such that an identical one could be reconstructed using ...
virtual double enthalpy_mole() const
Molar enthalpy. Units: J/kmol.
virtual void setState_TP(double t, double p)
Set the temperature (K) and pressure (Pa)
virtual double standardConcentration(size_t k=0) const
Return the standard concentration for the kth species.
virtual void setState_TV(double t, double v, double tol=1e-9)
Set the temperature (K) and specific volume (m^3/kg).
virtual double logStandardConc(size_t k=0) const
Natural logarithm of the standard concentration of the kth species.
virtual void setState_PV(double p, double v, double tol=1e-9)
Set the pressure (Pa) and specific volume (m^3/kg).
virtual void setState(const AnyMap &state)
Set the state using an AnyMap containing any combination of properties supported by the thermodynamic...
virtual double minTemp(size_t k=npos) const
Minimum temperature for which the thermodynamic data for the species or phase are valid.
void setState_SPorSV(double s, double p, double tol=1e-9, bool doSV=false)
Carry out work in SP and SV calculations.
double RT() const
Return the Gas Constant multiplied by the current temperature.
double o2Required(span< const double > y) const
Helper function for computing the amount of oxygen required for complete oxidation.
virtual double critPressure() const
Critical pressure (Pa).
double m_tlast
last value of the temperature processed by reference state
virtual void setState_ST(double s, double t, double tol=1e-9)
Set the specific entropy (J/kg/K) and temperature (K).
virtual void getActivities(span< double > a) const
Get the array of non-dimensional activities at the current solution temperature, pressure,...
virtual void getdlnActCoeffdlnN(const size_t ld, span< double > dlnActCoeffdlnN)
Get the array of derivatives of the log activity coefficients with respect to the log of the species ...
void setState_HPorUV(double h, double p, double tol=1e-9, bool doUV=false)
Carry out work in HP and UV calculations.
double gibbs_mass() const
Specific Gibbs function. Units: J/kg.
string type() const override
String indicating the thermodynamic model implemented.
AnyMap parameters(bool withInput=true) const
Returns the parameters of a ThermoPhase object such that an identical one could be reconstructed usin...
virtual string report(bool show_thermo=true, double threshold=-1e-14) const
returns a summary of the state of the phase as a string
virtual void getActivityConcentrations(span< double > c) const
This method returns an array of generalized concentrations.
virtual double maxTemp(size_t k=npos) const
Maximum temperature for which the thermodynamic data for the species are valid.
double o2Present(span< const double > y) const
Helper function for computing the amount of oxygen available in the current mixture.
virtual void setState_TPY(double t, double p, span< const double > y)
Set the internally stored temperature (K), pressure (Pa), and mass fractions of the phase.
virtual void setState_TPX(double t, double p, span< const double > x)
Set the temperature (K), pressure (Pa), and mole fractions.
virtual string phaseOfMatter() const
String indicating the mechanical phase of the matter in this Phase.
virtual void setState_Tsat(double t, double x)
Set the state to a saturated system at a particular temperature.
virtual double entropy_mole() const
Molar entropy. Units: J/kmol/K.
double cv_mass() const
Specific heat at constant volume and composition [J/kg/K].
virtual void getLnActivityCoefficients(span< double > lnac) const
Get the array of non-dimensional molar-based ln activity coefficients at the current solution tempera...
virtual int activityConvention() const
This method returns the convention used in specification of the activities, of which there are curren...
virtual void initThermo()
Initialize the ThermoPhase object after all species have been set up.
double entropy_mass() const
Specific entropy. Units: J/kg/K.
void getElectrochemPotentials(span< double > mu) const
Get the species electrochemical potentials.
virtual MultiSpeciesThermo & speciesThermo(int k=-1)
Return a changeable reference to the calculation manager for species reference-state thermodynamic pr...
virtual void setState_UP(double u, double p, double tol=1e-9)
Set the specific internal energy (J/kg) and pressure (Pa).
void initThermoFile(const string &inputFile, const string &id)
Initialize a ThermoPhase object using an input file.
shared_ptr< Solution > root() const
Get the Solution object containing this ThermoPhase object and linked Kinetics and Transport objects.
virtual void setState_SP(double s, double p, double tol=1e-9)
Set the specific entropy (J/kg/K) and pressure (Pa).
virtual int standardStateConvention() const
This method returns the convention used in specification of the standard state, of which there are cu...
void modifySpecies(size_t k, shared_ptr< Species > spec) override
Modify the thermodynamic data associated with a species.
virtual void setState_SH(double s, double h, double tol=1e-9)
Set the specific entropy (J/kg/K) and the specific enthalpy (J/kg)
virtual void getPartialMolarIntEnergies(span< double > ubar) const
Return an array of partial molar internal energies for the species in the mixture.
void invalidateCache() override
Invalidate any cached values which are normally updated only when a change in state is detected.
double stoichAirFuelRatio(span< const double > fuelComp, span< const double > oxComp, ThermoBasis basis=ThermoBasis::molar) const
Compute the stoichiometric air to fuel ratio (kg oxidizer / kg fuel) given fuel and oxidizer composit...
virtual double internalPressure() const
Return the internal pressure [Pa].
virtual void resetHf298(const size_t k=npos)
Restore the original heat of formation of one or more species.
double cp_mass() const
Specific heat at constant pressure and composition [J/kg/K].
virtual void setState_TH(double t, double h, double tol=1e-9)
Set the temperature (K) and the specific enthalpy (J/kg)
double intEnergy_mass() const
Specific internal energy. Units: J/kg.
virtual void getPartialMolarIntEnergies_TV(span< double > utilde) const
Return an array of partial molar internal energies at constant temperature and volume [J/kmol].
virtual Units standardConcentrationUnits() const
Returns the units of the "standard concentration" for this phase.
bool temperatureLimitsEnforced() const
Returns true if temperature limits are enforced for this phase.
void setMixtureFraction(double mixFrac, span< const double > fuelComp, span< const double > oxComp, ThermoBasis basis=ThermoBasis::molar)
Set the mixture composition according to the mixture fraction = kg fuel / (kg oxidizer + kg fuel)
double mixtureFraction(span< const double > fuelComp, span< const double > oxComp, ThermoBasis basis=ThermoBasis::molar, const string &element="Bilger") const
Compute the mixture fraction = kg fuel / (kg oxidizer + kg fuel) for the current mixture given fuel a...
void setEquivalenceRatio(double phi, span< const double > fuelComp, span< const double > oxComp, ThermoBasis basis=ThermoBasis::molar)
Set the mixture composition according to the equivalence ratio.
virtual double cv_mole() const
Molar heat capacity at constant volume and composition [J/kmol/K].
MultiSpeciesThermo m_spthermo
Pointer to the calculation manager for species reference-state thermodynamic properties.
virtual double satPressure(double t)
Return the saturation pressure given the temperature.
virtual void getChemPotentials(span< double > mu) const
Get the species chemical potentials. Units: J/kmol.
bool addSpecies(shared_ptr< Species > spec) override
Add a Species to this Phase.
AnyMap m_input
Data supplied via setParameters.
virtual double intEnergy_mole() const
Molar internal energy. Units: J/kmol.
virtual void setState_DP(double rho, double p)
Set the density (kg/m**3) and pressure (Pa) at constant composition.
void setState_TPQ(double T, double P, double Q)
Set the temperature, pressure, and vapor fraction (quality).
virtual void setState_VH(double v, double h, double tol=1e-9)
Set the specific volume (m^3/kg) and the specific enthalpy (J/kg)
virtual double gibbs_mole() const
Molar Gibbs function. Units: J/kmol.
virtual void setState_SV(double s, double v, double tol=1e-9)
Set the specific entropy (J/kg/K) and specific volume (m^3/kg).
const AnyMap & input() const
Access input data associated with the phase description.
virtual void setState_Psat(double p, double x)
Set the state to a saturated system at a particular pressure.
void setState_conditional_TP(double t, double p, bool set_p)
Helper function used by setState_HPorUV and setState_SPorSV.
virtual void getActivityCoefficients(span< double > ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
shared_ptr< ThermoPhase > clone() const
Create a new ThermoPhase object using the same species definitions, thermodynamic parameters,...
double enthalpy_mass() const
Specific enthalpy. Units: J/kg.
A representation of the units associated with a dimensional quantity.
This file contains definitions for utility functions and text for modules, inputfiles and logging,...
Composition parseCompString(const string &ss, const vector< string > &names)
Parse a composition string into a map consisting of individual key:composition pairs.
void equilibrate(const string &XY, const string &solver="auto", double rtol=1e-9, int max_steps=50000, int max_iter=100, int estimate_equil=0, int log_level=0)
Equilibrate a ThermoPhase object.
void debuglog(const string &msg, int loglevel)
Write a message to the log only if loglevel > 0.
double dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
T clip(const T &value, const T &lower, const T &upper)
Clip value such that lower <= value <= upper.
const double Faraday
Faraday constant [C/kmol].
const double OneAtm
One atmosphere [Pa].
shared_ptr< ThermoPhase > newThermo(const AnyMap &phaseNode, const AnyMap &rootNode)
Create a new ThermoPhase object and initialize it.
void setupPhase(ThermoPhase &thermo, const AnyMap &phaseNode, const AnyMap &rootNode)
Initialize a ThermoPhase object.
void warn_user(const string &method, const string &msg, const Args &... args)
Print a user warning raised from method as CanteraWarning.
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"
const int cAC_CONVENTION_MOLAR
Standard state uses the molar convention.
const double SmallNumber
smallest number to compare to zero.
ThermoBasis
Differentiate between mole fractions and mass fractions for input mixture composition.
map< string, double > Composition
Map from string names to doubles.
void checkArraySize(const char *procedure, size_t available, size_t required)
Wrapper for throwing ArraySizeError.
Contains declarations for string manipulation functions within Cantera.