11 #include "cantera/base/mdp_allo.h"
26 ThermoPhase::ThermoPhase() :
28 m_spthermo(0), m_speciesData(0),
30 m_hasElementPotentials(false),
31 m_chargeNeutralityNecessary(false),
38 for (
size_t k = 0; k <
m_kk; k++) {
60 m_hasElementPotentials(false),
61 m_chargeNeutralityNecessary(false),
89 for (
size_t k = 0; k <
m_kk; k++) {
102 (void)Phase::operator=(right);
114 for (
size_t k = 0; k <
m_kk; k++) {
161 for (
size_t k = 0; k <
nSpecies(); k++) {
169 for (
size_t k = 0; k <
m_kk; k++) {
170 lnac[k] = std::log(lnac[k]);
191 for (
size_t k = 0; k <
nSpecies(); k++) {
199 "Unknown species in composition map: "+ x);
223 const std::string& y)
226 for (
size_t k = 0; k <
nSpecies(); k++) {
234 "Unknown species in composition map: "+ y);
288 doublereal dTtol,
bool doUV)
291 doublereal Hmax = 0.0, Hmin = 0.0;
299 "Input specific volume is too small or negative. v = " +
fp2str(v));
305 "Input pressure is too small or negative. p = " +
fp2str(p));
349 bool ignoreBounds =
false;
353 bool unstablePhase =
false;
356 double Tunstable = -1.0;
357 bool unstablePhaseNew =
false;
361 for (
int n = 0; n < 500; n++) {
366 unstablePhase =
true;
369 dt = (Htarget - Hold)/cpd;
374 }
else if (dt < -100.0) {
385 if (!unstablePhase) {
386 if (Htop > Htarget) {
387 if (Tnew > (0.75 * Ttop + 0.25 * Told)) {
388 dt = 0.75 * (Ttop - Told);
393 if (Hbot < Htarget) {
394 if (Tnew < (0.75 * Tbot + 0.25 * Told)) {
395 dt = 0.75 * (Tbot - Told);
401 if (!unstablePhase) {
402 if (Hbot < Htarget) {
403 if (Tnew < (0.75 * Tbot + 0.25 * Told)) {
404 dt = 0.75 * (Tbot - Told);
409 if (Htop > Htarget) {
410 if (Tnew > (0.75 * Ttop + 0.25 * Told)) {
411 dt = 0.75 * (Ttop - Told);
427 if (Hmax >= Htarget) {
428 if (Htop < Htarget) {
447 if (Hmin <= Htarget) {
448 if (Hbot > Htarget) {
462 for (
int its = 0; its < 10; its++) {
474 unstablePhaseNew =
true;
477 unstablePhaseNew =
false;
480 if (unstablePhase ==
false) {
481 if (unstablePhaseNew ==
true) {
487 if (Hnew == Htarget) {
489 }
else if (Hnew > Htarget) {
490 if ((Htop < Htarget) || (Hnew < Htop)) {
494 }
else if (Hnew < Htarget) {
495 if ((Hbot > Htarget) || (Hnew > Hbot)) {
501 double Herr = Htarget - Hnew;
502 double acpd =
std::max(fabs(cpd), 1.0E-5);
503 double denom =
std::max(fabs(Htarget), acpd * dTtol);
504 double HConvErr = fabs((Herr)/denom);
505 if (HConvErr < 0.00001 *dTtol) {
508 if (fabs(dt) < dTtol) {
518 string ErrString =
"No convergence in 500 iterations\n";
520 ErrString +=
"\tTarget Internal Energy = " +
fp2str(Htarget) +
"\n";
521 ErrString +=
"\tCurrent Specific Volume = " +
fp2str(v) +
"\n";
522 ErrString +=
"\tStarting Temperature = " +
fp2str(Tinit) +
"\n";
523 ErrString +=
"\tCurrent Temperature = " +
fp2str(Tnew) +
"\n";
524 ErrString +=
"\tCurrent Internal Energy = " +
fp2str(Hnew) +
"\n";
525 ErrString +=
"\tCurrent Delta T = " +
fp2str(dt) +
"\n";
527 ErrString +=
"\tTarget Enthalpy = " +
fp2str(Htarget) +
"\n";
528 ErrString +=
"\tCurrent Pressure = " +
fp2str(p) +
"\n";
529 ErrString +=
"\tStarting Temperature = " +
fp2str(Tinit) +
"\n";
530 ErrString +=
"\tCurrent Temperature = " +
fp2str(Tnew) +
"\n";
531 ErrString +=
"\tCurrent Enthalpy = " +
fp2str(Hnew) +
"\n";
532 ErrString +=
"\tCurrent Delta T = " +
fp2str(dt) +
"\n";
535 ErrString +=
"\t - The phase became unstable (Cp < 0) T_unstable_last = "
536 +
fp2str(Tunstable) +
"\n";
571 doublereal dTtol,
bool doSV)
579 "Input specific volume is too small or negative. v = " +
fp2str(v));
585 "Input pressure is too small or negative. p = " +
fp2str(p));
628 bool ignoreBounds =
false;
632 bool unstablePhase =
false;
633 double Tunstable = -1.0;
634 bool unstablePhaseNew =
false;
638 for (
int n = 0; n < 500; n++) {
643 unstablePhase =
true;
646 dt = (Starget - Sold)*Told/cpd;
651 }
else if (dt < -100.0) {
657 if (!unstablePhase) {
658 if (Stop > Starget) {
660 dt = 0.75 * (Ttop - Told);
665 if (Sbot < Starget) {
667 dt = 0.75 * (Tbot - Told);
673 if (!unstablePhase) {
674 if (Sbot < Starget) {
676 dt = 0.75 * (Tbot - Told);
681 if (Stop > Starget) {
683 dt = 0.75 * (Ttop - Told);
698 if (Smax >= Starget) {
699 if (Stop < Starget) {
717 if (Smin <= Starget) {
718 if (Sbot > Starget) {
732 for (
int its = 0; its < 10; its++) {
743 unstablePhaseNew =
true;
746 unstablePhaseNew =
false;
749 if (unstablePhase ==
false) {
750 if (unstablePhaseNew ==
true) {
756 if (Snew == Starget) {
758 }
else if (Snew > Starget) {
759 if ((Stop < Starget) || (Snew < Stop)) {
763 }
else if (Snew < Starget) {
764 if ((Sbot > Starget) || (Snew > Sbot)) {
770 double Serr = Starget - Snew;
771 double acpd =
std::max(fabs(cpd), 1.0E-5);
772 double denom =
std::max(fabs(Starget), acpd * dTtol);
773 double SConvErr = fabs((Serr * Tnew)/denom);
774 if (SConvErr < 0.00001 *dTtol) {
777 if (fabs(dt) < dTtol) {
786 string ErrString =
"No convergence in 500 iterations\n";
788 ErrString +=
"\tTarget Entropy = " +
fp2str(Starget) +
"\n";
789 ErrString +=
"\tCurrent Specific Volume = " +
fp2str(v) +
"\n";
790 ErrString +=
"\tStarting Temperature = " +
fp2str(Tinit) +
"\n";
791 ErrString +=
"\tCurrent Temperature = " +
fp2str(Tnew) +
"\n";
792 ErrString +=
"\tCurrent Entropy = " +
fp2str(Snew) +
"\n";
793 ErrString +=
"\tCurrent Delta T = " +
fp2str(dt) +
"\n";
795 ErrString +=
"\tTarget Entropy = " +
fp2str(Starget) +
"\n";
796 ErrString +=
"\tCurrent Pressure = " +
fp2str(p) +
"\n";
797 ErrString +=
"\tStarting Temperature = " +
fp2str(Tinit) +
"\n";
798 ErrString +=
"\tCurrent Temperature = " +
fp2str(Tnew) +
"\n";
799 ErrString +=
"\tCurrent Entropy = " +
fp2str(Snew) +
"\n";
800 ErrString +=
"\tCurrent Delta T = " +
fp2str(dt) +
"\n";
803 ErrString +=
"\t - The phase became unstable (Cp < 0) T_unstable_last = "
804 +
fp2str(Tunstable) +
"\n";
850 for (
int i = 0; i < sizeUA; i++) {
855 uA[1] = -int(
nDim());
908 "species reference state thermo manager was not set");
931 if (inputFile.size() == 0) {
933 "input file is null");
936 ifstream fin(path.c_str());
939 +path+
" for reading.");
951 "ERROR: Can not find phase named " +
952 id +
" in file named " + inputFile);
954 fxml_phase->
copy(&phaseNode_XML);
996 for (
size_t k = 0; k <
m_kk; k++) {
1003 for (
size_t k = 0; k <
m_kk; k++) {
1006 if (fabs(sum) > 1.0E-11) {
1007 throw CanteraError(
"ThermoPhase::setReferenceComposition",
1008 "input mole fractions don't sum to 1.0");
1015 for (
size_t k = 0; k <
m_kk; k++) {
1040 "Number of species is equal to zero");
1064 "m_speciesData is the wrong size");
1083 if (state.
hasChild(
"temperature")) {
1084 double t =
getFloat(state,
"temperature",
"temperature");
1088 double p =
getFloat(state,
"pressure",
"pressure");
1092 double rho =
getFloat(state,
"density",
"density");
1110 if (lambda.size() < mm) {
1111 throw CanteraError(
"setElementPotentials",
"lambda too small");
1116 for (
size_t m = 0; m < mm; m++) {
1133 for (
size_t m = 0; m <
nElements(); m++) {
1160 for (
size_t m = 0; m <
m_kk; m++) {
1161 for (
size_t k = 0; k <
m_kk; k++) {
1162 dlnActCoeffdlnN[ld * k + m] = 0.0;
1168 void ThermoPhase::getdlnActCoeffdlnN_numderiv(
const size_t ld, doublereal*
const dlnActCoeffdlnN)
1170 double deltaMoles_j = 0.0;
1176 std::vector<double> ActCoeff_Base(
m_kk);
1178 std::vector<double> Xmol_Base(
m_kk);
1182 std::vector<double> ActCoeff(
m_kk);
1183 std::vector<double> Xmol(
m_kk);
1184 double v_totalMoles = 1.0;
1185 double TMoles_base = v_totalMoles;
1190 for (
size_t j = 0; j <
m_kk; j++) {
1198 double moles_j_base = v_totalMoles * Xmol_Base[j];
1199 deltaMoles_j = 1.0E-7 * moles_j_base + v_totalMoles * 1.0E-13 + 1.0E-150;
1204 v_totalMoles = TMoles_base + deltaMoles_j;
1205 for (
size_t k = 0; k <
m_kk; k++) {
1206 Xmol[k] = Xmol_Base[k] * TMoles_base / v_totalMoles;
1208 Xmol[j] = (moles_j_base + deltaMoles_j) / v_totalMoles;
1220 double*
const lnActCoeffCol = dlnActCoeffdlnN + ld * j;
1221 for (
size_t k = 0; k <
m_kk; k++) {
1222 lnActCoeffCol[k] = (2*moles_j_base + deltaMoles_j) *(ActCoeff[k] - ActCoeff_Base[k]) /
1223 ((ActCoeff[k] + ActCoeff_Base[k]) * deltaMoles_j);
1228 v_totalMoles = TMoles_base;
1249 sprintf(p,
" \n %s:\n",
name().c_str());
1252 sprintf(p,
" \n temperature %12.6g K\n",
temperature());
1254 sprintf(p,
" pressure %12.6g Pa\n",
pressure());
1256 sprintf(p,
" density %12.6g kg/m^3\n",
density());
1263 sprintf(p,
" potential %12.6g V\n", phi);
1269 sprintf(p,
" 1 kg 1 kmol\n");
1271 sprintf(p,
" ----------- ------------\n");
1273 sprintf(p,
" enthalpy %12.6g %12.4g J\n",
1276 sprintf(p,
" internal energy %12.6g %12.4g J\n",
1279 sprintf(p,
" entropy %12.6g %12.4g J/K\n",
1282 sprintf(p,
" Gibbs function %12.6g %12.4g J\n",
1285 sprintf(p,
" heat capacity c_p %12.6g %12.4g J/K\n",
1289 sprintf(p,
" heat capacity c_v %12.6g %12.4g J/K\n",
1294 sprintf(p,
" heat capacity c_v <not implemented> \n");
1311 " Y Chem. Pot. / RT \n");
1313 sprintf(p,
" ------------- "
1314 "------------ ------------\n");
1316 for (
size_t k = 0; k < kk; k++) {
1318 sprintf(p,
"%18s %12.6g %12.6g %12.6g\n",
1321 sprintf(p,
"%18s %12.6g %12.6g \n",
1330 sprintf(p,
" -------------"
1333 for (
size_t k = 0; k < kk; k++) {
1334 sprintf(p,
"%18s %12.6g %12.6g\n",
1353 csvFile.precision(3);
1359 csvFile <<
"\n"+
name()+
"\n\n";
1361 csvFile << setw(tabL) <<
"temperature (K) =" << setw(tabS) <<
temperature() << endl;
1362 csvFile << setw(tabL) <<
"pressure (Pa) =" << setw(tabS) <<
pressure() << endl;
1363 csvFile << setw(tabL) <<
"density (kg/m^3) =" << setw(tabS) <<
density() << endl;
1364 csvFile << setw(tabL) <<
"mean mol. weight (amu) =" << setw(tabS) <<
meanMolecularWeight() << endl;
1365 csvFile << setw(tabL) <<
"potential (V) =" << setw(tabS) <<
electricPotential() << endl;
1368 csvFile << setw(tabL) <<
"enthalpy (J/kg) = " << setw(tabS) <<
enthalpy_mass() << setw(tabL)
1369 <<
"enthalpy (J/kmol) = " << setw(tabS) <<
enthalpy_mole() << endl;
1370 csvFile << setw(tabL) <<
"internal E (J/kg) = " << setw(tabS) <<
intEnergy_mass() << setw(tabL)
1371 <<
"internal E (J/kmol) = " << setw(tabS) <<
intEnergy_mole() << endl;
1372 csvFile << setw(tabL) <<
"entropy (J/kg) = " << setw(tabS) <<
entropy_mass() << setw(tabL)
1373 <<
"entropy (J/kmol) = " << setw(tabS) <<
entropy_mole() << endl;
1374 csvFile << setw(tabL) <<
"Gibbs (J/kg) = " << setw(tabS) <<
gibbs_mass() << setw(tabL)
1375 <<
"Gibbs (J/kmol) = " << setw(tabS) <<
gibbs_mole() << endl;
1376 csvFile << setw(tabL) <<
"heat capacity c_p (J/K/kg) = " << setw(tabS) <<
cp_mass()
1377 << setw(tabL) <<
"heat capacity c_p (J/K/kmol) = " << setw(tabS) <<
cp_mole() << endl;
1378 csvFile << setw(tabL) <<
"heat capacity c_v (J/K/kg) = " << setw(tabS) <<
cv_mass()
1379 << setw(tabL) <<
"heat capacity c_v (J/K/kmol) = " << setw(tabS) <<
cv_mole() << endl;
1381 csvFile.precision(8);
1384 doublereal* x =
new doublereal[kk];
1385 doublereal* y =
new doublereal[kk];
1386 doublereal* mu =
new doublereal[kk];
1387 doublereal* a =
new doublereal[kk];
1388 doublereal* ac =
new doublereal[kk];
1389 doublereal* hbar =
new doublereal[kk];
1390 doublereal* sbar =
new doublereal[kk];
1391 doublereal* ubar =
new doublereal[kk];
1392 doublereal* cpbar=
new doublereal[kk];
1393 doublereal* vbar =
new doublereal[kk];
1394 std::vector<std::string> pNames;
1395 std::vector<doublereal*> data;
1398 pNames.push_back(
"X");
1402 pNames.push_back(
"Y");
1409 pNames.push_back(
"Chem. Pot (J/kmol)");
1416 pNames.push_back(
"Activity");
1423 pNames.push_back(
"Act. Coeff.");
1430 pNames.push_back(
"Part. Mol Enthalpy (J/kmol)");
1431 data.push_back(hbar);
1437 pNames.push_back(
"Part. Mol. Entropy (J/K/kmol)");
1438 data.push_back(sbar);
1444 pNames.push_back(
"Part. Mol. Energy (J/kmol)");
1445 data.push_back(ubar);
1451 pNames.push_back(
"Part. Mol. Cp (J/K/kmol");
1452 data.push_back(cpbar);
1458 pNames.push_back(
"Part. Mol. Cv (J/K/kmol)");
1459 data.push_back(vbar);
1464 csvFile << endl << setw(tabS) <<
"Species,";
1465 for (
size_t i = 0; i < pNames.size(); i++) {
1466 csvFile << setw(tabM) << pNames[i] <<
",";
1474 for (
size_t k = 0; k < kk; k++) {
1477 for (
size_t i = 0; i < pNames.size(); i++) {
1478 csvFile << setw(tabM) << data[i][k] <<
",";
1482 for (
size_t i = 0; i < pNames.size(); i++) {
1483 csvFile << setw(tabM) << 0 <<
",";
1506 return th.
report(show_thermo);