31 int Cantera::ChemEquil_print_lvl = 0;
39 string flag = string(xy);
42 }
else if (flag ==
"TV") {
44 }
else if (flag ==
"HP") {
46 }
else if (flag ==
"UV") {
48 }
else if (flag ==
"SP") {
50 }
else if (flag ==
"SV") {
52 }
else if (flag ==
"UP") {
55 throw CanteraError(
"_equilflag",
"unknown property pair "+flag);
67 ChemEquil::ChemEquil() : m_skip(
npos), m_elementTotalSum(1.0),
69 m_elemFracCutoff(1.0E-100),
81 m_elementTotalSum(1.0),
83 m_elemFracCutoff(1.0E-100),
89 ChemEquil::~ChemEquil()
110 m_elementmolefracs.resize(m_mm);
111 m_comp.resize(m_mm * m_kk);
112 m_jwork1.resize(m_mm+2);
113 m_jwork2.resize(m_mm+2);
114 m_startSoln.resize(m_mm+1);
116 m_mu_RT.resize(m_kk);
118 m_component.resize(m_mm,
npos);
119 m_orderVectorElements.resize(m_mm);
121 for (
size_t m = 0; m < m_mm; m++) {
122 m_orderVectorElements[m] = m;
124 m_orderVectorSpecies.resize(m_kk);
125 for (
size_t k = 0; k < m_kk; k++) {
126 m_orderVectorSpecies[k] = k;
132 for (
size_t m = 0; m < m_mm; m++) {
133 for (
size_t k = 0; k < m_kk; k++) {
144 if (mneg !=
npos && mneg != m)
146 "negative atom numbers allowed for only one element");
156 +
" atoms of element "
158 ", but this element is not an electron.\n"));
165 for (
size_t k = 0; k < m_kk; k++) {
166 for (
size_t m = 0; m < m_mm; m++) {
167 m_comp[k*m_mm + m] = s.
nAtoms(k,m);
183 const vector_fp& lambda_RT, doublereal t)
186 fill(m_mu_RT.begin(), m_mu_RT.end(), 0.0);
187 for (
size_t k = 0; k < m_kk; k++)
188 for (
size_t m = 0; m < m_mm; m++) {
189 m_mu_RT[k] += lambda_RT[m]*
nAtoms(k,m);
216 for (
size_t m = 0; m < m_mm; m++) {
217 m_elementmolefracs[m] = 0.0;
218 for (
size_t k = 0; k < m_kk; k++) {
226 sum += m_elementmolefracs[m];
229 m_elementTotalSum = sum;
231 for (
size_t m = 0; m < m_mm; m++) {
232 m_elementmolefracs[m] /= sum;
250 e.setInitialMixMoles(loglevel-1);
257 m_component[m] = e.componentIndex(m);
259 for (
size_t k = 0; k < m_kk; k++) {
274 if (ChemEquil_print_lvl > 0) {
276 writelog(
"setInitialMoles: Estimated Mole Fractions\n");
279 for (
size_t k = 0; k < m_kk; k++) {
283 writelogf(
" %-12s % -10.5g\n", nnn.c_str(), mf);
285 writelog(
" Element_Name ElementGoal ElementMF\n");
286 for (
size_t m = 0; m < m_mm; m++) {
289 nnn.c_str(), elMoleGoal[m], m_elementmolefracs[m]);
328 for (
size_t n = 0; n < s.
nSpecies(); n++) {
329 if (xMF_est[n] < 1.0E-20) {
330 xMF_est[n] = 1.0E-20;
339 int usedZeroedSpecies = 0;
342 &mp, m_orderVectorSpecies,
343 m_orderVectorElements, formRxnMatrix);
346 size_t k = m_orderVectorSpecies[m];
348 if (xMF_est[k] < 1.0E-8) {
356 m_orderVectorSpecies, m_orderVectorElements);
357 if (nct != m_nComponents) {
358 throw CanteraError(
"ChemEquil::estimateElementPotentials",
364 scale(mu_RT.begin(), mu_RT.end(), mu_RT.begin(), rrt);
367 if (ChemEquil_print_lvl > 0) {
370 int isp = m_component[m];
372 writelogf(
"isp = %d, %s\n", isp, nnn.c_str());
379 for (
size_t n = 0; n < s.
nSpecies(); n++) {
381 double mf = pc.
cropAbs10(xMF_est[n], -28);
383 n, nnn.c_str(), mf, mu_RT[n]);
390 aa(m,n) =
nAtoms(m_component[m], m_orderVectorElements[n]);
392 b[m] = mu_RT[m_component[m]];
398 addLogEntry(
"failed to estimate initial element potentials.");
403 lambda_RT[m_orderVectorElements[m]] = b[m];
405 for (
size_t m = m_nComponents; m < m_mm; m++) {
406 lambda_RT[m_orderVectorElements[m]] = 0.0;
410 for (
size_t m = 0; m < m_mm; m++) {
417 if (ChemEquil_print_lvl > 0) {
418 writelog(
" id CompSpecies ChemPot EstChemPot Diff\n");
420 int isp = m_component[m];
423 for (
size_t n = 0; n < m_mm; n++) {
424 tmp +=
nAtoms(isp, n) * lambda_RT[n];
426 writelogf(
"%3d %16s %10.5g %10.5g %10.5g\n",
427 m, sname.c_str(), mu_RT[isp], tmp, tmp - mu_RT[isp]);
431 for (
size_t m = 0; m < m_mm; m++) {
433 writelogf(
" %3d %6s %10.5g\n", m, ename.c_str(), lambda_RT[m]);
453 bool useThermoPhaseElementPotentials,
int loglevel)
458 copy(m_elementmolefracs.begin(), m_elementmolefracs.end(),
459 elMolesGoal.begin());
460 return equilibrate(s, XY, elMolesGoal, useThermoPhaseElementPotentials,
482 bool useThermoPhaseElementPotentials,
485 doublereal xval, yval, tmp;
488 bool tempFixed =
true;
499 "Input ThermoPhase is incompatible with initialization");
514 m_p1.reset(
new TemperatureCalculator<thermo_t>);
515 m_p2.reset(
new PressureCalculator<thermo_t>);
520 m_p1.reset(
new EnthalpyCalculator<thermo_t>);
521 m_p2.reset(
new PressureCalculator<thermo_t>);
526 m_p1.reset(
new EntropyCalculator<thermo_t>);
527 m_p2.reset(
new PressureCalculator<thermo_t>);
532 m_p1.reset(
new EntropyCalculator<thermo_t>);
533 m_p2.reset(
new DensityCalculator<thermo_t>);
537 m_p1.reset(
new TemperatureCalculator<thermo_t>);
538 m_p2.reset(
new DensityCalculator<thermo_t>);
543 m_p1.reset(
new IntEnergyCalculator<thermo_t>);
544 m_p2.reset(
new DensityCalculator<thermo_t>);
550 throw CanteraError(
"equilibrate",
"illegal property pair.");
553 addLogEntry(
"Problem type",
"fixed "+m_p1->symbol()+
", "+m_p2->symbol());
565 throw CanteraError(
"ChemEquil",
"Specified temperature ("
577 xval = m_p1->value(s);
578 yval = m_p2->value(s);
581 size_t nvar = mm + 1;
596 m = m_orderVectorElements[im];
597 if (elMolesGoal[m] > tmp) {
599 tmp = elMolesGoal[m];
604 "Element Abundance Vector is zeroed");
612 for (
size_t k = 0; k < m_kk; k++) {
623 doublereal tmaxPhase = s.
maxTemp();
624 doublereal tminPhase = s.
minTemp();
635 if (tmin < tminPhase) {
638 if (tmin > tmaxPhase) {
639 tmin = tmaxPhase - 20;
642 if (tmax > tmaxPhase) {
645 if (tmax < tminPhase) {
646 tmax = tminPhase + 20;
649 doublereal slope, phigh, plow, pval, dt;
658 phigh = m_p1->value(s);
662 plow = m_p1->value(s);
665 doublereal t0 = 0.5*(tmin + tmax);
669 for (
int it = 0; it < 10; it++) {
673 pval = m_p1->value(s);
689 slope = (phigh - plow)/(tmax - tmin);
690 dt = (xval - pval)/slope;
693 if (fabs(dt) < 50.0) {
702 if ((t0 + dt) < tminPhase) {
703 dt = 0.5*((t0) + tminPhase) - t0;
705 if ((t0 + dt) > tmaxPhase) {
706 dt = 0.5*((t0) + tmaxPhase) - t0;
710 if (t0 <= tminPhase || t0 >= tmaxPhase) {
711 printf(
"We shouldn't be here\n");
718 printf(
"t0 - we are here %g\n", t0);
736 if (useThermoPhaseElementPotentials) {
743 for (m = 0; m < m_mm; m++) {
776 addLogEntry(
"estimateEP_Brinkley didn't converge in given max iterations");
777 }
else if (info == -3) {
778 addLogEntry(
"estimateEP_Brinkley had a singular Jacobian. Continuing anyway");
804 for (m = 0; m < mm; m++) {
807 if (elMolesGoal[m] < m_elemFracCutoff && m !=
m_eloc) {
815 above[mm] = log(s.
maxTemp() + 25.0);
816 below[mm] = log(s.
minTemp() - 25.0);
824 doublereal fctr = 1.0, newval;
840 f = 0.5*
dot(res_trial.begin(), res_trial.end(), res_trial.begin());
844 equilJacobian(s, x, elMolesGoal, jac, xval, yval);
847 if (ChemEquil_print_lvl > 0) {
848 writelogf(
"Jacobian matrix %d:\n", iter);
849 for (m = 0; m <= m_mm; m++) {
851 for (n = 0; n <= m_mm; n++) {
857 string nnn = eNames[m];
858 sprintf(xName,
"x_%-10s", nnn.c_str());
860 sprintf(xName,
"x_XX");
863 sprintf(xName,
"x_ELOC");
866 sprintf(xName,
"x_YY");
869 writelogf(
" = - (%10.5g)\n", res_trial[m]);
877 copy(x.begin(), x.end(), oldx.begin());
879 scale(res_trial.begin(), res_trial.end(), res_trial.begin(), -1.0);
894 "Jacobian is singular. \nTry adding more species, "
895 "changing the elemental composition slightly, \nor removing "
903 for (m = 0; m < nvar; m++) {
904 newval = x[m] + res_trial[m];
905 if (newval > above[m]) {
907 std::min(fctr,0.8*(above[m] - x[m])/(newval - x[m])));
908 }
else if (newval < below[m]) {
909 if (m < m_mm && (m != m_skip)) {
911 if (x[m] < below[m] + 50.) {
912 res_trial[m] = below[m] - x[m];
915 fctr =
std::min(fctr, 0.8*(x[m] - below[m])/(x[m] - newval));
920 if (fabs(res_trial[mm]) > 0.2) {
921 fctr =
std::min(fctr, 0.2/fabs(res_trial[mm]));
926 addLogEntry(
"WARNING: factor to keep solution in bounds", fctr);
928 if (ChemEquil_print_lvl > 0) {
929 writelogf(
"WARNING Soln Damping because of bounds: %g\n", fctr);
935 scale(res_trial.begin(), res_trial.end(), res_trial.begin(), fctr);
937 if (!dampStep(s, oldx, oldf, grad, res_trial,
938 x, f, elMolesGoal , xval, yval)) {
941 addLogEntry(
"dampStep",
"Failed 3 times. Giving up.");
946 "Cannot find an acceptable Newton damping coefficient.");
957 f = 0.5*
dot(res_trial.begin(), res_trial.end(), res_trial.begin());
958 doublereal xx, yy, deltax, deltay;
961 deltax = (xx - xval)/xval;
962 deltay = (yy - yval)/yval;
963 doublereal rmax = 0.0;
964 bool passThis =
true;
965 for (m = 0; m < nvar; m++) {
988 if (fabs(res_trial[m]) > tval) {
992 if (iter > 0 && passThis
1000 addLogEntry(
"Relative error in "+m_p1->symbol(),deltax);
1001 addLogEntry(
"Relative error in "+m_p2->symbol(),deltay);
1006 for (m = 0; m < m_mm; m++) {
1014 adjustEloc(s, elMolesGoal);
1022 addLogEntry(
"Saving Element Potentials to ThermoPhase Object");
1072 double& f,
vector_fp& elmols,
double xval,
double yval)
1080 for (
size_t m = 0; m < m_mm; m++) {
1082 if (step[m] > 1.25) {
1083 damp =
std::min(damp, 1.25 /step[m]);
1085 if (step[m] < -1.25) {
1086 damp =
std::min(damp, -1.25 / step[m]);
1089 if (step[m] > 0.75) {
1090 damp =
std::min(damp, 0.75 /step[m]);
1092 if (step[m] < -0.75) {
1093 damp =
std::min(damp, -0.75 / step[m]);
1101 for (
size_t m = 0; m < x.size(); m++) {
1102 x[m] = oldx[m] + damp * step[m];
1105 if (ChemEquil_print_lvl > 0) {
1106 writelogf(
"Solution Unknowns: damp = %g\n", damp);
1108 for (
size_t m = 0; m < m_mm; m++) {
1109 writelogf(
" % -10.5g % -10.5g % -10.5g\n", x[m], oldx[m], step[m]);
1122 doublereal xval, doublereal yval,
int loglevel)
1128 doublereal temp = exp(x[m_mm]);
1132 vector_fp& elmFrac = m_elementmolefracs;
1133 for (
size_t n = 0; n < m_mm; n++) {
1134 size_t m = m_orderVectorElements[n];
1136 if (elmFracGoal[m] < m_elemFracCutoff && m !=
m_eloc) {
1137 resid[m] = x[m] + 1000.0;
1146 if (elmFracGoal[m] < 1.0E-10 || elmFrac[m] < 1.0E-10 || m ==
m_eloc) {
1147 resid[m] = elmFracGoal[m] - elmFrac[m];
1149 resid[m] = log((1.0 + elmFracGoal[m]) / (1.0 + elmFrac[m]));
1154 +
fp2str(elmFracGoal[m])+
")");
1158 if (ChemEquil_print_lvl > 0 && !m_doResPerturb) {
1160 writelog(
"Residual: ElFracGoal ElFracCurrent Resid\n");
1161 for (
int n = 0; n < m_mm; n++) {
1162 double rrr = pc.
cropAbs10(resid[n], -14);
1163 writelogf(
" % -14.7E % -14.7E % -10.5E\n",
1164 elmFracGoal[n], elmFrac[n], rrr);
1169 xx = m_p1->value(s);
1170 yy = m_p2->value(s);
1171 resid[m_mm] = xx/xval - 1.0;
1172 resid[m_skip] = yy/yval - 1.0;
1182 if (ChemEquil_print_lvl > 0 && !m_doResPerturb) {
1185 writelogf(
" XX : % -14.7E % -14.7E % -10.5E\n", xval, xx, resid[m_mm]);
1186 double rrr = pc.
cropAbs10(resid[m_skip], -14);
1187 writelogf(
" YY(%1d): % -14.7E % -14.7E % -10.5E\n", m_skip, yval, yy, rrr);
1197 doublereal xval, doublereal yval,
int loglevel)
1204 size_t len = x.size();
1208 doublereal rdx, dx, xsave, dx2;
1209 doublereal atol = 1.e-10;
1213 m_doResPerturb =
false;
1214 for (n = 0; n < len; n++) {
1217 dx2 = fabs(xsave) * 1.0E-7;
1231 for (m = 0; m < x.size(); m++) {
1232 jac(m, n) = (r1[m] - r0[m])*rdx;
1236 m_doResPerturb =
false;
1253 double pressureConst)
1255 double n_t_calc = 0.0;
1266 for (
size_t k = 0; k < m_kk; k++) {
1267 tmp = - (
m_muSS_RT[k] + log(actCoeff[k]));
1268 for (
size_t m = 0; m < m_mm; m++) {
1269 tmp +=
nAtoms(k,m) * x[m];
1277 n_i_calc[k] = n_t * exp(tmp);
1279 n_t_calc += n_i_calc[k];
1281 for (
size_t m = 0; m < m_mm; m++) {
1282 eMolesCalc[m] = 0.0;
1283 for (
size_t k = 0; k < m_kk; k++) {
1284 eMolesCalc[m] +=
nAtoms(k,m) * n_i_calc[k];
1337 bool modifiedMatrix =
false;
1338 size_t neq = m_mm+1;
1351 double pressureConst = s.
pressure();
1352 copy(n_i.begin(), n_i.end(), Xmol_i_calc.begin());
1368 double elMolesTotal = 0.0;
1369 for (m = 0; m < m_mm; m++) {
1370 elMolesTotal += elMoles[m];
1371 for (k = 0; k < m_kk; k++) {
1372 eMolesFix[m] +=
nAtoms(k,m) * n_i[k];
1376 for (m = 0; m < m_mm; m++) {
1380 if (elMoles[m] > 1.0E-70) {
1385 if (x[m] < -1000.) {
1394 double nAtomsMax = 1.0;
1398 for (k = 0; k < m_kk; k++) {
1399 tmp = - (
m_muSS_RT[k] + log(actCoeff[k]));
1401 for (m = 0; m < m_mm; m++) {
1405 if (sum2 > nAtomsMax) {
1419 if (ChemEquil_print_lvl > 0) {
1420 writelog(
"estimateEP_Brinkley::\n\n");
1425 writelog(
"Initial mole numbers and mu_SS:\n");
1426 writelog(
" Name MoleNum mu_SS actCoeff\n");
1427 for (k = 0; k < m_kk; k++) {
1429 writelogf(
"%15s %13.5g %13.5g %13.5g\n",
1430 nnn.c_str(), n_i[k],
m_muSS_RT[k], actCoeff[k]);
1432 writelogf(
"Initial n_t = %10.5g\n", n_t);
1433 writelog(
"Comparison of Goal Element Abundance with Initial Guess:\n");
1434 writelog(
" eName eCurrent eGoal\n");
1435 for (m = 0; m < m_mm; m++) {
1437 writelogf(
"%5s %13.5g %13.5g\n",nnn.c_str(), eMolesFix[m], elMoles[m]);
1441 for (m = 0; m < m_mm; m++) {
1457 for (m = 0; m < m_mm; m++) {
1465 if (ChemEquil_print_lvl > 0) {
1466 writelogf(
"START ITERATION %d:\n", iter);
1472 double n_t_calc =
calcEmoles(s, x, n_t, Xmol_i_calc, eMolesCalc, n_i_calc,
1475 for (k = 0; k < m_kk; k++) {
1476 Xmol_i_calc[k] = n_i_calc[k]/n_t_calc;
1481 if (ChemEquil_print_lvl > 0) {
1482 writelog(
" Species: Calculated_Moles Calculated_Mole_Fraction\n");
1483 for (k = 0; k < m_kk; k++) {
1485 writelogf(
"%15s: %10.5g %10.5g\n", nnn.c_str(), n_i_calc[k], Xmol_i_calc[k]);
1487 writelogf(
"%15s: %10.5g\n",
"Total Molar Sum", n_t_calc);
1488 writelogf(
"(iter %d) element moles bal: Goal Calculated\n", iter);
1489 for (m = 0; m < m_mm; m++) {
1490 string nnn = eNames[m];
1491 writelogf(
" %8s: %10.5g %10.5g \n", nnn.c_str(), elMoles[m], eMolesCalc[m]);
1498 bool normalStep =
true;
1503 for (m = 0; m < m_mm; m++) {
1504 if (elMoles[m] > 0.001 * elMolesTotal) {
1505 if (eMolesCalc[m] > 1000. * elMoles[m]) {
1509 if (1000 * eMolesCalc[m] < elMoles[m]) {
1515 if (DEBUG_MODE_ENABLED && ChemEquil_print_lvl > 0) {
1517 writelogf(
" NOTE: iter(%d) Doing an abnormal step due to row %d\n", iter, iM);
1523 for (im = 0; im < m_mm; im++) {
1524 m = m_orderVectorElements[im];
1527 if (elMoles[m] > 0.001 * elMolesTotal) {
1528 if (eMolesCalc[m] > 1000. * elMoles[m]) {
1532 if (1000 * eMolesCalc[m] < elMoles[m]) {
1539 if (n_t < (elMolesTotal / nAtomsMax)) {
1540 if (resid[m_mm] < 0.0) {
1543 }
else if (n_t > elMolesTotal) {
1544 if (resid[m_mm] > 0.0) {
1548 goto updateSolnVector;
1576 for (m = 0; m < m_mm; m++) {
1580 nCutoff = 1.0E-9 * n_t_calc;
1582 if (ChemEquil_print_lvl > 0) {
1583 writelog(
" Lump Sum Elements Calculation: \n");
1586 for (m = 0; m < m_mm; m++) {
1588 size_t kMSp2 =
npos;
1589 int nSpeciesWithElem = 0;
1590 for (k = 0; k < m_kk; k++) {
1591 if (n_i_calc[k] > nCutoff) {
1592 if (fabs(
nAtoms(k,m)) > 0.001) {
1596 double factor = fabs(
nAtoms(kMSp,m) /
nAtoms(kMSp2,m));
1597 for (n = 0; n < m_mm; n++) {
1598 if (fabs(factor *
nAtoms(kMSp2,n) -
nAtoms(kMSp,n)) > 1.0E-8) {
1610 if (ChemEquil_print_lvl > 0) {
1611 string nnn = eNames[m];
1612 writelogf(
" %5s %3d : %5d %5d\n",nnn.c_str(), lumpSum[m], kMSp, kMSp2);
1620 for (im = 0; im < m_mm; im++) {
1621 m = m_orderVectorElements[im];
1623 for (n = 0; n < m_mm; n++) {
1625 for (k = 0; k < m_kk; k++) {
1629 a1(m,m_mm) = eMolesCalc[m];
1630 a1(m_mm, m) = eMolesCalc[m];
1632 for (n = 0; n <= m_mm; n++) {
1638 a1(m_mm, m_mm) = 0.0;
1644 for (im = 0; im < m_mm; im++) {
1645 m = m_orderVectorElements[im];
1647 resid[m] = elMoles[m] - eMolesCalc[m];
1665 for (m = 0; m < m_mm; m++) {
1666 if (a1(m,m) < 1.0E-50) {
1668 if (ChemEquil_print_lvl > 0) {
1669 writelogf(
" NOTE: Diagonalizing the analytical Jac row %d\n", m);
1672 for (n = 0; n < m_mm; n++) {
1676 if (resid[m] > 0.0) {
1678 }
else if (resid[m] < 0.0) {
1687 resid[m_mm] = n_t - n_t_calc;
1690 if (ChemEquil_print_lvl > 0) {
1692 for (m = 0; m <= m_mm; m++) {
1694 for (n = 0; n <= m_mm; n++) {
1702 tmp = resid[m_mm] /(n_t + 1.0E-15);
1705 if (ChemEquil_print_lvl > 0) {
1706 writelogf(
"(it %d) Convergence = %g\n", iter, sum);
1724 for (m = 0; m <= m_mm; m++) {
1726 for (n = 0; n <= m_mm; n++) {
1727 tmp += fabs(a1(m,n));
1729 if (m < m_mm && tmp < 1.0E-30) {
1731 if (ChemEquil_print_lvl > 0) {
1732 writelogf(
" NOTE: Diagonalizing row %d\n", m);
1735 for (n = 0; n <= m_mm; n++) {
1743 for (n = 0; n <= m_mm; n++) {
1750 if (ChemEquil_print_lvl > 0) {
1752 for (m = 0; m <= m_mm; m++) {
1754 for (n = 0; n <= m_mm; n++) {
1782 modifiedMatrix =
false;
1783 for (m = 0; m < m_mm; m++) {
1784 size_t sameAsRow =
npos;
1785 for (
size_t im = 0; im < m; im++) {
1786 bool theSame =
true;
1787 for (n = 0; n < m_mm; n++) {
1788 if (fabs(a1(m,n) - a1(im,n)) > 1.0E-7) {
1797 if (sameAsRow !=
npos || lumpSum[m]) {
1799 if (ChemEquil_print_lvl > 0) {
1801 writelogf(
"Lump summing row %d, due to rank deficiency analysis\n", m);
1802 }
else if (sameAsRow !=
npos) {
1803 writelogf(
"Identified that rows %d and %d are the same\n", m, sameAsRow);
1807 modifiedMatrix =
true;
1808 for (n = 0; n < m_mm; n++) {
1810 a1(m,m) += fabs(a1(m,n));
1817 if (DEBUG_MODE_ENABLED && ChemEquil_print_lvl > 0 && modifiedMatrix) {
1818 writelog(
"Row Summed, MODIFIED Matrix:\n");
1819 for (m = 0; m <= m_mm; m++) {
1821 for (n = 0; n <= m_mm; n++) {
1832 addLogEntry(
"estimateEP_Brinkley:Jacobian is singular.");
1834 if (ChemEquil_print_lvl > 0) {
1835 writelog(
"Matrix is SINGULAR.ERROR\n");
1839 throw CanteraError(
"equilibrate:estimateEP_Brinkley()",
1840 "Jacobian is singular. \nTry adding more species, "
1841 "changing the elemental composition slightly, \nor removing "
1842 "unused elements.");
1852 for (m = 0; m < m_mm; m++) {
1853 if (resid[m] > 1.0) {
1854 double betat = 1.0 / resid[m];
1859 if (resid[m] < -1.0) {
1860 double betat = -1.0 / resid[m];
1867 if (ChemEquil_print_lvl > 0) {
1869 writelogf(
"(it %d) Beta = %g\n", iter, beta);
1878 for (m = 0; m < m_mm; m++) {
1879 x[m] += beta * resid[m];
1881 n_t *= exp(beta * resid[m_mm]);
1885 if (ChemEquil_print_lvl > 0) {
1886 writelogf(
"(it %d) OLD_SOLUTION NEW SOLUTION (undamped updated)\n", iter);
1887 for (m = 0; m < m_mm; m++) {
1888 string eee = eNames[m];
1889 writelogf(
" %5s %10.5g %10.5g %10.5g\n", eee.c_str(), x_old[m], x[m], resid[m]);
1891 writelogf(
" n_t %10.5g %10.5g %10.5g \n", x_old[m_mm], n_t, exp(resid[m_mm]));
1897 if (ChemEquil_print_lvl > 0) {
1902 writelogf(
" ChemEquil::estimateEP_Brinkley() SUCCESS: equilibrium found at T = %g, Pres = %g\n",
1905 writelogf(
" ChemEquil::estimateEP_Brinkley() FAILURE: equilibrium not found at T = %g, Pres = %g\n",
1919 if (fabs(elMolesGoal[
m_eloc]) > 1.0E-20) {
1926 int maxPosEloc = -1;
1927 int maxNegEloc = -1;
1928 double maxPosVal = -1.0;
1929 double maxNegVal = -1.0;
1930 if (ChemEquil_print_lvl > 0) {
1931 for (k = 0; k < m_kk; k++) {
1932 if (
nAtoms(k,m_eloc) > 0.0) {
1938 if (
nAtoms(k,m_eloc) < 0.0) {
1948 double sumPos = 0.0;
1949 double sumNeg = 0.0;
1950 for (k = 0; k < m_kk; k++) {
1951 if (
nAtoms(k,m_eloc) > 0.0) {
1954 if (
nAtoms(k,m_eloc) < 0.0) {
1960 if (sumPos >= sumNeg) {
1961 if (sumPos <= 0.0) {
1964 double factor = (elMolesGoal[
m_eloc] + sumNeg) / sumPos;
1966 if (ChemEquil_print_lvl > 0) {
1967 if (factor < 0.9999999999) {
1969 writelogf(
"adjustEloc: adjusted %s and friends from %g to %g to ensure neutrality condition\n",
1975 for (k = 0; k < m_kk; k++) {
1976 if (
nAtoms(k,m_eloc) > 0.0) {
1981 double factor = (-elMolesGoal[
m_eloc] + sumPos) / sumNeg;
1983 if (ChemEquil_print_lvl > 0) {
1984 if (factor < 0.9999999999) {
1986 writelogf(
"adjustEloc: adjusted %s and friends from %g to %g to ensure neutrality condition\n",
1992 for (k = 0; k < m_kk; k++) {
1993 if (
nAtoms(k,m_eloc) < 0.0) {