20 int ChemEquil_print_lvl = 0;
24 string flag = string(xy);
27 }
else if (flag ==
"TV") {
29 }
else if (flag ==
"HP") {
31 }
else if (flag ==
"UV") {
33 }
else if (flag ==
"SP") {
35 }
else if (flag ==
"SV") {
37 }
else if (flag ==
"UP") {
40 throw CanteraError(
"_equilflag",
"unknown property pair "+flag);
45 ChemEquil::ChemEquil() : m_skip(
npos), m_elementTotalSum(1.0),
47 m_elemFracCutoff(1.0E-100),
53 m_elementTotalSum(1.0),
55 m_elemFracCutoff(1.0E-100),
61 ChemEquil::~ChemEquil()
79 m_jwork1.resize(
m_mm+2);
80 m_jwork2.resize(
m_mm+2);
81 m_startSoln.resize(
m_mm+1);
86 m_orderVectorElements.resize(
m_mm);
88 for (
size_t m = 0; m <
m_mm; m++) {
89 m_orderVectorElements[m] = m;
91 m_orderVectorSpecies.resize(
m_kk);
92 for (
size_t k = 0; k <
m_kk; k++) {
93 m_orderVectorSpecies[k] = k;
98 for (
size_t m = 0; m <
m_mm; m++) {
99 for (
size_t k = 0; k <
m_kk; k++) {
103 if (s.
nAtoms(k,m) < 0.0) {
107 if (mneg !=
npos && mneg != m) {
109 "negative atom numbers allowed for only one element");
116 writelog(
"WARNING: species {} has {} atoms of element {}," 117 " but this element is not an electron.\n",
126 for (
size_t k = 0; k <
m_kk; k++) {
127 for (
size_t m = 0; m <
m_mm; m++) {
134 const vector_fp& lambda_RT, doublereal t)
137 fill(m_mu_RT.begin(), m_mu_RT.end(), 0.0);
138 for (
size_t k = 0; k <
m_kk; k++) {
139 for (
size_t m = 0; m <
m_mm; m++) {
140 m_mu_RT[k] += lambda_RT[m]*
nAtoms(k,m);
163 for (
size_t m = 0; m <
m_mm; m++) {
165 for (
size_t k = 0; k <
m_kk; k++) {
169 "negative mole fraction for {}: {}",
178 for (
size_t m = 0; m <
m_mm; m++) {
190 e.setInitialMixMoles(loglevel-1);
195 m_component[m] = e.componentIndex(m);
202 if (ChemEquil_print_lvl > 0) {
203 writelog(
"setInitialMoles: Estimated Mole Fractions\n");
206 for (
size_t k = 0; k <
m_kk; k++) {
210 writelog(
" Element_Name ElementGoal ElementMF\n");
211 for (
size_t m = 0; m <
m_mm; m++) {
227 for (
size_t n = 0; n < s.
nSpecies(); n++) {
228 xMF_est[n] = std::max(xMF_est[n], 1e-20);
236 int usedZeroedSpecies = 0;
239 &mp, m_orderVectorSpecies,
240 m_orderVectorElements, formRxnMatrix);
243 size_t k = m_orderVectorSpecies[m];
245 xMF_est[k] = std::max(xMF_est[k], 1e-8);
251 m_orderVectorSpecies, m_orderVectorElements);
254 scale(mu_RT.begin(), mu_RT.end(), mu_RT.begin(),
257 if (ChemEquil_print_lvl > 0) {
259 size_t isp = m_component[m];
265 for (
size_t n = 0; n < s.
nSpecies(); n++) {
273 aa(m,n) =
nAtoms(m_component[m], m_orderVectorElements[n]);
275 b[m] = mu_RT[m_component[m]];
283 lambda_RT[m_orderVectorElements[m]] = b[m];
286 lambda_RT[m_orderVectorElements[m]] = 0.0;
289 if (ChemEquil_print_lvl > 0) {
290 writelog(
" id CompSpecies ChemPot EstChemPot Diff\n");
292 size_t isp = m_component[m];
294 for (
size_t n = 0; n <
m_mm; n++) {
295 tmp +=
nAtoms(isp, n) * lambda_RT[n];
297 writelogf(
"%3d %16s %10.5g %10.5g %10.5g\n",
298 m, s.
speciesName(isp), mu_RT[isp], tmp, tmp - mu_RT[isp]);
302 for (
size_t m = 0; m <
m_mm; m++) {
310 bool useThermoPhaseElementPotentials,
int loglevel)
315 return equilibrate(s, XY, elMolesGoal, useThermoPhaseElementPotentials,
321 bool useThermoPhaseElementPotentials,
325 bool tempFixed =
true;
333 "Input ThermoPhase is incompatible with initialization");
374 throw CanteraError(
"equilibrate",
"illegal property pair.");
381 throw CanteraError(
"ChemEquil::equilibrate",
"Specified temperature" 382 " ({} K) outside valid range of {} K to {} K\n",
389 double xval = m_p1(s);
390 double yval = m_p2(s);
393 size_t nvar = mm + 1;
404 size_t m = m_orderVectorElements[im];
405 if (elMolesGoal[m] > tmp) {
407 tmp = elMolesGoal[m];
412 "Element Abundance Vector is zeroed");
419 for (
size_t k = 0; k <
m_kk; k++) {
428 doublereal tmaxPhase = s.
maxTemp();
429 doublereal tminPhase = s.
minTemp();
432 doublereal tmin = std::max(s.
temperature(), tminPhase);
433 if (tmin > tmaxPhase) {
434 tmin = tmaxPhase - 20;
436 doublereal tmax = std::min(tmin + 10., tmaxPhase);
437 if (tmax < tminPhase) {
438 tmax = tminPhase + 20;
441 doublereal slope, phigh, plow, pval, dt;
456 doublereal t0 = 0.5*(tmin + tmax);
460 for (
int it = 0; it < 10; it++) {
479 slope = (phigh - plow)/(tmax - tmin);
480 dt = (xval - pval)/slope;
483 if (fabs(dt) < 50.0) {
486 dt =
clip(dt, -200.0, 200.0);
487 if ((t0 + dt) < tminPhase) {
488 dt = 0.5*((t0) + tminPhase) - t0;
490 if ((t0 + dt) > tmaxPhase) {
491 dt = 0.5*((t0) + tmaxPhase) - t0;
495 if (t0 <= tminPhase || t0 >= tmaxPhase || t0 < 100.0) {
496 throw CanteraError(
"ChemEquil::equilibrate",
"T out of bounds");
506 if (useThermoPhaseElementPotentials) {
512 for (
size_t m = 0; m <
m_mm; m++) {
513 x[m] *= 1.0 / s.
RT();
547 for (
size_t m = 0; m < mm; m++) {
557 above[mm] = log(s.
maxTemp() + 25.0);
558 below[mm] = log(s.
minTemp() - 25.0);
567 double f = 0.5*
dot(res_trial.begin(), res_trial.end(), res_trial.begin());
570 double deltax = (xx - xval)/xval;
571 double deltay = (yy - yval)/yval;
572 bool passThis =
true;
573 for (
size_t m = 0; m < nvar; m++) {
594 if (fabs(res_trial[m]) > tval) {
601 for (
size_t m = 0; m <
m_mm; m++) {
606 adjustEloc(s, elMolesGoal);
614 writelog(
"Warning: Temperature ({} K) outside valid range of " 623 f = 0.5*
dot(res_trial.begin(), res_trial.end(), res_trial.begin());
626 equilJacobian(s, x, elMolesGoal, jac, xval, yval);
628 if (ChemEquil_print_lvl > 0) {
629 writelogf(
"Jacobian matrix %d:\n", iter);
630 for (
size_t m = 0; m <=
m_mm; m++) {
632 for (
size_t n = 0; n <=
m_mm; n++) {
640 }
else if (m == m_skip) {
645 writelog(
" = - ({:10.5g})\n", res_trial[m]);
651 scale(res_trial.begin(), res_trial.end(), res_trial.begin(), -1.0);
659 "Jacobian is singular. \nTry adding more species, " 660 "changing the elemental composition slightly, \nor removing " 667 for (
size_t m = 0; m < nvar; m++) {
668 double newval = x[m] + res_trial[m];
669 if (newval > above[m]) {
671 std::min(fctr,0.8*(above[m] - x[m])/(newval - x[m])));
672 }
else if (newval < below[m]) {
673 if (m <
m_mm && (m != m_skip)) {
675 if (x[m] < below[m] + 50.) {
676 res_trial[m] = below[m] - x[m];
679 fctr = std::min(fctr, 0.8*(x[m] - below[m])/(x[m] - newval));
683 if (m == mm && fabs(res_trial[mm]) > 0.2) {
684 fctr = std::min(fctr, 0.2/fabs(res_trial[mm]));
687 if (fctr != 1.0 && ChemEquil_print_lvl > 0) {
688 writelogf(
"WARNING Soln Damping because of bounds: %g\n", fctr);
692 scale(res_trial.begin(), res_trial.end(), res_trial.begin(), fctr);
694 if (!
dampStep(s, oldx, oldf, grad, res_trial,
695 x, f, elMolesGoal , xval, yval)) {
700 "Cannot find an acceptable Newton damping coefficient.");
716 double& f,
vector_fp& elmols,
double xval,
double yval)
721 for (
size_t m = 0; m <
m_mm; m++) {
723 if (step[m] > 1.25) {
724 damp = std::min(damp, 1.25 /step[m]);
726 if (step[m] < -1.25) {
727 damp = std::min(damp, -1.25 / step[m]);
730 if (step[m] > 0.75) {
731 damp = std::min(damp, 0.75 /step[m]);
733 if (step[m] < -0.75) {
734 damp = std::min(damp, -0.75 / step[m]);
740 for (
size_t m = 0; m < x.size(); m++) {
741 x[m] = oldx[m] + damp * step[m];
743 if (ChemEquil_print_lvl > 0) {
744 writelogf(
"Solution Unknowns: damp = %g\n", damp);
746 for (
size_t m = 0; m <
m_mm; m++) {
747 writelogf(
" % -10.5g % -10.5g % -10.5g\n", x[m], oldx[m], step[m]);
755 doublereal xval, doublereal yval,
int loglevel)
761 for (
size_t n = 0; n <
m_mm; n++) {
762 size_t m = m_orderVectorElements[n];
765 resid[m] = x[m] + 1000.0;
771 if (elmFracGoal[m] < 1.0E-10 || elmFrac[m] < 1.0E-10 || m ==
m_eloc) {
772 resid[m] = elmFracGoal[m] - elmFrac[m];
774 resid[m] = log((1.0 + elmFracGoal[m]) / (1.0 + elmFrac[m]));
779 if (ChemEquil_print_lvl > 0 && !m_doResPerturb) {
780 writelog(
"Residual: ElFracGoal ElFracCurrent Resid\n");
781 for (
size_t n = 0; n <
m_mm; n++) {
782 writelogf(
" % -14.7E % -14.7E % -10.5E\n",
783 elmFracGoal[n], elmFrac[n], resid[n]);
789 resid[
m_mm] = xx/xval - 1.0;
790 resid[m_skip] = yy/yval - 1.0;
792 if (ChemEquil_print_lvl > 0 && !m_doResPerturb) {
794 writelogf(
" XX : % -14.7E % -14.7E % -10.5E\n", xval, xx, resid[
m_mm]);
795 writelogf(
" YY(%1d): % -14.7E % -14.7E % -10.5E\n", m_skip, yval, yy, resid[m_skip]);
801 doublereal xval, doublereal yval,
int loglevel)
805 size_t len = x.size();
808 doublereal atol = 1.e-10;
812 m_doResPerturb =
false;
813 for (
size_t n = 0; n < len; n++) {
815 double dx = std::max(atol, fabs(xsave) * 1.0E-7);
824 for (
size_t m = 0; m < x.size(); m++) {
825 jac(m, n) = (r1[m] - r0[m])*rdx;
829 m_doResPerturb =
false;
835 double pressureConst)
837 double n_t_calc = 0.0;
846 for (
size_t k = 0; k <
m_kk; k++) {
847 double tmp = - (
m_muSS_RT[k] + log(actCoeff[k]));
848 for (
size_t m = 0; m <
m_mm; m++) {
849 tmp +=
nAtoms(k,m) * x[m];
851 tmp = std::min(tmp, 100.0);
855 n_i_calc[k] = n_t * exp(tmp);
857 n_t_calc += n_i_calc[k];
859 for (
size_t m = 0; m <
m_mm; m++) {
861 for (
size_t k = 0; k <
m_kk; k++) {
862 eMolesCalc[m] +=
nAtoms(k,m) * n_i_calc[k];
875 bool modifiedMatrix =
false;
886 double pressureConst = s.
pressure();
899 double elMolesTotal = 0.0;
900 for (
size_t m = 0; m <
m_mm; m++) {
901 elMolesTotal += elMoles[m];
902 for (
size_t k = 0; k <
m_kk; k++) {
903 eMolesFix[m] +=
nAtoms(k,m) * n_i[k];
907 for (
size_t m = 0; m <
m_mm; m++) {
908 if (elMoles[m] > 1.0E-70) {
909 x[m] =
clip(x[m], -100.0, 50.0);
911 x[m] =
clip(x[m], -1000.0, 50.0);
916 double nAtomsMax = 1.0;
920 for (
size_t k = 0; k <
m_kk; k++) {
921 double tmp = - (
m_muSS_RT[k] + log(actCoeff[k]));
923 for (
size_t m = 0; m <
m_mm; m++) {
927 nAtomsMax = std::max(nAtomsMax, sum2);
936 if (ChemEquil_print_lvl > 0) {
937 writelog(
"estimateEP_Brinkley::\n\n");
940 writelog(
"Initial mole numbers and mu_SS:\n");
941 writelog(
" Name MoleNum mu_SS actCoeff\n");
942 for (
size_t k = 0; k <
m_kk; k++) {
946 writelogf(
"Initial n_t = %10.5g\n", n_t);
947 writelog(
"Comparison of Goal Element Abundance with Initial Guess:\n");
948 writelog(
" eName eCurrent eGoal\n");
949 for (
size_t m = 0; m <
m_mm; m++) {
954 for (
size_t m = 0; m <
m_mm; m++) {
963 for (
size_t m = 0; m <
m_mm; m++) {
968 if (ChemEquil_print_lvl > 0) {
969 writelogf(
"START ITERATION %d:\n", iter);
972 double n_t_calc =
calcEmoles(s, x, n_t, Xmol_i_calc, eMolesCalc, n_i_calc,
975 for (
size_t k = 0; k <
m_kk; k++) {
976 Xmol_i_calc[k] = n_i_calc[k]/n_t_calc;
979 if (ChemEquil_print_lvl > 0) {
980 writelog(
" Species: Calculated_Moles Calculated_Mole_Fraction\n");
981 for (
size_t k = 0; k <
m_kk; k++) {
985 writelogf(
"%15s: %10.5g\n",
"Total Molar Sum", n_t_calc);
986 writelogf(
"(iter %d) element moles bal: Goal Calculated\n", iter);
987 for (
size_t m = 0; m <
m_mm; m++) {
993 bool normalStep =
true;
996 for (
size_t m = 0; m <
m_mm; m++) {
997 if (elMoles[m] > 0.001 * elMolesTotal) {
998 if (eMolesCalc[m] > 1000. * elMoles[m]) {
1002 if (1000 * eMolesCalc[m] < elMoles[m]) {
1008 if (ChemEquil_print_lvl > 0 && !normalStep) {
1009 writelogf(
" NOTE: iter(%d) Doing an abnormal step due to row %d\n", iter, iM);
1014 for (
size_t im = 0; im <
m_mm; im++) {
1015 size_t m = m_orderVectorElements[im];
1017 if (im <
m_nComponents && elMoles[m] > 0.001 * elMolesTotal) {
1018 if (eMolesCalc[m] > 1000. * elMoles[m]) {
1022 if (1000 * eMolesCalc[m] < elMoles[m]) {
1028 if (n_t < (elMolesTotal / nAtomsMax)) {
1029 if (resid[
m_mm] < 0.0) {
1032 }
else if (n_t > elMolesTotal) {
1033 resid[
m_mm] = std::min(resid[
m_mm], 0.0);
1058 for (
size_t m = 0; m <
m_mm; m++) {
1062 double nCutoff = 1.0E-9 * n_t_calc;
1063 if (ChemEquil_print_lvl > 0) {
1064 writelog(
" Lump Sum Elements Calculation: \n");
1066 for (
size_t m = 0; m <
m_mm; m++) {
1068 size_t kMSp2 =
npos;
1069 int nSpeciesWithElem = 0;
1070 for (
size_t k = 0; k <
m_kk; k++) {
1071 if (n_i_calc[k] > nCutoff && fabs(
nAtoms(k,m)) > 0.001) {
1075 double factor = fabs(
nAtoms(kMSp,m) /
nAtoms(kMSp2,m));
1076 for (
size_t n = 0; n <
m_mm; n++) {
1077 if (fabs(factor *
nAtoms(kMSp2,n) -
nAtoms(kMSp,n)) > 1.0E-8) {
1087 if (ChemEquil_print_lvl > 0) {
1094 for (
size_t im = 0; im <
m_mm; im++) {
1095 size_t m = m_orderVectorElements[im];
1097 for (
size_t n = 0; n <
m_mm; n++) {
1099 for (
size_t k = 0; k <
m_kk; k++) {
1103 a1(m,
m_mm) = eMolesCalc[m];
1104 a1(
m_mm, m) = eMolesCalc[m];
1106 for (
size_t n = 0; n <=
m_mm; n++) {
1117 for (
size_t im = 0; im <
m_mm; im++) {
1118 size_t m = m_orderVectorElements[im];
1120 resid[m] = elMoles[m] - eMolesCalc[m];
1139 for (
size_t m = 0; m <
m_mm; m++) {
1140 if (a1(m,m) < 1.0E-50) {
1141 if (ChemEquil_print_lvl > 0) {
1142 writelogf(
" NOTE: Diagonalizing the analytical Jac row %d\n", m);
1144 for (
size_t n = 0; n <
m_mm; n++) {
1148 if (resid[m] > 0.0) {
1150 }
else if (resid[m] < 0.0) {
1158 resid[
m_mm] = n_t - n_t_calc;
1160 if (ChemEquil_print_lvl > 0) {
1162 for (
size_t m = 0; m <=
m_mm; m++) {
1164 for (
size_t n = 0; n <=
m_mm; n++) {
1171 sum += pow(resid[
m_mm] /(n_t + 1.0E-15), 2);
1172 if (ChemEquil_print_lvl > 0) {
1173 writelogf(
"(it %d) Convergence = %g\n", iter, sum);
1186 for (
size_t m = 0; m <=
m_mm; m++) {
1188 for (
size_t n = 0; n <=
m_mm; n++) {
1189 tmp += fabs(a1(m,n));
1191 if (m <
m_mm && tmp < 1.0E-30) {
1192 if (ChemEquil_print_lvl > 0) {
1193 writelogf(
" NOTE: Diagonalizing row %d\n", m);
1195 for (
size_t n = 0; n <=
m_mm; n++) {
1203 for (
size_t n = 0; n <=
m_mm; n++) {
1209 if (ChemEquil_print_lvl > 0) {
1211 for (
size_t m = 0; m <=
m_mm; m++) {
1213 for (
size_t n = 0; n <=
m_mm; n++) {
1239 modifiedMatrix =
false;
1240 for (
size_t m = 0; m <
m_mm; m++) {
1241 size_t sameAsRow =
npos;
1242 for (
size_t im = 0; im < m; im++) {
1243 bool theSame =
true;
1244 for (
size_t n = 0; n <
m_mm; n++) {
1245 if (fabs(a1(m,n) - a1(im,n)) > 1.0E-7) {
1254 if (sameAsRow !=
npos || lumpSum[m]) {
1255 if (ChemEquil_print_lvl > 0) {
1257 writelogf(
"Lump summing row %d, due to rank deficiency analysis\n", m);
1258 }
else if (sameAsRow !=
npos) {
1259 writelogf(
"Identified that rows %d and %d are the same\n", m, sameAsRow);
1262 modifiedMatrix =
true;
1263 for (
size_t n = 0; n <
m_mm; n++) {
1265 a1(m,m) += fabs(a1(m,n));
1272 if (ChemEquil_print_lvl > 0 && modifiedMatrix) {
1273 writelog(
"Row Summed, MODIFIED Matrix:\n");
1274 for (
size_t m = 0; m <=
m_mm; m++) {
1276 for (
size_t n = 0; n <=
m_mm; n++) {
1287 throw CanteraError(
"equilibrate:estimateEP_Brinkley()",
1288 "Jacobian is singular. \nTry adding more species, " 1289 "changing the elemental composition slightly, \nor removing " 1296 for (
size_t m = 0; m <
m_mm; m++) {
1297 if (resid[m] > 1.0) {
1298 beta = std::min(beta, 1.0 / resid[m]);
1300 if (resid[m] < -1.0) {
1301 beta = std::min(beta, -1.0 / resid[m]);
1304 if (ChemEquil_print_lvl > 0 && beta != 1.0) {
1305 writelogf(
"(it %d) Beta = %g\n", iter, beta);
1309 for (
size_t m = 0; m <
m_mm; m++) {
1310 x[m] += beta * resid[m];
1312 n_t *= exp(beta * resid[
m_mm]);
1314 if (ChemEquil_print_lvl > 0) {
1315 writelogf(
"(it %d) OLD_SOLUTION NEW SOLUTION (undamped updated)\n", iter);
1316 for (
size_t m = 0; m <
m_mm; m++) {
1317 writelogf(
" %5s %10.5g %10.5g %10.5g\n",
1323 if (ChemEquil_print_lvl > 0) {
1328 writelogf(
" ChemEquil::estimateEP_Brinkley() SUCCESS: equilibrium found at T = %g, Pres = %g\n",
1331 writelogf(
" ChemEquil::estimateEP_Brinkley() FAILURE: equilibrium not found at T = %g, Pres = %g\n",
1344 if (fabs(elMolesGoal[
m_eloc]) > 1.0E-20) {
1348 size_t maxPosEloc =
npos;
1349 size_t maxNegEloc =
npos;
1350 double maxPosVal = -1.0;
1351 double maxNegVal = -1.0;
1352 if (ChemEquil_print_lvl > 0) {
1353 for (
size_t k = 0; k <
m_kk; k++) {
1365 double sumPos = 0.0;
1366 double sumNeg = 0.0;
1367 for (
size_t k = 0; k <
m_kk; k++) {
1377 if (sumPos >= sumNeg) {
1378 if (sumPos <= 0.0) {
1381 double factor = (elMolesGoal[
m_eloc] + sumNeg) / sumPos;
1382 if (ChemEquil_print_lvl > 0 && factor < 0.9999999999) {
1383 writelogf(
"adjustEloc: adjusted %s and friends from %g to %g to ensure neutrality condition\n",
1387 for (
size_t k = 0; k <
m_kk; k++) {
1393 double factor = (-elMolesGoal[
m_eloc] + sumPos) / sumNeg;
1394 if (ChemEquil_print_lvl > 0 && factor < 0.9999999999) {
1395 writelogf(
"adjustEloc: adjusted %s and friends from %g to %g to ensure neutrality condition\n",
1399 for (
size_t k = 0; k <
m_kk; k++) {
EquilOpt options
Options controlling how the calculation is carried out.
size_t nElements() const
Number of elements.
void restoreState(const vector_fp &state)
Restore a state saved on a previous call to saveState.
vector_fp m_muSS_RT
Dimensionless values of the Gibbs free energy for the standard state of each species, at the temperature and pressure of the solution (the star standard state).
size_t BasisOptimize(int *usedZeroedSpecies, bool doFormRxn, MultiPhase *mphase, std::vector< size_t > &orderVectorSpecies, std::vector< size_t > &orderVectorElements, vector_fp &formRxnMatrix)
Choose the optimum basis of species for the equilibrium calculations.
thermo_t * m_phase
Pointer to the ThermoPhase object used to initialize this object.
doublereal relTolerance
Relative tolerance.
const doublereal OneAtm
One atmosphere [Pa].
doublereal temperature() const
Temperature (K).
int setInitialMoles(thermo_t &s, vector_fp &elMoleGoal, int loglevel=0)
Estimate the initial mole numbers.
doublereal nAtoms(size_t k, size_t m) const
number of atoms of element m in species k.
void saveState(vector_fp &state) const
Save the current internal state of the phase.
doublereal moleFraction(size_t k) const
Return the mole fraction of a single species.
const size_t npos
index returned by functions to indicate "no position"
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
virtual void getGibbs_RT(doublereal *grt) const
Get the nondimensional Gibbs functions for the species in their standard states at the current T and ...
bool getElementPotentials(doublereal *lambda) const
Returns the element potentials stored in the ThermoPhase object.
size_t m_kk
number of species in the phase
void writelog(const std::string &fmt, const Args &... args)
Write a formatted message to the screen.
void addPhase(ThermoPhase *p, doublereal moles)
Add a phase to the mixture.
doublereal m_elementTotalSum
Current value of the sum of the element abundances given the current element potentials.
int equilibrate(thermo_t &s, const char *XY, bool useThermoPhaseElementPotentials=false, int loglevel=0)
T clip(const T &value, const T &lower, const T &upper)
Clip value such that lower <= value <= upper.
size_t nSpecies() const
Returns the number of species in the phase.
virtual doublereal density() const
Density (kg/m^3).
int solve(DenseMatrix &A, double *b, size_t nrhs, size_t ldb)
Solve Ax = b. Array b is overwritten on exit with x.
void initialize(thermo_t &s)
virtual doublereal minTemp(size_t k=npos) const
Minimum temperature for which the thermodynamic data for the species or phase are valid...
doublereal enthalpy_mass() const
Specific enthalpy. Units: J/kg.
size_t m_nComponents
This is equal to the rank of the stoichiometric coefficient matrix when it is computed.
vector_fp m_elementmolefracs
Current value of the element mole fractions.
void ElemRearrange(size_t nComponents, const vector_fp &elementAbundances, MultiPhase *mphase, std::vector< size_t > &orderVectorSpecies, std::vector< size_t > &orderVectorElements)
Handles the potential rearrangement of the constraint equations represented by the Formula Matrix...
void equilResidual(thermo_t &s, const vector_fp &x, const vector_fp &elmtotal, vector_fp &resid, double xval, double yval, int loglevel=0)
Evaluates the residual vector F, of length m_mm.
void update(const thermo_t &s)
Update internally stored state information.
int iterations
Iteration counter.
doublereal RT() const
Return the Gas Constant multiplied by the current temperature.
Base class for a phase with thermodynamic properties.
virtual std::string getMessage() const
Method overridden by derived classes to format the error message.
std::vector< int > vector_int
Vector of ints.
doublereal atomicWeight(size_t m) const
Atomic weight of element m.
void setToEquilState(thermo_t &s, const vector_fp &x, doublereal t)
A class for multiphase mixtures.
size_t m_eloc
Index of the element id corresponding to the electric charge of each species.
std::string speciesName(size_t k) const
Name of the species with index k.
vector_fp m_comp
Storage of the element compositions. natom(k,m) = m_comp[k*m_mm+ m];.
doublereal absElemTol
Abs Tol in element number.
double m_elemFracCutoff
element fractional cutoff, below which the element will be zeroed.
doublereal entropy_mass() const
Specific entropy. Units: J/kg/K.
int estimateEP_Brinkley(thermo_t &s, vector_fp &lambda, vector_fp &elMoles)
Base class for exceptions thrown by Cantera classes.
virtual void setMoleFractions(const doublereal *const x)
Set the mole fractions to the specified values.
vector_fp & data()
Return a reference to the data vector.
int estimateElementPotentials(thermo_t &s, vector_fp &lambda, vector_fp &elMolesGoal, int loglevel=0)
Generate a starting estimate for the element potentials.
size_t m_mm
number of elements in the phase
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
doublereal dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
virtual doublereal pressure() const
Return the thermodynamic pressure (Pa).
void writelogf(const char *fmt, const Args &... args)
Write a formatted message to the screen.
virtual void setPressure(doublereal p)
Set the internally stored pressure (Pa) at constant temperature and composition.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
virtual void setTemperature(const doublereal temp)
Set the internally stored temperature of the phase (K).
void scale(InputIter begin, InputIter end, OutputIter out, S scale_factor)
Multiply elements of an array by a scale factor.
vector_fp m_lambda
Current value of the dimensional element potentials. length = m_mm.
virtual doublereal refPressure() const
Returns the reference pressure in Pa.
const doublereal GasConstant
Universal Gas Constant. [J/kmol/K].
void init()
Process phases and build atomic composition array.
Contains declarations for string manipulation functions within Cantera.
void setElementPotentials(const vector_fp &lambda)
Stores the element potentials in the ThermoPhase object.
vector_fp m_molefractions
Current value of the mole fractions in the single phase. length = m_kk.
double calcEmoles(thermo_t &s, vector_fp &x, const double &n_t, const vector_fp &Xmol_i_calc, vector_fp &eMolesCalc, vector_fp &n_i_calc, double pressureConst)
Given a vector of dimensionless element abundances, this routine calculates the moles of the elements...
int maxIterations
Maximum number of iterations.
int _equilflag(const char *xy)
map property strings to integers
virtual void setToEquilState(const doublereal *lambda_RT)
This method is used by the ChemEquil equilibrium solver.
Namespace for the Cantera kernel.
doublereal intEnergy_mass() const
Specific internal energy. Units: J/kg.
virtual doublereal maxTemp(size_t k=npos) const
Maximum temperature for which the thermodynamic data for the species are valid.
doublereal nAtoms(size_t k, size_t m) const
Number of atoms of element m in species k.
std::string elementName(size_t m) const
Name of the element with index m.
A class for full (non-sparse) matrices with Fortran-compatible data storage, which adds matrix operat...
int dampStep(thermo_t &s, vector_fp &oldx, double oldf, vector_fp &grad, vector_fp &step, vector_fp &x, double &f, vector_fp &elmols, double xval, double yval)
Find an acceptable step size and take it.