17 #include "cantera/thermo/mix_defs.h"
27 const doublereal RedlichKwongMFTP::omega_a = 4.27480233540E-01;
28 const doublereal RedlichKwongMFTP::omega_b = 8.66403499650E-02;
29 const doublereal RedlichKwongMFTP::omega_vc = 3.33333333333333E-01;
35 RedlichKwongMFTP::RedlichKwongMFTP() :
37 m_standardMixingRules(0),
50 m_partialMolarVolumes(0),
62 m_standardMixingRules(0),
75 m_partialMolarVolumes(0),
90 "Couldn't find phase named \"" +
id +
"\" in file, " + infile);
97 m_standardMixingRules(0),
110 m_partialMolarVolumes(0),
120 throw CanteraError(
"RedlichKwongMFTP::RedlichKwongMFTP()",
"Couldn't find phase named \"" +
id +
"\" in XML node");
128 m_standardMixingRules(0),
141 m_partialMolarVolumes(0),
146 std::string infile =
"co2_redlichkwong.xml";
149 infile =
"co2_redlichkwong.xml";
150 id =
"carbondioxide";
160 throw CanteraError(
"newPhase",
"Couldn't find phase named \"" +
id +
"\" in file, " + infile);
176 m_standardMixingRules(0),
189 m_partialMolarVolumes(0),
220 a_vec_Curr_ = b.a_vec_Curr_;
221 b_vec_Curr_ = b.b_vec_Curr_;
222 a_coeff_vec = b.a_coeff_vec;
224 m_pc_Species = b.m_pc_Species;
225 m_tc_Species = b.m_tc_Species;
226 m_vc_Species = b.m_vc_Species;
228 Vroot_[0] = b.Vroot_[0];
229 Vroot_[1] = b.Vroot_[1];
230 Vroot_[2] = b.Vroot_[2];
233 m_partialMolarVolumes = b.m_partialMolarVolumes;
261 return cRedlichKwongMFTP;
273 doublereal rt =
_RT();
275 doublereal h_nonideal =
hresid();
276 return (h_ideal + h_nonideal);
293 doublereal sr_nonideal =
sresid();
294 return (sr_ideal + sr_nonideal);
308 doublereal sqt = sqrt(TKelvin);
313 doublereal dadt = da_dt();
314 doublereal fac = TKelvin * dadt - 3.0 *
m_a_current / 2.0;
315 doublereal dHdT_V = (cpref + mv *
dpdT_ -
GasConstant - 1.0 / (2.0 * m_b_current * TKelvin * sqt) * log(vpb/mv) * fac
316 +1.0/(m_b_current * sqt) * log(vpb/mv) * (-0.5 * dadt));
350 double molarV = mmw / rho;
355 throw CanteraError(
" RedlichKwongMFTP::pressure()",
"setState broken down, maybe");
375 double dens = 1.0/invDens;
423 throw CanteraError(
"RedlichKwongMFTP::isothermalCompressibility() ",
432 for (
size_t k = 0; k <
m_kk; k++) {
459 double lc = std::log(c);
493 for (
int i = 0; i < sizeUA; i++) {
498 uA[1] = -
static_cast<int>(
nDim());
529 doublereal sqt = sqrt(TKelvin);
533 for (
size_t k = 0; k <
m_kk; k++) {
535 for (
size_t i = 0; i <
m_kk; i++) {
536 size_t counter = k + m_kk*i;
542 for (
size_t k = 0; k <
m_kk; k++) {
543 ac[k] = (- rt * log(pres * mv / rt)
545 + rt * b_vec_Curr_[k] / vmb
546 - 2.0 *
m_pp[k] / (m_b_current * sqt) * log(vpb/mv)
547 +
m_a_current * b_vec_Curr_[k] / (m_b_current * m_b_current * sqt) * log(vpb/mv)
548 -
m_a_current / (m_b_current * sqt) * (b_vec_Curr_[k]/vpb)
551 for (
size_t k = 0; k <
m_kk; k++) {
552 ac[k] = exp(ac[k]/rt);
572 doublereal invRT = 1.0 /
_RT();
573 for (
size_t k = 0; k <
m_kk; k++) {
583 for (
size_t k = 0; k <
m_kk; k++) {
585 mu[k] += rt*(log(xx));
590 doublereal sqt = sqrt(TKelvin);
594 for (
size_t k = 0; k <
m_kk; k++) {
596 for (
size_t i = 0; i <
m_kk; i++) {
597 size_t counter = k + m_kk*i;
604 for (
size_t k = 0; k <
m_kk; k++) {
605 mu[k] += (rt * log(pres/refP) - rt * log(pres * mv / rt)
607 + rt * b_vec_Curr_[k] / vmb
608 - 2.0 *
m_pp[k] / (m_b_current * sqt) * log(vpb/mv)
609 +
m_a_current * b_vec_Curr_[k] / (m_b_current * m_b_current * sqt) * log(vpb/mv)
610 -
m_a_current / (m_b_current * sqt) * (b_vec_Curr_[k]/vpb)
629 doublereal sqt = sqrt(TKelvin);
634 for (
size_t k = 0; k <
m_kk; k++) {
636 for (
size_t i = 0; i <
m_kk; i++) {
637 size_t counter = k + m_kk*i;
644 for (
size_t k = 0; k <
m_kk; k++) {
645 dpdni_[k] = rt/vmb + rt * b_vec_Curr_[k] / (vmb * vmb) - 2.0 *
m_pp[k] / (sqt * mv * vpb)
646 +
m_a_current * b_vec_Curr_[k]/(sqt * mv * vpb * vpb);
648 doublereal dadt = da_dt();
649 doublereal fac = TKelvin * dadt - 3.0 *
m_a_current / 2.0;
651 for (
size_t k = 0; k <
m_kk; k++) {
653 for (
size_t i = 0; i <
m_kk; i++) {
654 size_t counter = k + m_kk*i;
660 doublereal fac2 = mv + TKelvin *
dpdT_ /
dpdV_;
662 for (
size_t k = 0; k <
m_kk; k++) {
663 double hE_v = (mv *
dpdni_[k] - rt - b_vec_Curr_[k]/ (m_b_current * m_b_current * sqt) * log(vpb/mv)*fac
664 + 1.0 / (m_b_current * sqt) * log(vpb/mv) *
m_tmpV[k]
665 + b_vec_Curr_[k] / vpb / (m_b_current * sqt) * fac);
666 hbar[k] = hbar[k] + hE_v;
669 hbar[k] -= fac2 *
dpdni_[k];
680 doublereal sqt = sqrt(TKelvin);
684 for (
size_t k = 0; k <
m_kk; k++) {
686 sbar[k] += r * (- log(xx));
689 for (
size_t k = 0; k <
m_kk; k++) {
691 for (
size_t i = 0; i <
m_kk; i++) {
692 size_t counter = k + m_kk*i;
697 for (
size_t k = 0; k <
m_kk; k++) {
699 for (
size_t i = 0; i <
m_kk; i++) {
700 size_t counter = k + m_kk*i;
706 doublereal dadt = da_dt();
707 doublereal fac = dadt -
m_a_current / (2.0 * TKelvin);
712 for (
size_t k = 0; k <
m_kk; k++) {
717 +
m_pp[k]/(m_b_current * TKelvin * sqt) * log(vpb/mv)
718 - 2.0 *
m_tmpV[k]/(m_b_current * sqt) * log(vpb/mv)
719 + b_vec_Curr_[k] / (m_b_current * m_b_current * sqt) * log(vpb/mv) * fac
720 - 1.0 / (m_b_current * sqt) * b_vec_Curr_[k] / vpb * fac
726 for (
size_t k = 0; k <
m_kk; k++) {
727 sbar[k] -= -m_partialMolarVolumes[k] *
dpdT_;
750 for (
size_t k = 0; k <
m_kk; k++) {
752 for (
size_t i = 0; i <
m_kk; i++) {
753 size_t counter = k + m_kk*i;
758 for (
size_t k = 0; k <
m_kk; k++) {
760 for (
size_t i = 0; i <
m_kk; i++) {
761 size_t counter = k + m_kk*i;
767 doublereal sqt = sqrt(TKelvin);
775 for (
size_t k = 0; k <
m_kk; k++) {
777 doublereal num = (rt + rt * m_b_current/ vmb + rt * b_vec_Curr_[k] / vmb
778 + rt * m_b_current * b_vec_Curr_[k] /(vmb * vmb)
779 - 2.0 *
m_pp[k] / (sqt * vpb)
786 vbar[k] = num / denom;
796 for (
size_t i = 0; i <
m_kk; i++) {
797 for (
size_t j = 0; j <
m_kk; j++) {
798 size_t counter = i + m_kk * j;
812 for (
size_t i = 0; i <
m_kk; i++) {
813 for (
size_t j = 0; j <
m_kk; j++) {
814 size_t counter = i + m_kk * j;
829 for (
size_t i = 0; i <
m_kk; i++) {
830 for (
size_t j = 0; j <
m_kk; j++) {
831 size_t counter = i + m_kk * j;
877 doublereal pres = 0.0;
879 for (
size_t k = 0; k <
m_kk; k++) {
880 tmp = -
m_tmpV[k] + mu_RT[k];
883 }
else if (tmp > 500.0) {
886 m_pp[k] = m_p0 * exp(500.) * tmp2;
888 m_pp[k] = m_p0 * exp(tmp);
904 a_vec_Curr_.resize(
m_kk *
m_kk, 0.0);
905 b_vec_Curr_.resize(m_kk, 0.0);
907 a_coeff_vec.
resize(2, m_kk * m_kk, 0.0);
910 m_pc_Species.resize(m_kk, 0.0);
911 m_tc_Species.resize(m_kk, 0.0);
912 m_vc_Species.resize(m_kk, 0.0);
915 m_pp.resize(m_kk, 0.0);
917 m_partialMolarVolumes.resize(m_kk, 0.0);
950 std::string model = thermoNode[
"model"];
951 if (model ==
"RedlichKwong") {
953 }
else if (model ==
"RedlichKwongMFTP") {
957 "Unknown thermo model : " + model);
966 if (thermoNode.
hasChild(
"activityCoefficients")) {
975 for (
size_t i = 0; i < nC; i++) {
977 string stemp = xmlACChild.
name();
984 if (nodeName ==
"purefluidparameters") {
995 for (
size_t i = 0; i < nC; i++) {
997 string stemp = xmlACChild.
name();
1004 if (nodeName ==
"crossfluidparameters") {
1012 for (
size_t i = 0; i <
m_kk; i++) {
1013 double a0coeff = a_coeff_vec(0, i*m_kk + i);
1014 double aTcoeff = a_coeff_vec(1, i*m_kk + i);
1015 double ai = a0coeff + aTcoeff * 500.;
1016 double bi = b_vec_Curr_[i];
1017 calcCriticalConditions(ai, bi, a0coeff, aTcoeff, m_pc_Species[i], m_tc_Species[i], m_vc_Species[i]);
1027 string xname = pureFluidParam.
name();
1028 if (xname !=
"pureFluidParameters") {
1029 throw CanteraError(
"RedlichKwongMFTP::readXMLPureFluid",
1030 "Incorrect name for processing this routine: " + xname);
1037 string iName = pureFluidParam.
attrib(
"species");
1039 throw CanteraError(
"RedlichKwongMFTP::readXMLPureFluid",
"no species attribute");
1042 if (iSpecies ==
npos) {
1045 size_t counter = iSpecies +
m_kk * iSpecies;
1046 size_t nParamsExpected, nParamsFound;
1047 size_t num = pureFluidParam.
nChildren();
1048 for (
size_t iChild = 0; iChild < num; iChild++) {
1050 string stemp = xmlChild.
name();
1053 if (nodeName ==
"a_coeff") {
1055 if (iModel ==
"constant") {
1056 nParamsExpected = 1;
1057 }
else if (iModel ==
"linear_a") {
1058 nParamsExpected = 2;
1067 nParamsFound = vParams.size();
1068 if (nParamsFound != nParamsExpected) {
1069 throw CanteraError(
"RedlichKwongMFTP::readXMLPureFluid(for a_coeff" + iName +
")",
1070 "wrong number of params found");
1073 for (
size_t i = 0; i < nParamsFound; i++) {
1074 a_coeff_vec(i, counter) = vParams[i];
1076 }
else if (nodeName ==
"b_coeff") {
1078 nParamsFound = vParams.size();
1079 if (nParamsFound != 1) {
1080 throw CanteraError(
"RedlichKwongMFTP::readXMLPureFluid(for b_coeff" + iName +
")",
1081 "wrong number of params found");
1083 b_vec_Curr_[iSpecies] = vParams[0];
1091 for (
size_t i = 0; i <
m_kk; i++) {
1092 size_t icounter = i + m_kk * i;
1093 for (
size_t j = 0; j <
m_kk; j++) {
1095 size_t counter = i + m_kk * j;
1096 size_t jcounter = j + m_kk * j;
1097 for (
int n = 0; n < nParam; n++) {
1098 a_coeff_vec(n, counter) = sqrt(a_coeff_vec(n, icounter) * a_coeff_vec(n, jcounter));
1109 string xname = CrossFluidParam.
name();
1110 if (xname !=
"crossFluidParameters") {
1111 throw CanteraError(
"RedlichKwongMFTP::readXMLCrossFluid",
1112 "Incorrect name for processing this routine: " + xname);
1119 string iName = CrossFluidParam.
attrib(
"species1");
1121 throw CanteraError(
"RedlichKwongMFTP::readXMLCrossFluid",
"no species1 attribute");
1124 if (iSpecies ==
npos) {
1127 string jName = CrossFluidParam.
attrib(
"species2");
1129 throw CanteraError(
"RedlichKwongMFTP::readXMLCrossFluid",
"no species2 attribute");
1132 if (jSpecies ==
npos) {
1136 size_t counter = iSpecies +
m_kk * jSpecies;
1137 size_t counter0 = jSpecies +
m_kk * iSpecies;
1138 size_t nParamsExpected, nParamsFound;
1139 size_t num = CrossFluidParam.
nChildren();
1140 for (
size_t iChild = 0; iChild < num; iChild++) {
1142 string stemp = xmlChild.
name();
1145 if (nodeName ==
"a_coeff") {
1147 if (iModel ==
"constant") {
1148 nParamsExpected = 1;
1149 }
else if (iModel ==
"linear_a") {
1150 nParamsExpected = 2;
1159 nParamsFound = vParams.size();
1160 if (nParamsFound != nParamsExpected) {
1161 throw CanteraError(
"RedlichKwongMFTP::readXMLCrossFluid(for a_coeff" + iName +
")",
1162 "wrong number of params found");
1165 for (
size_t i = 0; i < nParamsFound; i++) {
1166 a_coeff_vec(i, counter) = vParams[i];
1167 a_coeff_vec(i, counter0) = vParams[i];
1176 std::string model = thermoNode[
"model"];
1193 doublereal molarV = mmw / rho;
1195 doublereal zz =
z();
1196 doublereal dadt = da_dt();
1198 doublereal sqT = sqrt(T);
1217 doublereal molarV = mmw / rho;
1219 doublereal zz =
z();
1220 doublereal dadt = da_dt();
1222 doublereal sqT = sqrt(T);
1223 doublereal fac = T * dadt - 3.0 *
m_a_current / (2.0);
1249 doublereal pres = presGuess;
1256 bool foundLiq =
false;
1260 int nsol = NicholsSolve(TKelvin, pres, atmp, btmp, Vroot);
1265 if (nsol == 1 || nsol == 2) {
1275 }
while ((m < 100) && (!foundLiq));
1320 double densBase = 0.0;
1321 if (rhoguess == -1.0) {
1322 if (phaseRequested != FLUID_GAS) {
1323 if (TKelvin > tcrit) {
1324 rhoguess = presPa * mmw / (
GasConstant * TKelvin);
1326 if (phaseRequested == FLUID_GAS || phaseRequested == FLUID_SUPERCRIT) {
1327 rhoguess = presPa * mmw / (
GasConstant * TKelvin);
1328 }
else if (phaseRequested >= FLUID_LIQUID_0) {
1330 rhoguess = mmw / lqvol;
1338 rhoguess = presPa * mmw / (
GasConstant * TKelvin);
1344 doublereal volguess = mmw / rhoguess;
1347 doublereal molarVolLast = Vroot_[0];
1349 if (phaseRequested >= FLUID_LIQUID_0) {
1350 molarVolLast = Vroot_[0];
1351 }
else if (phaseRequested == FLUID_GAS || phaseRequested == FLUID_SUPERCRIT) {
1352 molarVolLast = Vroot_[2];
1354 if (volguess > Vroot_[1]) {
1355 molarVolLast = Vroot_[2];
1357 molarVolLast = Vroot_[0];
1360 }
else if (NSolns_ == 1) {
1361 if (phaseRequested == FLUID_GAS || phaseRequested == FLUID_SUPERCRIT || phaseRequested == FLUID_UNDEFINED) {
1362 molarVolLast = Vroot_[0];
1368 }
else if (NSolns_ == -1) {
1369 if (phaseRequested >= FLUID_LIQUID_0 || phaseRequested == FLUID_UNDEFINED || phaseRequested == FLUID_SUPERCRIT) {
1370 molarVolLast = Vroot_[0];
1371 }
else if (TKelvin > tcrit) {
1372 molarVolLast = Vroot_[0];
1379 molarVolLast = Vroot_[0];
1383 densBase = mmw / molarVolLast;
1398 double vmax = Vroot_[1];
1399 double vmin = Vroot_[0];
1402 rf.
setTol(1.0E-5, 1.0E-10);
1405 double vbest = 0.5 * (Vroot_[0]+Vroot_[1]);
1406 double funcNeeded = 0.0;
1408 int status = rf.
solve(vmin, vmax, 100, funcNeeded, &vbest);
1410 throw CanteraError(
" RedlichKwongMFTP::densSpinodalLiquid() ",
"didn't converge");
1413 doublereal rho = mmw / vbest;
1428 double vmax = Vroot_[2];
1429 double vmin = Vroot_[1];
1432 rf.
setTol(1.0E-5, 1.0E-10);
1435 double vbest = 0.5 * (Vroot_[1]+Vroot_[2]);
1436 double funcNeeded = 0.0;
1438 int status = rf.
solve(vmin, vmax, 100, funcNeeded, &vbest);
1440 throw CanteraError(
" RedlichKwongMFTP::densSpinodalGas() ",
"didn't converge");
1443 doublereal rho = mmw / vbest;
1458 doublereal sqt = sqrt(TKelvin);
1477 doublereal sqt = sqrt(TKelvin);
1483 doublereal dpdv = (-
GasConstant * TKelvin / (vmb * vmb)
1484 +
m_a_current * (2 * molarVol + m_b_current) / (sqt * molarVol * molarVol * vpb * vpb));
1497 doublereal sqt = sqrt(TKelvin);
1500 doublereal dadt = da_dt();
1501 doublereal fac = dadt -
m_a_current/(2.0 * TKelvin);
1506 void RedlichKwongMFTP::updateMixingExpressions()
1515 for (
size_t i = 0; i <
m_kk; i++) {
1516 for (
size_t j = 0; j <
m_kk; j++) {
1517 size_t counter = i * m_kk + j;
1518 a_vec_Curr_[counter] = a_coeff_vec(0,counter) + a_coeff_vec(1,counter) * temp;
1525 for (
size_t i = 0; i <
m_kk; i++) {
1527 for (
size_t j = 0; j <
m_kk; j++) {
1538 for (
size_t i = 0; i <
m_kk; i++) {
1540 for (
size_t j = 0; j <
m_kk; j++) {
1541 size_t counter = i * m_kk + j;
1542 doublereal a_vec_Curr = a_coeff_vec(0,counter) + a_coeff_vec(1,counter) * temp;
1547 for (
size_t i = 0; i <
m_kk; i++) {
1549 for (
size_t j = 0; j <
m_kk; j++) {
1550 size_t counter = i * m_kk + j;
1551 doublereal a_vec_Curr = a_coeff_vec(0,counter);
1558 doublereal RedlichKwongMFTP::da_dt()
const
1561 doublereal dadT = 0.0;
1563 for (
size_t i = 0; i <
m_kk; i++) {
1564 for (
size_t j = 0; j <
m_kk; j++) {
1565 size_t counter = i * m_kk + j;
1573 void RedlichKwongMFTP::calcCriticalConditions(doublereal a, doublereal b, doublereal a0_coeff, doublereal aT_coeff,
1574 doublereal& pc, doublereal& tc, doublereal& vc)
const
1593 doublereal sqrttc, f, dfdt, deltatc;
1600 for (
int j = 0; j < 10; j++) {
1604 deltatc = - f / dfdt;
1607 if (deltatc > 0.1) {
1608 throw CanteraError(
"RedlichKwongMFTP::calcCriticalConditions",
"didn't converge");
1628 int RedlichKwongMFTP::NicholsSolve(
double TKelvin,
double pres, doublereal a, doublereal b,
1629 doublereal Vroot[3])
const
1635 bool lotsOfNumError =
false;
1636 doublereal Vturn[2];
1637 if (TKelvin <= 0.0) {
1638 throw CanteraError(
"RedlichKwongMFTP::NicholsSolve()",
"neg temperature");
1643 doublereal an = 1.0;
1645 doublereal sqt = sqrt(TKelvin);
1646 doublereal cn = - (
GasConstant * TKelvin * b / pres - a/(pres * sqt) + b * b);
1647 doublereal dn = - (a * b / (pres * sqt));
1651 double tc = pow(tmp, pp);
1655 doublereal xN = - bn /(3 * an);
1659 doublereal delta2 = (bn * bn - 3 * an * cn) / (9 * an * an);
1660 doublereal delta = 0.0;
1663 doublereal ratio1 = 3.0 * an * cn / (bn * bn);
1664 doublereal ratio2 = pres * b / (
GasConstant * TKelvin);
1665 if (fabs(ratio1) < 1.0E-7) {
1668 if (fabs(ratio2) < 1.0E-5 && fabs(ratio3) < 1.0E-5) {
1670 for (
int i = 0; i < 10; i++) {
1671 doublereal znew = z / (z - ratio2) - ratio3 / (z + ratio1);
1672 doublereal deltaz = znew -
z;
1674 if (fabs(deltaz) < 1.0E-14) {
1691 for (
int i = 0; i < 90; i++) {
1692 V[n++] = 0.030 + 0.005 * i;
1694 double p1, presCalc;
1695 for (
int i = 0; i < n; i++) {
1696 p1 =
dpdVCalc(TKelvin, V[i], presCalc);
1697 printf(
" %13.5g %13.5g %13.5g \n", V[i], presCalc , p1);
1701 double h2 = 4. * an * an * delta2 * delta2 * delta2;
1702 if (delta2 == 0.0) {
1706 }
else if (delta2 < 0.0) {
1711 delta = sqrt(delta2);
1712 Vturn[0] = xN - delta;
1713 Vturn[1] = xN + delta;
1716 double p1 =
dpdVCalc(TKelvin, Vturn[0], presCalc);
1718 double p2 =
dpdVCalc(TKelvin, Vturn[1], presCalc);
1720 printf(
"p1 = %g p2 = %g \n", p1, p2);
1721 p1 =
dpdVCalc(TKelvin, 0.9*Vturn[0], presCalc);
1722 printf(
"0.9 p1 = %g \n", p1);
1726 doublereal h = 2.0 * an * delta * delta2;
1728 doublereal yN = 2.0 * bn * bn * bn / (27.0 * an * an) - bn * cn / (3.0 * an) + dn;
1730 doublereal desc = yN * yN - h2;
1732 if (fabs(fabs(h) - fabs(yN)) < 1.0E-10) {
1735 printf(
"NicholsSolve(): numerical issues\n");
1736 throw CanteraError(
"NicholsSolve()",
"numerical issues");
1743 }
else if (desc == 0.0) {
1753 }
else if (desc > 0.0) {
1761 doublereal tmpD = sqrt(desc);
1762 doublereal tmp1 = (- yN + tmpD) / (2.0 * an);
1763 doublereal sgn1 = 1.0;
1768 doublereal tmp2 = (- yN - tmpD) / (2.0 * an);
1769 doublereal sgn2 = 1.0;
1774 doublereal p1 = pow(tmp1, 1./3.);
1775 doublereal p2 = pow(tmp2, 1./3.);
1777 doublereal alpha = xN + sgn1 * p1 + sgn2 * p2;
1782 double tmp = an * Vroot[0] * Vroot[0] * Vroot[0] + bn * Vroot[0] * Vroot[0] + cn * Vroot[0] + dn;
1783 if (fabs(tmp) > 1.0E-4) {
1784 lotsOfNumError =
true;
1787 }
else if (desc < 0.0) {
1788 doublereal tmp = - yN/h;
1790 doublereal val = acos(tmp);
1791 doublereal theta = val / 3.0;
1794 doublereal alpha = xN + 2. * delta * cos(theta);
1796 doublereal beta = xN + 2. * delta * cos(theta + oo);
1798 doublereal gamma = xN + 2. * delta * cos(theta + 2.0 * oo);
1805 for (
int i = 0; i < 3; i++) {
1806 double tmp = an * Vroot[i] * Vroot[i] * Vroot[i] + bn * Vroot[i] * Vroot[i] + cn * Vroot[i] + dn;
1807 if (fabs(tmp) > 1.0E-4) {
1808 lotsOfNumError =
true;
1809 for (
int j = 0; j < 3; j++) {
1811 if (fabs(Vroot[i] - Vroot[j]) < 1.0E-4 * (fabs(Vroot[i]) + fabs(Vroot[j]))) {
1812 writelog(
"RedlichKwongMFTP::NicholsSolve(T = " +
fp2str(TKelvin) +
", p = " +
1813 fp2str(pres) +
"): WARNING roots have merged: " +
1821 }
else if (desc == 0.0) {
1822 if (yN == 0.0 && h == 0.0) {
1829 double tmp = pow(yN/(2*an), 1./3.);
1830 if (fabs(tmp - delta) > 1.0E-9) {
1831 throw CanteraError(
"RedlichKwongMFTP::NicholsSolve()",
"unexpected");
1833 Vroot[1] = xN + delta;
1834 Vroot[0] = xN - 2.0*delta;
1836 double tmp = pow(yN/(2*an), 1./3.);
1837 if (fabs(tmp - delta) > 1.0E-9) {
1838 throw CanteraError(
"RedlichKwongMFTP::NicholsSolve()",
"unexpected");
1841 Vroot[0] = xN + delta;
1842 Vroot[1] = xN - 2.0*delta;
1845 for (
int i = 0; i < 2; i++) {
1846 double tmp = an * Vroot[i] * Vroot[i] * Vroot[i] + bn * Vroot[i] * Vroot[i] + cn * Vroot[i] + dn;
1847 if (fabs(tmp) > 1.0E-4) {
1848 lotsOfNumError =
true;
1857 for (
int i = 0; i < nSolnValues; i++) {
1858 for (
int n = 0; n < 20; n++) {
1859 res = an * Vroot[i] * Vroot[i] * Vroot[i] + bn * Vroot[i] * Vroot[i] + cn * Vroot[i] + dn;
1860 if (fabs(res) < 1.0E-14) {
1863 dresdV = 3.0 * an * Vroot[i] * Vroot[i] + 2.0 * bn * Vroot[i] + cn;
1864 double del = - res / dresdV;
1867 if (fabs(del) / (fabs(Vroot[i]) + fabs(del)) < 1.0E-14) {
1870 double res2 = an * Vroot[i] * Vroot[i] * Vroot[i] + bn * Vroot[i] * Vroot[i] + cn * Vroot[i] + dn;
1871 if (fabs(res2) < fabs(res)) {
1875 Vroot[i] += 0.1 * del;
1878 if ((fabs(res) > 1.0E-14) && (fabs(res) > 1.0E-14 * fabs(dresdV) * fabs(Vroot[i]))) {
1879 writelog(
"RedlichKwongMFTP::NicholsSolve(T = " +
fp2str(TKelvin) +
", p = " +
1880 fp2str(pres) +
"): WARNING root didn't converge V = " +
fp2str(Vroot[i]));
1885 if (nSolnValues == 1) {
1887 if (Vroot[0] < vc) {
1891 if (Vroot[0] < xN) {
1897 if (nSolnValues == 2) {