22 string flag = string(xy);
25 }
else if (flag ==
"TV") {
27 }
else if (flag ==
"HP") {
29 }
else if (flag ==
"UV") {
31 }
else if (flag ==
"SP") {
33 }
else if (flag ==
"SV") {
35 }
else if (flag ==
"UP") {
38 throw CanteraError(
"_equilflag",
"unknown property pair "+flag);
45const char* targetPropertyName(
int XY)
58 return "internal energy";
60 return "specified property";
64[[noreturn]]
void throwTemperatureBoundError(
const string& XYstr,
int XY,
65 double target,
double current,
66 double currentT,
double Tmin,
67 double Tmax,
int boundDirection)
69 string bound = boundDirection > 0 ?
"upper" :
"lower";
70 double Tbound = boundDirection > 0 ? Tmax : Tmin;
71 throw CanteraError(
"ChemEquil::equilibrate",
72 "Equilibration with the '{}' property pair failed because the solver "
73 "reached the {} temperature bound of {} K. The target {} is {}, but "
74 "the current value is {} at T = {} K. The enforced temperature bounds "
75 "are {} K to {} K. Disable temperature-limit enforcement to allow "
76 "extrapolation beyond this range.",
77 XYstr, bound, Tbound, targetPropertyName(XY), target, current,
78 currentT, Tmin, Tmax);
100 m_jwork1.resize(
m_mm+2);
101 m_jwork2.resize(
m_mm+2);
102 m_mu_RT.resize(
m_kk);
105 m_orderVectorElements.resize(
m_mm);
107 for (
size_t m = 0; m <
m_mm; m++) {
108 m_orderVectorElements[m] = m;
110 m_orderVectorSpecies.resize(
m_kk);
111 for (
size_t k = 0; k <
m_kk; k++) {
112 m_orderVectorSpecies[k] = k;
117 for (
size_t m = 0; m <
m_mm; m++) {
118 for (
size_t k = 0; k <
m_kk; k++) {
122 if (s.
nAtoms(k,m) < 0.0) {
126 if (mneg !=
npos && mneg != m) {
128 "negative atom numbers allowed for only one element");
136 "species {} has {} atoms of element {}, "
137 "but this element is not an electron.",
146 for (
size_t k = 0; k <
m_kk; k++) {
147 for (
size_t m = 0; m <
m_mm; m++) {
156 fill(m_mu_RT.begin(), m_mu_RT.end(), 0.0);
157 for (
size_t k = 0; k <
m_kk; k++) {
158 for (
size_t m = 0; m <
m_mm; m++) {
159 m_mu_RT[k] += lambda_RT[m]*
nAtoms(k,m);
180 for (
size_t m = 0; m <
m_mm; m++) {
182 for (
size_t k = 0; k <
m_kk; k++) {
186 "negative mole fraction for {}: {}",
195 for (
size_t m = 0; m <
m_mm; m++) {
208 e.setInitialMixMoles(loglevel-1);
213 m_component[m] = e.componentIndex(m);
221 writelog(
"setInitialMoles: Estimated Mole Fractions\n");
224 for (
size_t k = 0; k <
m_kk; k++) {
228 writelog(
" Element_Name ElementGoal ElementMF\n");
229 for (
size_t m = 0; m <
m_mm; m++) {
238 span<double> elMolesGoal,
int loglevel)
240 vector<double> b(
m_mm, -999.0);
241 vector<double> mu_RT(
m_kk, 0.0);
242 vector<double> xMF_est(
m_kk, 0.0);
245 for (
size_t n = 0; n < s.
nSpecies(); n++) {
246 xMF_est[n] = std::max(xMF_est[n], 1e-20);
254 bool usedZeroedSpecies =
false;
257 &mp, m_orderVectorSpecies,
258 m_orderVectorElements, formRxnMatrix);
261 size_t k = m_orderVectorSpecies[m];
263 xMF_est[k] = std::max(xMF_est[k], 1e-8);
269 m_orderVectorSpecies, m_orderVectorElements);
272 scale(mu_RT.begin(), mu_RT.end(), mu_RT.begin(),
277 size_t isp = m_component[m];
283 for (
size_t n = 0; n < s.
nSpecies(); n++) {
291 aa(m,n) =
nAtoms(m_component[m], m_orderVectorElements[n]);
293 b[m] = mu_RT[m_component[m]];
303 lambda_RT[m_orderVectorElements[m]] = b[m];
306 lambda_RT[m_orderVectorElements[m]] = 0.0;
310 writelog(
" id CompSpecies ChemPot EstChemPot Diff\n");
312 size_t isp = m_component[m];
314 for (
size_t n = 0; n <
m_mm; n++) {
315 tmp +=
nAtoms(isp, n) * lambda_RT[n];
317 writelogf(
"%3d %16s %10.5g %10.5g %10.5g\n",
318 m, s.
speciesName(isp), mu_RT[isp], tmp, tmp - mu_RT[isp]);
322 for (
size_t m = 0; m <
m_mm; m++) {
334 return equilibrate(s, XY, elMolesGoal, loglevel-1);
338 span<double> elMolesGoal,
int loglevel)
340 bool tempFixed =
true;
349 "Input ThermoPhase is incompatible with initialization");
391 "illegal property pair '{}'", XYstr);
398 throw CanteraError(
"ChemEquil::equilibrate",
"Specified temperature"
399 " ({} K) outside valid range of {} K to {} K\n",
406 double xval = m_p1(s);
407 double yval = m_p2(s);
410 size_t nvar = mm + 1;
412 vector<double> x(nvar, -102.0);
413 vector<double> res_trial(nvar, 0.0);
421 size_t m = m_orderVectorElements[im];
422 if (elMolesGoal[m] > tmp) {
424 tmp = elMolesGoal[m];
429 "Element Abundance Vector is zeroed");
435 vector<double> xmm(
m_kk, 0.0);
436 for (
size_t k = 0; k <
m_kk; k++) {
444 double tmaxPhase = s.
maxTemp();
445 double tminPhase = s.
minTemp();
449 std::max(tmaxPhase + 1000.0, 10.0 * tmaxPhase);
450 if (tmaxSolver <= tminSolver) {
451 tmaxSolver = tminSolver + 20.0;
453 int limitingTemperatureBound = 0;
457 double tmin = std::max(s.
temperature(), tminSolver);
458 if (tmin > tmaxSolver) {
459 tmin = tmaxSolver - 20;
461 double tmax = std::min(tmin + 10., tmaxSolver);
462 if (tmax < tminSolver) {
463 tmax = tminSolver + 20;
466 double slope, phigh, plow, pval, dt;
481 double t0 = 0.5*(tmin + tmax);
485 for (
int it = 0; it < 10; it++) {
504 slope = (phigh - plow)/(tmax - tmin);
505 dt = (xval - pval)/slope;
508 if (fabs(dt) < 50.0) {
511 dt =
clip(dt, -200.0, 200.0);
512 if ((t0 + dt) < tminSolver) {
513 dt = 0.5*((t0) + tminSolver) - t0;
515 if ((t0 + dt) > tmaxSolver) {
516 dt = 0.5*((t0) + tmaxSolver) - t0;
520 if (t0 <= tminSolver || t0 >= tmaxSolver) {
521 double current = m_p1(s);
524 throwTemperatureBoundError(XYstr, XY, xval, current, currentT,
525 tminPhase, tmaxPhase,
526 t0 >= tmaxSolver ? 1 : -1);
558 vector<double> above(nvar);
559 vector<double> below(nvar);
560 for (
size_t m = 0; m < mm; m++) {
572 above[mm] = log(tmaxPhase);
575 above[mm] = log(tmaxSolver);
576 below[mm] = log(tminSolver);
579 vector<double> oldx(nvar, 0.0);
586 double deltax = (xx - xval)/xval;
587 double deltay = (yy - yval)/yval;
588 bool passThis =
true;
589 for (
size_t m = 0; m < nvar; m++) {
610 if (fabs(res_trial[m]) > tval) {
619 adjustEloc(s, elMolesGoal);
625 "Temperature ({} K) outside valid range of {} K "
635 equilJacobian(s, x, elMolesGoal, jac, xval, yval);
638 writelogf(
"Jacobian matrix %d:\n", iter);
639 for (
size_t m = 0; m <=
m_mm; m++) {
641 for (
size_t n = 0; n <=
m_mm; n++) {
649 }
else if (m == m_skip) {
654 writelog(
" = - ({:10.5g})\n", res_trial[m]);
659 scale(res_trial.begin(), res_trial.end(), res_trial.begin(), -1.0);
663 solve(jac, res_trial);
667 "Jacobian is singular. \nTry adding more species, "
668 "changing the elemental composition slightly, \nor removing "
679 double newTempVal = x[mm] + res_trial[mm];
680 if (newTempVal > above[mm]) {
681 limitingTemperatureBound = 1;
682 }
else if (newTempVal < below[mm]) {
683 limitingTemperatureBound = -1;
686 for (
size_t m = 0; m < nvar; m++) {
687 double newval = x[m] + res_trial[m];
688 if (newval > above[m]) {
690 std::min(fctr,0.8*(above[m] - x[m])/(newval - x[m])));
691 }
else if (newval < below[m]) {
692 if (m <
m_mm && (m != m_skip)) {
694 if (x[m] < below[m] + 50.) {
695 res_trial[m] = below[m] - x[m];
698 fctr = std::min(fctr, 0.8*(x[m] - below[m])/(x[m] - newval));
702 if (m == mm && fabs(res_trial[mm]) > 0.2) {
703 fctr = std::min(fctr, 0.2/fabs(res_trial[mm]));
706 if (fctr != 1.0 && loglevel > 0) {
708 "Soln Damping because of bounds: %g", fctr);
712 scale(res_trial.begin(), res_trial.end(), res_trial.begin(), fctr);
721 if (x[mm] >= above[mm] - 1e-10) {
722 limitingTemperatureBound = 1;
723 }
else if (x[mm] <= below[mm] + 1e-10) {
724 limitingTemperatureBound = -1;
727 double current = m_p1(s);
730 if (limitingTemperatureBound != 0) {
731 throwTemperatureBoundError(XYstr, XY, xval, current, currentT,
732 tminPhase, tmaxPhase, limitingTemperatureBound);
744 for (
size_t m = 0; m <
m_mm; m++) {
746 if (step[m] > 1.25) {
747 damp = std::min(damp, 1.25 /step[m]);
749 if (step[m] < -1.25) {
750 damp = std::min(damp, -1.25 / step[m]);
753 if (step[m] > 0.75) {
754 damp = std::min(damp, 0.75 /step[m]);
756 if (step[m] < -0.75) {
757 damp = std::min(damp, -0.75 / step[m]);
763 for (
size_t m = 0; m < x.size(); m++) {
764 x[m] = oldx[m] + damp * step[m];
767 writelogf(
"Solution Unknowns: damp = %g\n", damp);
769 for (
size_t m = 0; m <
m_mm; m++) {
770 writelogf(
" % -10.5g % -10.5g % -10.5g\n", x[m], oldx[m], step[m]);
776 span<const double> elmFracGoal, span<double> resid,
777 double xval,
double yval,
int loglevel)
783 for (
size_t n = 0; n <
m_mm; n++) {
784 size_t m = m_orderVectorElements[n];
787 resid[m] = x[m] + 1000.0;
793 if (elmFracGoal[m] < 1.0E-10 || elmFrac[m] < 1.0E-10 || m ==
m_eloc) {
794 resid[m] = elmFracGoal[m] - elmFrac[m];
796 resid[m] = log((1.0 + elmFracGoal[m]) / (1.0 + elmFrac[m]));
802 writelog(
"Residual: ElFracGoal ElFracCurrent Resid\n");
803 for (
size_t n = 0; n <
m_mm; n++) {
804 writelogf(
" % -14.7E % -14.7E % -10.5E\n",
805 elmFracGoal[n], elmFrac[n], resid[n]);
811 resid[
m_mm] = xx/xval - 1.0;
812 resid[m_skip] = yy/yval - 1.0;
816 writelogf(
" XX : % -14.7E % -14.7E % -10.5E\n", xval, xx, resid[
m_mm]);
817 writelogf(
" YY(%1d): % -14.7E % -14.7E % -10.5E\n", m_skip, yval, yy, resid[m_skip]);
821void ChemEquil::equilJacobian(
ThermoPhase& s, span<double> x, span<const double> elmols,
822 DenseMatrix& jac,
double xval,
double yval,
int loglevel)
824 vector<double>& r0 = m_jwork1;
825 vector<double>& r1 = m_jwork2;
826 size_t len = x.size();
829 double atol = 1.e-10;
833 for (
size_t n = 0; n <
len; n++) {
835 double dx = std::max(atol, fabs(xsave) * 1.0E-7);
844 for (
size_t m = 0; m < x.size(); m++) {
845 jac(m, n) = (r1[m] - r0[m])*rdx;
852 span<const double> Xmol_i_calc, span<double> eMolesCalc,
853 span<double> n_i_calc,
double pressureConst)
855 double n_t_calc = 0.0;
859 vector<double> actCoeff(
m_kk, 1.0);
864 for (
size_t k = 0; k <
m_kk; k++) {
865 double tmp = - (
m_muSS_RT[k] + log(actCoeff[k]));
866 for (
size_t m = 0; m <
m_mm; m++) {
867 tmp +=
nAtoms(k,m) * x[m];
869 tmp = std::min(tmp, 100.0);
873 n_i_calc[k] = n_t * exp(tmp);
875 n_t_calc += n_i_calc[k];
877 for (
size_t m = 0; m <
m_mm; m++) {
879 for (
size_t k = 0; k <
m_kk; k++) {
880 eMolesCalc[m] +=
nAtoms(k,m) * n_i_calc[k];
892 bool modifiedMatrix =
false;
896 vector<double> b(neq, 0.0);
897 vector<double> n_i(
m_kk,0.0);
898 vector<double> n_i_calc(
m_kk,0.0);
899 vector<double> actCoeff(
m_kk, 1.0);
903 double pressureConst = s.
pressure();
904 vector<double> Xmol_i_calc = n_i;
906 vector<double> x_old(
m_mm+1, 0.0);
907 vector<double> resid(
m_mm+1, 0.0);
908 vector<int> lumpSum(
m_mm+1, 0);
914 vector<double> eMolesCalc(
m_mm, 0.0);
915 vector<double> eMolesFix(
m_mm, 0.0);
916 double elMolesTotal = 0.0;
917 for (
size_t m = 0; m <
m_mm; m++) {
918 elMolesTotal += elMoles[m];
919 for (
size_t k = 0; k <
m_kk; k++) {
920 eMolesFix[m] +=
nAtoms(k,m) * n_i[k];
924 for (
size_t m = 0; m <
m_mm; m++) {
925 if (elMoles[m] > 1.0E-70) {
926 x[m] =
clip(x[m], -100.0, 50.0);
928 x[m] =
clip(x[m], -1000.0, 50.0);
933 double nAtomsMax = 1.0;
937 for (
size_t k = 0; k <
m_kk; k++) {
938 double tmp = - (
m_muSS_RT[k] + log(actCoeff[k]));
940 for (
size_t m = 0; m <
m_mm; m++) {
944 nAtomsMax = std::max(nAtomsMax, sum2);
954 writelog(
"estimateEP_Brinkley::\n\n");
957 writelog(
"Initial mole numbers and mu_SS:\n");
958 writelog(
" Name MoleNum mu_SS actCoeff\n");
959 for (
size_t k = 0; k <
m_kk; k++) {
963 writelogf(
"Initial n_t = %10.5g\n", n_t);
964 writelog(
"Comparison of Goal Element Abundance with Initial Guess:\n");
965 writelog(
" eName eCurrent eGoal\n");
966 for (
size_t m = 0; m <
m_mm; m++) {
971 for (
size_t m = 0; m <
m_mm; m++) {
980 for (
size_t m = 0; m <
m_mm; m++) {
986 writelogf(
"START ITERATION %d:\n", iter);
989 double n_t_calc =
calcEmoles(s, x, n_t, Xmol_i_calc, eMolesCalc, n_i_calc,
992 for (
size_t k = 0; k <
m_kk; k++) {
993 Xmol_i_calc[k] = n_i_calc[k]/n_t_calc;
997 writelog(
" Species: Calculated_Moles Calculated_Mole_Fraction\n");
998 for (
size_t k = 0; k <
m_kk; k++) {
1002 writelogf(
"%15s: %10.5g\n",
"Total Molar Sum", n_t_calc);
1003 writelogf(
"(iter %d) element moles bal: Goal Calculated\n", iter);
1004 for (
size_t m = 0; m <
m_mm; m++) {
1010 bool normalStep =
true;
1013 for (
size_t m = 0; m <
m_mm; m++) {
1014 if (elMoles[m] > 0.001 * elMolesTotal) {
1015 if (eMolesCalc[m] > 1000. * elMoles[m]) {
1019 if (1000 * eMolesCalc[m] < elMoles[m]) {
1026 writelogf(
" NOTE: iter(%d) Doing an abnormal step due to row %d\n", iter, iM);
1031 for (
size_t im = 0; im <
m_mm; im++) {
1032 size_t m = m_orderVectorElements[im];
1034 if (im <
m_nComponents && elMoles[m] > 0.001 * elMolesTotal) {
1035 if (eMolesCalc[m] > 1000. * elMoles[m]) {
1039 if (1000 * eMolesCalc[m] < elMoles[m]) {
1045 if (n_t < (elMolesTotal / nAtomsMax)) {
1046 if (resid[
m_mm] < 0.0) {
1049 }
else if (n_t > elMolesTotal) {
1050 resid[
m_mm] = std::min(resid[
m_mm], 0.0);
1075 for (
size_t m = 0; m <
m_mm; m++) {
1079 double nCutoff = 1.0E-9 * n_t_calc;
1081 writelog(
" Lump Sum Elements Calculation: \n");
1083 for (
size_t m = 0; m <
m_mm; m++) {
1085 size_t kMSp2 =
npos;
1086 for (
size_t k = 0; k <
m_kk; k++) {
1087 if (n_i_calc[k] > nCutoff && fabs(
nAtoms(k,m)) > 0.001) {
1090 double factor = fabs(
nAtoms(kMSp,m) /
nAtoms(kMSp2,m));
1091 for (
size_t n = 0; n <
m_mm; n++) {
1092 if (fabs(factor *
nAtoms(kMSp2,n) -
nAtoms(kMSp,n)) > 1.0E-8) {
1109 for (
size_t im = 0; im <
m_mm; im++) {
1110 size_t m = m_orderVectorElements[im];
1112 for (
size_t n = 0; n <
m_mm; n++) {
1114 for (
size_t k = 0; k <
m_kk; k++) {
1118 a1(m,
m_mm) = eMolesCalc[m];
1119 a1(
m_mm, m) = eMolesCalc[m];
1121 for (
size_t n = 0; n <=
m_mm; n++) {
1132 for (
size_t im = 0; im <
m_mm; im++) {
1133 size_t m = m_orderVectorElements[im];
1135 resid[m] = elMoles[m] - eMolesCalc[m];
1154 for (
size_t m = 0; m <
m_mm; m++) {
1155 if (a1(m,m) < 1.0E-50) {
1157 writelogf(
" NOTE: Diagonalizing the analytical Jac row %d\n", m);
1159 for (
size_t n = 0; n <
m_mm; n++) {
1163 if (resid[m] > 0.0) {
1165 }
else if (resid[m] < 0.0) {
1173 resid[
m_mm] = n_t - n_t_calc;
1177 for (
size_t m = 0; m <=
m_mm; m++) {
1179 for (
size_t n = 0; n <=
m_mm; n++) {
1186 sum += pow(resid[
m_mm] /(n_t + 1.0E-15), 2);
1188 writelogf(
"(it %d) Convergence = %g\n", iter, sum);
1201 for (
size_t m = 0; m <=
m_mm; m++) {
1203 for (
size_t n = 0; n <=
m_mm; n++) {
1204 tmp += fabs(a1(m,n));
1206 if (m <
m_mm && tmp < 1.0E-30) {
1208 writelogf(
" NOTE: Diagonalizing row %d\n", m);
1210 for (
size_t n = 0; n <=
m_mm; n++) {
1218 for (
size_t n = 0; n <=
m_mm; n++) {
1226 for (
size_t m = 0; m <=
m_mm; m++) {
1228 for (
size_t n = 0; n <=
m_mm; n++) {
1254 modifiedMatrix =
false;
1255 for (
size_t m = 0; m <
m_mm; m++) {
1256 size_t sameAsRow =
npos;
1257 for (
size_t im = 0; im < m; im++) {
1258 bool theSame =
true;
1259 for (
size_t n = 0; n <
m_mm; n++) {
1260 if (fabs(a1(m,n) - a1(im,n)) > 1.0E-7) {
1269 if (sameAsRow !=
npos || lumpSum[m]) {
1272 writelogf(
"Lump summing row %d, due to rank deficiency analysis\n", m);
1273 }
else if (sameAsRow !=
npos) {
1274 writelogf(
"Identified that rows %d and %d are the same\n", m, sameAsRow);
1277 modifiedMatrix =
true;
1278 for (
size_t n = 0; n <
m_mm; n++) {
1280 a1(m,m) += fabs(a1(m,n));
1288 writelog(
"Row Summed, MODIFIED Matrix:\n");
1289 for (
size_t m = 0; m <=
m_mm; m++) {
1291 for (
size_t n = 0; n <=
m_mm; n++) {
1303 "Jacobian is singular. \nTry adding more species, "
1304 "changing the elemental composition slightly, \nor removing "
1311 for (
size_t m = 0; m <
m_mm; m++) {
1312 if (resid[m] > 1.0) {
1313 beta = std::min(beta, 1.0 / resid[m]);
1315 if (resid[m] < -1.0) {
1316 beta = std::min(beta, -1.0 / resid[m]);
1320 writelogf(
"(it %d) Beta = %g\n", iter, beta);
1324 for (
size_t m = 0; m <
m_mm; m++) {
1325 x[m] += beta * resid[m];
1327 n_t *= exp(beta * resid[
m_mm]);
1330 writelogf(
"(it %d) OLD_SOLUTION NEW SOLUTION (undamped updated)\n", iter);
1331 for (
size_t m = 0; m <
m_mm; m++) {
1332 writelogf(
" %5s %10.5g %10.5g %10.5g\n",
1343 writelogf(
" ChemEquil::estimateEP_Brinkley() SUCCESS: equilibrium found at T = %g, Pres = %g\n",
1346 writelogf(
" ChemEquil::estimateEP_Brinkley() FAILURE: equilibrium not found at T = %g, Pres = %g\n",
1354void ChemEquil::adjustEloc(
ThermoPhase& s, span<double> elMolesGoal)
1359 if (fabs(elMolesGoal[
m_eloc]) > 1.0E-20) {
1363 size_t maxPosEloc =
npos;
1364 size_t maxNegEloc =
npos;
1365 double maxPosVal = -1.0;
1366 double maxNegVal = -1.0;
1368 for (
size_t k = 0; k <
m_kk; k++) {
1380 double sumPos = 0.0;
1381 double sumNeg = 0.0;
1382 for (
size_t k = 0; k <
m_kk; k++) {
1392 if (sumPos >= sumNeg) {
1393 if (sumPos <= 0.0) {
1396 double factor = (elMolesGoal[
m_eloc] + sumNeg) / sumPos;
1397 if (
m_loglevel > 0 && factor < 0.9999999999) {
1398 writelogf(
"adjustEloc: adjusted %s and friends from %g to %g to ensure neutrality condition\n",
1402 for (
size_t k = 0; k <
m_kk; k++) {
1408 double factor = (-elMolesGoal[
m_eloc] + sumPos) / sumNeg;
1409 if (
m_loglevel > 0 && factor < 0.9999999999) {
1410 writelogf(
"adjustEloc: adjusted %s and friends from %g to %g to ensure neutrality condition\n",
1414 for (
size_t k = 0; k <
m_kk; k++) {
Header file for class ThermoPhase, the base class for phases with thermodynamic properties,...
Base class for exceptions thrown by Cantera classes.
virtual string getMessage() const
Method overridden by derived classes to format the error message.
int setInitialMoles(ThermoPhase &s, span< double > elMoleGoal, int loglevel=0)
Estimate the initial mole numbers.
void equilResidual(ThermoPhase &s, span< const double > x, span< const double > elmtotal, span< double > resid, double xval, double yval, int loglevel=0)
Evaluates the residual vector F, of length m_mm.
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...
size_t m_kk
number of species in the phase
int m_loglevel
Verbosity of printed output.
size_t m_nComponents
This is equal to the rank of the stoichiometric coefficient matrix when it is computed.
ThermoPhase * m_phase
Pointer to the ThermoPhase object used to initialize this object.
double m_elementTotalSum
Current value of the sum of the element abundances given the current element potentials.
void update(const ThermoPhase &s)
Update internally stored state information.
int estimateElementPotentials(ThermoPhase &s, span< double > lambda, span< double > elMolesGoal, int loglevel=0)
Generate a starting estimate for the element potentials.
size_t m_eloc
Index of the element id corresponding to the electric charge of each species.
double calcEmoles(ThermoPhase &s, span< double > x, const double &n_t, span< const double > Xmol_i_calc, span< double > eMolesCalc, span< double > n_i_calc, double pressureConst)
Given a vector of dimensionless element abundances, this routine calculates the moles of the elements...
void initialize(ThermoPhase &s)
Prepare for equilibrium calculations.
EquilOpt options
Options controlling how the calculation is carried out.
vector< double > m_molefractions
Current value of the mole fractions in the single phase. length = m_kk.
vector< double > m_comp
Storage of the element compositions. natom(k,m) = m_comp[k*m_mm+ m];.
double nAtoms(size_t k, size_t m) const
number of atoms of element m in species k.
double m_elemFracCutoff
element fractional cutoff, below which the element will be zeroed.
vector< double > m_muSS_RT
Dimensionless values of the Gibbs free energy for the standard state of each species,...
void dampStep(span< double > oldx, span< double > step, span< double > x)
Find an acceptable step size and take it.
vector< double > m_elementmolefracs
Current value of the element mole fractions.
size_t m_mm
number of elements in the phase
void setToEquilState(ThermoPhase &s, span< const double > x, double t)
Set mixture to an equilibrium state consistent with specified element potentials and temperature.
int estimateEP_Brinkley(ThermoPhase &s, span< double > lambda, span< double > elMoles)
Do a calculation of the element potentials using the Brinkley method, p.
A class for full (non-sparse) matrices with Fortran-compatible data storage, which adds matrix operat...
double absElemTol
Abs Tol in element number.
int iterations
Iteration counter.
bool enforceTemperatureLimits
Enforce temperature validity limits during equilibrium solver iterations.
double relTolerance
Relative tolerance.
int maxIterations
Maximum number of iterations.
Multiphase chemical equilibrium solver.
A class for multiphase mixtures.
void init()
Process phases and build atomic composition array.
size_t nSpecies() const
Number of species, summed over all phases.
void addPhase(shared_ptr< ThermoPhase > p, double moles)
Add a phase to the mixture.
size_t nElements() const
Number of elements.
void getMoleFractions(span< double > x) const
Get the species mole fraction vector.
size_t nSpecies() const
Returns the number of species in the phase.
double temperature() const
Temperature (K).
virtual void setPressure(double p)
Set the internally stored pressure (Pa) at constant temperature and composition.
double atomicWeight(size_t m) const
Atomic weight of element m.
string speciesName(size_t k) const
Name of the species with index k.
virtual size_t stateSize() const
Return size of vector defining internal state of the phase.
double moleFraction(size_t k) const
Return the mole fraction of a single species.
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.
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.
virtual void saveState(span< double > state) const
Write to array 'state' the current internal state.
Base class for a phase with thermodynamic properties.
virtual void getGibbs_RT(span< double > grt) const
Get the nondimensional Gibbs functions for the species in their standard states at the current T and ...
virtual double minTemp(size_t k=npos) const
Minimum temperature for which the thermodynamic data for the species or phase are valid.
virtual double maxTemp(size_t k=npos) const
Maximum temperature for which the thermodynamic data for the species are valid.
double entropy_mass() const
Specific entropy. Units: J/kg/K.
double intEnergy_mass() const
Specific internal energy. Units: J/kg.
virtual void getChemPotentials(span< double > mu) const
Get the species chemical potentials. Units: J/kmol.
virtual void getActivityCoefficients(span< double > ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
double enthalpy_mass() const
Specific enthalpy. Units: J/kg.
This file contains definitions for utility functions and text for modules, inputfiles and logging,...
size_t BasisOptimize(bool &usedZeroedSpecies, bool doFormRxn, MultiPhase *mphase, span< size_t > orderVectorSpecies, span< size_t > orderVectorElements, span< double > formRxnMatrix)
Choose the optimum basis of species for the equilibrium calculations.
void ElemRearrange(size_t nComponents, span< const double > elementAbundances, MultiPhase *mphase, span< size_t > orderVectorSpecies, span< size_t > orderVectorElements)
Handles the potential rearrangement of the constraint equations represented by the Formula Matrix.
virtual void setToEquilState(span< const double > mu_RT)
This method is used by the ChemEquil equilibrium solver.
void writelogf(const char *fmt, const Args &... args)
Write a formatted message to the screen.
void writelog(const string &fmt, const Args &... args)
Write a formatted message to the screen.
U len(const T &container)
Get the size of a container, cast to a signed integer type.
void scale(InputIter begin, InputIter end, OutputIter out, S scale_factor)
Multiply elements of an array by a scale factor.
T clip(const T &value, const T &lower, const T &upper)
Clip value such that lower <= value <= upper.
const double GasConstant
Universal Gas Constant [J/kmol/K].
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"
void solve(DenseMatrix &A, span< double > b, size_t nrhs, size_t ldb)
Solve Ax = b. Array b is overwritten on exit with x.
const double SmallNumber
smallest number to compare to zero.
int _equilflag(const char *xy)
map property strings to integers
Contains declarations for string manipulation functions within Cantera.
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...