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;
31 RedlichKwongMFTP::RedlichKwongMFTP() :
33 m_standardMixingRules(0),
46 m_partialMolarVolumes(0),
58 m_standardMixingRules(0),
71 m_partialMolarVolumes(0),
86 "Couldn't find phase named \"" + id_ +
"\" in file, " + infile);
93 m_standardMixingRules(0),
106 m_partialMolarVolumes(0),
116 throw CanteraError(
"RedlichKwongMFTP::RedlichKwongMFTP()",
"Couldn't find phase named \"" + id_ +
"\" in XML node");
123 m_standardMixingRules(0),
136 m_partialMolarVolumes(0),
141 std::string infile =
"co2_redlichkwong.xml";
144 infile =
"co2_redlichkwong.xml";
145 id_ =
"carbondioxide";
155 throw CanteraError(
"newPhase",
"Couldn't find phase named \"" + id_ +
"\" in file, " + infile);
162 m_standardMixingRules(0),
175 m_partialMolarVolumes(0),
199 a_vec_Curr_ = b.a_vec_Curr_;
200 b_vec_Curr_ = b.b_vec_Curr_;
201 a_coeff_vec = b.a_coeff_vec;
203 m_pc_Species = b.m_pc_Species;
204 m_tc_Species = b.m_tc_Species;
205 m_vc_Species = b.m_vc_Species;
207 Vroot_[0] = b.Vroot_[0];
208 Vroot_[1] = b.Vroot_[1];
209 Vroot_[2] = b.Vroot_[2];
212 m_partialMolarVolumes = b.m_partialMolarVolumes;
227 return cRedlichKwongMFTP;
237 doublereal rt =
_RT();
239 doublereal h_nonideal =
hresid();
240 return h_ideal + h_nonideal;
255 doublereal sr_nonideal =
sresid();
256 return sr_ideal + sr_nonideal;
268 doublereal sqt = sqrt(TKelvin);
273 doublereal dadt = da_dt();
274 doublereal fac = TKelvin * dadt - 3.0 *
m_a_current / 2.0;
275 doublereal dHdT_V = (cpref + mv *
dpdT_ -
GasConstant - 1.0 / (2.0 * m_b_current * TKelvin * sqt) * log(vpb/mv) * fac
276 +1.0/(m_b_current * sqt) * log(vpb/mv) * (-0.5 * dadt));
295 double molarV = mmw / rho;
300 throw CanteraError(
" RedlichKwongMFTP::pressure()",
"setState broken down, maybe");
319 double dens = 1.0/invDens;
362 throw CanteraError(
"RedlichKwongMFTP::isothermalCompressibility() ",
370 for (
size_t k = 0; k <
m_kk; k++) {
391 for (
int i = 0; i < sizeUA; i++) {
396 uA[1] = -
static_cast<int>(
nDim());
419 doublereal sqt = sqrt(TKelvin);
423 for (
size_t k = 0; k <
m_kk; k++) {
425 for (
size_t i = 0; i <
m_kk; i++) {
426 size_t counter = k + m_kk*i;
432 for (
size_t k = 0; k <
m_kk; k++) {
433 ac[k] = (- rt * log(pres * mv / rt)
435 + rt * b_vec_Curr_[k] / vmb
436 - 2.0 *
m_pp[k] / (m_b_current * sqt) * log(vpb/mv)
437 +
m_a_current * b_vec_Curr_[k] / (m_b_current * m_b_current * sqt) * log(vpb/mv)
438 -
m_a_current / (m_b_current * sqt) * (b_vec_Curr_[k]/vpb)
441 for (
size_t k = 0; k <
m_kk; k++) {
442 ac[k] = exp(ac[k]/rt);
453 doublereal invRT = 1.0 /
_RT();
454 for (
size_t k = 0; k <
m_kk; k++) {
464 for (
size_t k = 0; k <
m_kk; k++) {
466 mu[k] += rt*(log(xx));
471 doublereal sqt = sqrt(TKelvin);
475 for (
size_t k = 0; k <
m_kk; k++) {
477 for (
size_t i = 0; i <
m_kk; i++) {
478 size_t counter = k + m_kk*i;
485 for (
size_t k = 0; k <
m_kk; k++) {
486 mu[k] += (rt * log(pres/refP) - rt * log(pres * mv / rt)
488 + rt * b_vec_Curr_[k] / vmb
489 - 2.0 *
m_pp[k] / (m_b_current * sqt) * log(vpb/mv)
490 +
m_a_current * b_vec_Curr_[k] / (m_b_current * m_b_current * sqt) * log(vpb/mv)
491 -
m_a_current / (m_b_current * sqt) * (b_vec_Curr_[k]/vpb)
510 doublereal sqt = sqrt(TKelvin);
515 for (
size_t k = 0; k <
m_kk; k++) {
517 for (
size_t i = 0; i <
m_kk; i++) {
518 size_t counter = k + m_kk*i;
525 for (
size_t k = 0; k <
m_kk; k++) {
526 dpdni_[k] = rt/vmb + rt * b_vec_Curr_[k] / (vmb * vmb) - 2.0 *
m_pp[k] / (sqt * mv * vpb)
527 +
m_a_current * b_vec_Curr_[k]/(sqt * mv * vpb * vpb);
529 doublereal dadt = da_dt();
530 doublereal fac = TKelvin * dadt - 3.0 *
m_a_current / 2.0;
532 for (
size_t k = 0; k <
m_kk; k++) {
534 for (
size_t i = 0; i <
m_kk; i++) {
535 size_t counter = k + m_kk*i;
541 doublereal fac2 = mv + TKelvin *
dpdT_ /
dpdV_;
543 for (
size_t k = 0; k <
m_kk; k++) {
544 double hE_v = (mv *
dpdni_[k] - rt - b_vec_Curr_[k]/ (m_b_current * m_b_current * sqt) * log(vpb/mv)*fac
545 + 1.0 / (m_b_current * sqt) * log(vpb/mv) *
m_tmpV[k]
546 + b_vec_Curr_[k] / vpb / (m_b_current * sqt) * fac);
547 hbar[k] = hbar[k] + hE_v;
550 hbar[k] -= fac2 *
dpdni_[k];
561 doublereal sqt = sqrt(TKelvin);
565 for (
size_t k = 0; k <
m_kk; k++) {
567 sbar[k] += r * (- log(xx));
570 for (
size_t k = 0; k <
m_kk; k++) {
572 for (
size_t i = 0; i <
m_kk; i++) {
573 size_t counter = k + m_kk*i;
578 for (
size_t k = 0; k <
m_kk; k++) {
580 for (
size_t i = 0; i <
m_kk; i++) {
581 size_t counter = k + m_kk*i;
587 doublereal dadt = da_dt();
588 doublereal fac = dadt -
m_a_current / (2.0 * TKelvin);
593 for (
size_t k = 0; k <
m_kk; k++) {
598 +
m_pp[k]/(m_b_current * TKelvin * sqt) * log(vpb/mv)
599 - 2.0 *
m_tmpV[k]/(m_b_current * sqt) * log(vpb/mv)
600 + b_vec_Curr_[k] / (m_b_current * m_b_current * sqt) * log(vpb/mv) * fac
601 - 1.0 / (m_b_current * sqt) * b_vec_Curr_[k] / vpb * fac
607 for (
size_t k = 0; k <
m_kk; k++) {
608 sbar[k] -= -m_partialMolarVolumes[k] *
dpdT_;
631 for (
size_t k = 0; k <
m_kk; k++) {
633 for (
size_t i = 0; i <
m_kk; i++) {
634 size_t counter = k + m_kk*i;
639 for (
size_t k = 0; k <
m_kk; k++) {
641 for (
size_t i = 0; i <
m_kk; i++) {
642 size_t counter = k + m_kk*i;
648 doublereal sqt = sqrt(TKelvin);
656 for (
size_t k = 0; k <
m_kk; k++) {
658 doublereal num = (rt + rt * m_b_current/ vmb + rt * b_vec_Curr_[k] / vmb
659 + rt * m_b_current * b_vec_Curr_[k] /(vmb * vmb)
660 - 2.0 *
m_pp[k] / (sqt * vpb)
667 vbar[k] = num / denom;
677 for (
size_t i = 0; i <
m_kk; i++) {
678 for (
size_t j = 0; j <
m_kk; j++) {
679 size_t counter = i + m_kk * j;
693 for (
size_t i = 0; i <
m_kk; i++) {
694 for (
size_t j = 0; j <
m_kk; j++) {
695 size_t counter = i + m_kk * j;
710 for (
size_t i = 0; i <
m_kk; i++) {
711 for (
size_t j = 0; j <
m_kk; j++) {
712 size_t counter = i + m_kk * j;
745 doublereal pres = 0.0;
747 for (
size_t k = 0; k <
m_kk; k++) {
748 tmp = -
m_tmpV[k] + mu_RT[k];
751 }
else if (tmp > 500.0) {
754 m_pp[k] = m_p0 * exp(500.) * tmp2;
756 m_pp[k] = m_p0 * exp(tmp);
768 a_vec_Curr_.resize(
m_kk *
m_kk, 0.0);
769 b_vec_Curr_.resize(m_kk, 0.0);
771 a_coeff_vec.
resize(2, m_kk * m_kk, 0.0);
774 m_pc_Species.resize(m_kk, 0.0);
775 m_tc_Species.resize(m_kk, 0.0);
776 m_vc_Species.resize(m_kk, 0.0);
779 m_pp.resize(m_kk, 0.0);
781 m_partialMolarVolumes.resize(m_kk, 0.0);
797 std::string model = thermoNode[
"model"];
798 if (model ==
"RedlichKwong") {
800 }
else if (model ==
"RedlichKwongMFTP") {
804 "Unknown thermo model : " + model);
813 if (thermoNode.
hasChild(
"activityCoefficients")) {
822 for (
size_t i = 0; i < nC; i++) {
824 string stemp = xmlACChild.
name();
831 if (nodeName ==
"purefluidparameters") {
842 for (
size_t i = 0; i < nC; i++) {
844 string stemp = xmlACChild.
name();
851 if (nodeName ==
"crossfluidparameters") {
859 for (
size_t i = 0; i <
m_kk; i++) {
860 double a0coeff = a_coeff_vec(0, i*m_kk + i);
861 double aTcoeff = a_coeff_vec(1, i*m_kk + i);
862 double ai = a0coeff + aTcoeff * 500.;
863 double bi = b_vec_Curr_[i];
864 calcCriticalConditions(ai, bi, a0coeff, aTcoeff, m_pc_Species[i], m_tc_Species[i], m_vc_Species[i]);
873 string xname = pureFluidParam.
name();
874 if (xname !=
"pureFluidParameters") {
875 throw CanteraError(
"RedlichKwongMFTP::readXMLPureFluid",
876 "Incorrect name for processing this routine: " + xname);
883 string iName = pureFluidParam.
attrib(
"species");
885 throw CanteraError(
"RedlichKwongMFTP::readXMLPureFluid",
"no species attribute");
888 if (iSpecies ==
npos) {
891 size_t counter = iSpecies +
m_kk * iSpecies;
892 size_t nParamsExpected, nParamsFound;
894 for (
size_t iChild = 0; iChild < num; iChild++) {
896 string stemp = xmlChild.
name();
899 if (nodeName ==
"a_coeff") {
901 if (iModel ==
"constant") {
903 }
else if (iModel ==
"linear_a") {
913 nParamsFound = vParams.size();
914 if (nParamsFound != nParamsExpected) {
915 throw CanteraError(
"RedlichKwongMFTP::readXMLPureFluid(for a_coeff" + iName +
")",
916 "wrong number of params found");
919 for (
size_t i = 0; i < nParamsFound; i++) {
920 a_coeff_vec(i, counter) = vParams[i];
922 }
else if (nodeName ==
"b_coeff") {
924 nParamsFound = vParams.size();
925 if (nParamsFound != 1) {
926 throw CanteraError(
"RedlichKwongMFTP::readXMLPureFluid(for b_coeff" + iName +
")",
927 "wrong number of params found");
929 b_vec_Curr_[iSpecies] = vParams[0];
937 for (
size_t i = 0; i <
m_kk; i++) {
938 size_t icounter = i + m_kk * i;
939 for (
size_t j = 0; j <
m_kk; j++) {
941 size_t counter = i + m_kk * j;
942 size_t jcounter = j + m_kk * j;
943 for (
int n = 0; n < nParam; n++) {
944 a_coeff_vec(n, counter) = sqrt(a_coeff_vec(n, icounter) * a_coeff_vec(n, jcounter));
954 string xname = CrossFluidParam.
name();
955 if (xname !=
"crossFluidParameters") {
956 throw CanteraError(
"RedlichKwongMFTP::readXMLCrossFluid",
957 "Incorrect name for processing this routine: " + xname);
964 string iName = CrossFluidParam.
attrib(
"species1");
966 throw CanteraError(
"RedlichKwongMFTP::readXMLCrossFluid",
"no species1 attribute");
969 if (iSpecies ==
npos) {
972 string jName = CrossFluidParam.
attrib(
"species2");
974 throw CanteraError(
"RedlichKwongMFTP::readXMLCrossFluid",
"no species2 attribute");
977 if (jSpecies ==
npos) {
981 size_t counter = iSpecies +
m_kk * jSpecies;
982 size_t counter0 = jSpecies +
m_kk * iSpecies;
983 size_t nParamsExpected, nParamsFound;
984 size_t num = CrossFluidParam.
nChildren();
985 for (
size_t iChild = 0; iChild < num; iChild++) {
987 string stemp = xmlChild.
name();
990 if (nodeName ==
"a_coeff") {
992 if (iModel ==
"constant") {
994 }
else if (iModel ==
"linear_a") {
1004 nParamsFound = vParams.size();
1005 if (nParamsFound != nParamsExpected) {
1006 throw CanteraError(
"RedlichKwongMFTP::readXMLCrossFluid(for a_coeff" + iName +
")",
1007 "wrong number of params found");
1010 for (
size_t i = 0; i < nParamsFound; i++) {
1011 a_coeff_vec(i, counter) = vParams[i];
1012 a_coeff_vec(i, counter0) = vParams[i];
1021 std::string model = thermoNode[
"model"];
1029 doublereal molarV = mmw / rho;
1031 doublereal zz =
z();
1032 doublereal dadt = da_dt();
1034 doublereal sqT = sqrt(T);
1045 doublereal molarV = mmw / rho;
1047 doublereal zz =
z();
1048 doublereal dadt = da_dt();
1050 doublereal sqT = sqrt(T);
1051 doublereal fac = T * dadt - 3.0 *
m_a_current / (2.0);
1062 doublereal pres = presGuess;
1069 bool foundLiq =
false;
1073 int nsol =
NicholsSolve(TKelvin, pres, atmp, btmp, Vroot);
1078 if (nsol == 1 || nsol == 2) {
1088 }
while ((m < 100) && (!foundLiq));
1109 if (rhoguess == -1.0) {
1110 if (phaseRequested != FLUID_GAS) {
1111 if (TKelvin > tcrit) {
1112 rhoguess = presPa * mmw / (
GasConstant * TKelvin);
1114 if (phaseRequested == FLUID_GAS || phaseRequested == FLUID_SUPERCRIT) {
1115 rhoguess = presPa * mmw / (
GasConstant * TKelvin);
1116 }
else if (phaseRequested >= FLUID_LIQUID_0) {
1118 rhoguess = mmw / lqvol;
1126 rhoguess = presPa * mmw / (
GasConstant * TKelvin);
1132 doublereal volguess = mmw / rhoguess;
1135 doublereal molarVolLast = Vroot_[0];
1137 if (phaseRequested >= FLUID_LIQUID_0) {
1138 molarVolLast = Vroot_[0];
1139 }
else if (phaseRequested == FLUID_GAS || phaseRequested == FLUID_SUPERCRIT) {
1140 molarVolLast = Vroot_[2];
1142 if (volguess > Vroot_[1]) {
1143 molarVolLast = Vroot_[2];
1145 molarVolLast = Vroot_[0];
1148 }
else if (NSolns_ == 1) {
1149 if (phaseRequested == FLUID_GAS || phaseRequested == FLUID_SUPERCRIT || phaseRequested == FLUID_UNDEFINED) {
1150 molarVolLast = Vroot_[0];
1156 }
else if (NSolns_ == -1) {
1157 if (phaseRequested >= FLUID_LIQUID_0 || phaseRequested == FLUID_UNDEFINED || phaseRequested == FLUID_SUPERCRIT) {
1158 molarVolLast = Vroot_[0];
1159 }
else if (TKelvin > tcrit) {
1160 molarVolLast = Vroot_[0];
1167 molarVolLast = Vroot_[0];
1171 return mmw / molarVolLast;
1179 double vmax = Vroot_[1];
1180 double vmin = Vroot_[0];
1183 rf.
setTol(1.0E-5, 1.0E-10);
1186 double vbest = 0.5 * (Vroot_[0]+Vroot_[1]);
1187 double funcNeeded = 0.0;
1189 int status = rf.
solve(vmin, vmax, 100, funcNeeded, &vbest);
1191 throw CanteraError(
" RedlichKwongMFTP::densSpinodalLiquid() ",
"didn't converge");
1202 double vmax = Vroot_[2];
1203 double vmin = Vroot_[1];
1206 rf.
setTol(1.0E-5, 1.0E-10);
1209 double vbest = 0.5 * (Vroot_[1]+Vroot_[2]);
1210 double funcNeeded = 0.0;
1212 int status = rf.
solve(vmin, vmax, 100, funcNeeded, &vbest);
1214 throw CanteraError(
" RedlichKwongMFTP::densSpinodalGas() ",
"didn't converge");
1222 doublereal sqt = sqrt(TKelvin);
1230 doublereal sqt = sqrt(TKelvin);
1236 doublereal dpdv = (-
GasConstant * TKelvin / (vmb * vmb)
1237 +
m_a_current * (2 * molarVol + m_b_current) / (sqt * molarVol * molarVol * vpb * vpb));
1249 doublereal sqt = sqrt(TKelvin);
1252 doublereal dadt = da_dt();
1253 doublereal fac = dadt -
m_a_current/(2.0 * TKelvin);
1258 void RedlichKwongMFTP::updateMixingExpressions()
1267 for (
size_t i = 0; i <
m_kk; i++) {
1268 for (
size_t j = 0; j <
m_kk; j++) {
1269 size_t counter = i * m_kk + j;
1270 a_vec_Curr_[counter] = a_coeff_vec(0,counter) + a_coeff_vec(1,counter) * temp;
1277 for (
size_t i = 0; i <
m_kk; i++) {
1279 for (
size_t j = 0; j <
m_kk; j++) {
1290 for (
size_t i = 0; i <
m_kk; i++) {
1292 for (
size_t j = 0; j <
m_kk; j++) {
1293 size_t counter = i * m_kk + j;
1294 doublereal a_vec_Curr = a_coeff_vec(0,counter) + a_coeff_vec(1,counter) * temp;
1299 for (
size_t i = 0; i <
m_kk; i++) {
1301 for (
size_t j = 0; j <
m_kk; j++) {
1302 size_t counter = i * m_kk + j;
1303 doublereal a_vec_Curr = a_coeff_vec(0,counter);
1310 doublereal RedlichKwongMFTP::da_dt()
const
1313 doublereal dadT = 0.0;
1315 for (
size_t i = 0; i <
m_kk; i++) {
1316 for (
size_t j = 0; j <
m_kk; j++) {
1317 size_t counter = i * m_kk + j;
1325 void RedlichKwongMFTP::calcCriticalConditions(doublereal a, doublereal b, doublereal a0_coeff, doublereal aT_coeff,
1326 doublereal& pc, doublereal& tc, doublereal& vc)
const
1345 doublereal sqrttc, f, dfdt, deltatc;
1352 for (
int j = 0; j < 10; j++) {
1356 deltatc = - f / dfdt;
1359 if (deltatc > 0.1) {
1360 throw CanteraError(
"RedlichKwongMFTP::calcCriticalConditions",
"didn't converge");
1369 doublereal Vroot[3])
const
1375 bool lotsOfNumError =
false;
1376 doublereal Vturn[2];
1377 if (TKelvin <= 0.0) {
1378 throw CanteraError(
"RedlichKwongMFTP::NicholsSolve()",
"neg temperature");
1383 doublereal an = 1.0;
1385 doublereal sqt = sqrt(TKelvin);
1386 doublereal cn = - (
GasConstant * TKelvin * b / pres - a/(pres * sqt) + b * b);
1387 doublereal dn = - (a * b / (pres * sqt));
1391 double tc = pow(tmp, pp);
1395 doublereal xN = - bn /(3 * an);
1399 doublereal delta2 = (bn * bn - 3 * an * cn) / (9 * an * an);
1400 doublereal delta = 0.0;
1403 doublereal ratio1 = 3.0 * an * cn / (bn * bn);
1404 doublereal ratio2 = pres * b / (
GasConstant * TKelvin);
1405 if (fabs(ratio1) < 1.0E-7) {
1408 if (fabs(ratio2) < 1.0E-5 && fabs(ratio3) < 1.0E-5) {
1409 doublereal zz = 1.0;
1410 for (
int i = 0; i < 10; i++) {
1411 doublereal znew = zz / (zz - ratio2) - ratio3 / (zz + ratio1);
1412 doublereal deltaz = znew - zz;
1414 if (fabs(deltaz) < 1.0E-14) {
1431 for (
int i = 0; i < 90; i++) {
1432 V[n++] = 0.030 + 0.005 * i;
1434 double p1, presCalc;
1435 for (
int i = 0; i < n; i++) {
1436 p1 =
dpdVCalc(TKelvin, V[i], presCalc);
1437 printf(
" %13.5g %13.5g %13.5g \n", V[i], presCalc , p1);
1441 double h2 = 4. * an * an * delta2 * delta2 * delta2;
1442 if (delta2 == 0.0) {
1446 }
else if (delta2 < 0.0) {
1451 delta = sqrt(delta2);
1452 Vturn[0] = xN - delta;
1453 Vturn[1] = xN + delta;
1456 double p1 =
dpdVCalc(TKelvin, Vturn[0], presCalc);
1458 double p2 =
dpdVCalc(TKelvin, Vturn[1], presCalc);
1460 printf(
"p1 = %g p2 = %g \n", p1, p2);
1461 p1 =
dpdVCalc(TKelvin, 0.9*Vturn[0], presCalc);
1462 printf(
"0.9 p1 = %g \n", p1);
1466 doublereal h = 2.0 * an * delta * delta2;
1468 doublereal yN = 2.0 * bn * bn * bn / (27.0 * an * an) - bn * cn / (3.0 * an) + dn;
1470 doublereal desc = yN * yN - h2;
1472 if (fabs(fabs(h) - fabs(yN)) < 1.0E-10) {
1475 printf(
"NicholsSolve(): numerical issues\n");
1476 throw CanteraError(
"NicholsSolve()",
"numerical issues");
1483 }
else if (desc == 0.0) {
1493 }
else if (desc > 0.0) {
1501 doublereal tmpD = sqrt(desc);
1502 doublereal tmp1 = (- yN + tmpD) / (2.0 * an);
1503 doublereal sgn1 = 1.0;
1508 doublereal tmp2 = (- yN - tmpD) / (2.0 * an);
1509 doublereal sgn2 = 1.0;
1514 doublereal p1 = pow(tmp1, 1./3.);
1515 doublereal p2 = pow(tmp2, 1./3.);
1517 doublereal alpha = xN + sgn1 * p1 + sgn2 * p2;
1522 tmp = an * Vroot[0] * Vroot[0] * Vroot[0] + bn * Vroot[0] * Vroot[0] + cn * Vroot[0] + dn;
1523 if (fabs(tmp) > 1.0E-4) {
1524 lotsOfNumError =
true;
1527 }
else if (desc < 0.0) {
1528 doublereal tmp = - yN/h;
1530 doublereal val = acos(tmp);
1531 doublereal theta = val / 3.0;
1534 doublereal alpha = xN + 2. * delta * cos(theta);
1536 doublereal beta = xN + 2. * delta * cos(theta + oo);
1538 doublereal gamma = xN + 2. * delta * cos(theta + 2.0 * oo);
1545 for (
int i = 0; i < 3; i++) {
1546 tmp = an * Vroot[i] * Vroot[i] * Vroot[i] + bn * Vroot[i] * Vroot[i] + cn * Vroot[i] + dn;
1547 if (fabs(tmp) > 1.0E-4) {
1548 lotsOfNumError =
true;
1549 for (
int j = 0; j < 3; j++) {
1551 if (fabs(Vroot[i] - Vroot[j]) < 1.0E-4 * (fabs(Vroot[i]) + fabs(Vroot[j]))) {
1552 writelog(
"RedlichKwongMFTP::NicholsSolve(T = " +
fp2str(TKelvin) +
", p = " +
1553 fp2str(pres) +
"): WARNING roots have merged: " +
1561 }
else if (desc == 0.0) {
1562 if (yN == 0.0 && h == 0.0) {
1569 tmp = pow(yN/(2*an), 1./3.);
1570 if (fabs(tmp - delta) > 1.0E-9) {
1571 throw CanteraError(
"RedlichKwongMFTP::NicholsSolve()",
"unexpected");
1573 Vroot[1] = xN + delta;
1574 Vroot[0] = xN - 2.0*delta;
1576 tmp = pow(yN/(2*an), 1./3.);
1577 if (fabs(tmp - delta) > 1.0E-9) {
1578 throw CanteraError(
"RedlichKwongMFTP::NicholsSolve()",
"unexpected");
1581 Vroot[0] = xN + delta;
1582 Vroot[1] = xN - 2.0*delta;
1585 for (
int i = 0; i < 2; i++) {
1586 tmp = an * Vroot[i] * Vroot[i] * Vroot[i] + bn * Vroot[i] * Vroot[i] + cn * Vroot[i] + dn;
1587 if (fabs(tmp) > 1.0E-4) {
1588 lotsOfNumError =
true;
1596 double res, dresdV = 0.0;
1597 for (
int i = 0; i < nSolnValues; i++) {
1598 for (
int n = 0; n < 20; n++) {
1599 res = an * Vroot[i] * Vroot[i] * Vroot[i] + bn * Vroot[i] * Vroot[i] + cn * Vroot[i] + dn;
1600 if (fabs(res) < 1.0E-14) {
1603 dresdV = 3.0 * an * Vroot[i] * Vroot[i] + 2.0 * bn * Vroot[i] + cn;
1604 double del = - res / dresdV;
1607 if (fabs(del) / (fabs(Vroot[i]) + fabs(del)) < 1.0E-14) {
1610 double res2 = an * Vroot[i] * Vroot[i] * Vroot[i] + bn * Vroot[i] * Vroot[i] + cn * Vroot[i] + dn;
1611 if (fabs(res2) < fabs(res)) {
1615 Vroot[i] += 0.1 * del;
1618 if ((fabs(res) > 1.0E-14) && (fabs(res) > 1.0E-14 * fabs(dresdV) * fabs(Vroot[i]))) {
1619 writelog(
"RedlichKwongMFTP::NicholsSolve(T = " +
fp2str(TKelvin) +
", p = " +
1620 fp2str(pres) +
"): WARNING root didn't converge V = " +
fp2str(Vroot[i]));
1625 if (nSolnValues == 1) {
1627 if (Vroot[0] < vc) {
1631 if (Vroot[0] < xN) {
1637 if (nSolnValues == 2) {
int NicholsSolve(double TKelvin, double pres, doublereal a, doublereal b, doublereal Vroot[3]) const
Solve the cubic equation of state.
RedlichKwongMFTP & operator=(const RedlichKwongMFTP &right)
Assignment operator.
virtual doublereal density() const
Density (kg/m^3).
This class can handle either an ideal solution or an ideal gas approximation of a phase...
doublereal m_b_current
Value of b in the equation of state.
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Initialize a ThermoPhase object, potentially reading activity coefficient information from an XML dat...
doublereal dpdV_
The derivative of the pressure wrt the volume.
XML_Node * get_XML_File(const std::string &file, int debug)
Return a pointer to the XML tree for a Cantera input file.
virtual doublereal isothermalCompressibility() const
Returns the isothermal compressibility. Units: 1/Pa.
virtual void getPartialMolarIntEnergies(doublereal *ubar) const
Get the species partial molar enthalpies. Units: J/kmol.
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
void resize(size_t n, size_t m, doublereal v=0.0)
Resize the array, and fill the new entries with 'v'.
virtual doublereal pressure() const
Return the thermodynamic pressure (Pa).
vector_fp m_tmpV
Temporary storage - length = m_kk.
virtual void getGibbs_ref(doublereal *g) const
virtual doublereal entropy_mole() const
Molar entropy. Units: J/kmol/K.
doublereal _RT() const
Return the Gas Constant multiplied by the current temperature.
const size_t npos
index returned by functions to indicate "no position"
RedlichKwongMFTP()
Base constructor.
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
doublereal z() const
Calculate the value of z.
virtual void getCp_R(doublereal *cpr) const
Get the nondimensional Heat Capacities at constant pressure for the standard state of the species at ...
virtual doublereal densityCalc(doublereal TKelvin, doublereal pressure, int phase, doublereal rhoguess)
Calculates the density given the temperature and the pressure and a guess at the density.
virtual void setMoleFractions(const doublereal *const x)
Set the mole fractions to the specified values, and then normalize them so that they sum to 1...
Class XML_Node is a tree-based representation of the contents of an XML file.
This is a filter class for ThermoPhase that implements some preparatory steps for efficiently handlin...
virtual ThermoPhase * duplMyselfAsThermoPhase() const
Duplicator from the ThermoPhase parent class.
virtual doublereal enthalpy_mole() const
Molar enthalpy. Units: J/kmol.
MixtureFugacityTP & operator=(const MixtureFugacityTP &b)
Assignment operator.
Header file for implicit nonlinear solver of a one dimensional function (see Numerical Utilities with...
void readXMLPureFluid(XML_Node &pureFluidParam)
Read the pure species RedlichKwong input parameters.
virtual void getPartialMolarCp(doublereal *cpbar) const
Get the partial molar heat capacities Units: J/kmol/K.
virtual int eosType() const
Equation of state type flag.
void setFuncIsGenerallyDecreasing(bool value)
Set the function behavior flag.
virtual void getGibbs_RT_ref(doublereal *grt) const
Returns the vector of nondimensional Gibbs free energies of the reference state at the current temper...
doublereal molarDensity() const
Molar density (kmol/m^3).
std::string lowercase(const std::string &s)
Cast a copy of a string to lower case.
virtual void setMassFractions(const doublereal *const y)
Set the mass fractions to the specified values, and then normalize them so that they sum to 1...
virtual void initThermo()
virtual void getEnthalpy_RT_ref(doublereal *hrt) const
Returns the vector of nondimensional enthalpies of the reference state at the current temperature of ...
virtual void getPartialMolarVolumes(doublereal *vbar) const
Get the species partial molar volumes. Units: m^3/kmol.
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Initialize a ThermoPhase object, potentially reading activity coefficient information from an XML dat...
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Base class for a phase with thermodynamic properties.
void setToEquilState(const doublereal *lambda_RT)
This method is used by the ChemEquil equilibrium solver.
vector_fp m_s0_R
Temporary storage for dimensionless reference state entropies.
virtual void getStandardVolumes(doublereal *vol) const
Get the molar volumes of each species in their standard states at the current T and P of the solution...
doublereal mean_X(const doublereal *const Q) const
Evaluate the mole-fraction-weighted mean of an array Q.
doublereal m_Pcurrent
Current value of the pressures.
int m_standardMixingRules
boolean indicating whether standard mixing rules are applied
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
static const doublereal omega_b
Omega constant for b.
bool importPhase(XML_Node &phase, ThermoPhase *th, SpeciesThermoFactory *spfactory)
Import a phase information into an empty thermophase object.
virtual void setMoleFractions_NoNorm(const doublereal *const x)
Set the mole fractions to the specified values without normalizing.
int m_formTempParam
Form of the temperature parameterization.
virtual void setMassFractions_NoNorm(const doublereal *const y)
Set the mass fractions to the specified values without normalizing.
void setTol(doublereal rtolf, doublereal atolf, doublereal rtolx=0.0, doublereal atolx=0.0)
Set the tolerance parameters for the rootfinder.
virtual void setMassFractions(const doublereal *const y)
Set the mass fractions to the specified values, and then normalize them so that they sum to 1...
virtual void initThermo()
virtual doublereal psatEst(doublereal TKelvin) const
Estimate for the saturation pressure.
Root finder for 1D problems.
void setFuncIsGenerallyIncreasing(bool value)
Set the function behavior flag.
doublereal dpdT_
The derivative of the pressure wrt the temperature.
doublereal m_a_current
Value of a in the equation of state.
virtual doublereal sresid() const
Calculate the deviation terms for the total entropy of the mixture from the ideal gas mixture...
doublereal molarVolume() const
Molar volume (m^3/kmol).
virtual void setConcentrations(const doublereal *const c)
Set the concentrations to the specified values within the phase.
doublereal sum_xlogx() const
Evaluate .
void pressureDerivatives() const
Calculate dpdV and dpdT at the current conditions.
std::string fp2str(const double x, const std::string &fmt)
Convert a double into a c++ string.
virtual void setMoleFractions(const doublereal *const x)
Set the mole fractions to the specified values, and then normalize them so that they sum to 1...
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
virtual doublereal logStandardConc(size_t k=0) const
Returns the natural logarithm of the standard concentration of the kth species.
vector_fp m_pp
Temporary storage - length = m_kk.
std::string name() const
Returns the name of the XML node.
virtual void setParametersFromXML(const XML_Node &thermoNode)
Set equation of state parameter values from XML entries.
Definition file for a derived class of ThermoPhase that assumes either an ideal gas or ideal solution...
virtual doublereal dpdVCalc(doublereal TKelvin, doublereal molarVol, doublereal &presCalc) const
Calculate the pressure and the pressure derivative given the temperature and the molar volume...
virtual void setMassFractions_NoNorm(const doublereal *const y)
Set the mass fractions to the specified values without normalizing.
virtual doublereal standardConcentration(size_t k=0) const
Returns the standard concentration , which is used to normalize the generalized concentration.
std::vector< doublereal > moleFractions_
Storage for the current values of the mole fractions of the species.
virtual doublereal refPressure(size_t k=npos) const =0
The reference-state pressure for species k.
virtual void setConcentrations(const doublereal *const c)
Set the concentrations to the specified values within the phase.
Base class for exceptions thrown by Cantera classes.
virtual doublereal cp_mole() const
Molar heat capacity at constant pressure. Units: J/kmol/K.
virtual void setTemperature(const doublereal temp)
Set the temperature (K)
virtual doublereal hresid() const
Calculate the deviation terms for the total enthalpy of the mixture from the ideal gas mixture...
virtual doublereal critDensity() const
Critical density (kg/m3).
void readXMLCrossFluid(XML_Node &pureFluidParam)
Read the cross species RedlichKwong input parameters.
virtual doublereal liquidVolEst(doublereal TKelvin, doublereal &pres) const
Estimate for the molar volume of the liquid.
virtual void calcDensity()
Calculate the density of the mixture using the partial molar volumes and mole fractions as input...
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
doublereal dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
static const doublereal omega_a
Omega constant for a -> value of a in terms of critical properties.
virtual void getActivityConcentrations(doublereal *c) const
This method returns an array of generalized concentrations.
virtual void getIntEnergy_RT(doublereal *urt) const
Returns the vector of nondimensional internal Energies of the standard state at the current temperatu...
virtual doublereal intEnergy_mole() const
Molar internal energy. Units: J/kmol.
virtual doublereal refPressure() const
Returns the reference pressure in Pa.
int solve(doublereal xmin, doublereal xmax, int itmax, doublereal &funcTargetValue, doublereal *xbest)
Using a line search method, find the root of a 1D function.
virtual doublereal densSpinodalGas() const
Return the value of the density at the gas spinodal point (on the gas side) for the current temperatu...
void writelogendl()
Write an end of line character to the screen and flush output.
doublereal moleFraction(size_t k) const
Return the mole fraction of a single species.
doublereal temperature() const
Temperature (K).
size_t nDim() const
Returns the number of spatial dimensions (1, 2, or 3)
virtual doublereal critPressure() const
Critical pressure (Pa).
const doublereal SmallNumber
smallest number to compare to zero.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
void calculateAB(doublereal temp, doublereal &aCalc, doublereal &bCalc) const
Calculate the a and the b parameters given the temperature.
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.
virtual void setParametersFromXML(const XML_Node &eosdata)
Set equation of state parameter values from XML entries.
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
const doublereal GasConstant
Universal Gas Constant. [J/kmol/K].
virtual void setState_PX(doublereal p, doublereal *x)
Set the pressure (Pa) and mole fractions.
virtual doublereal gibbs_mole() const
Molar Gibbs function. Units: J/kmol.
Contains declarations for string manipulation functions within Cantera.
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Get the species partial molar enthalpies. Units: J/kmol.
static const doublereal omega_vc
Omega constant for the critical molar volume.
virtual doublereal densSpinodalLiquid() const
Return the value of the density at the liquid spinodal point (on the liquid side) for the current tem...
virtual doublereal cv_mole() const
Molar heat capacity at constant volume. Units: J/kmol/K.
void writelog(const std::string &msg)
Write a message to the screen.
virtual void getUnitsStandardConc(double *uA, int k=0, int sizeUA=6) const
Returns the units of the standard and generalized concentrations.
size_t m_kk
Number of species in the phase.
void applyStandardMixingRules()
Apply mixing rules for a coefficients.
virtual void getEntropy_R_ref(doublereal *er) const
virtual doublereal pressureCalc(doublereal TKelvin, doublereal molarVol) const
Calculate the pressure given the temperature and the molar volume.
void setPrintLvl(int printLvl)
Set the print level from the rootfinder.
virtual void _updateReferenceStateThermo() const
Updates the reference state thermodynamic functions at the current T of the solution.
void getChemPotentials_RT(doublereal *mu) const
Get the array of non-dimensional species chemical potentials.
virtual doublereal critTemperature() const
Critical temperature (K).
virtual void getPartialMolarEntropies(doublereal *sbar) const
Get the species partial molar entropies. Units: J/kmol/K.
#define ROOTFIND_SUCCESS
This means that the root solver was a success.
vector_fp dpdni_
Vector of derivatives of pressure wrt mole number.
SpeciesThermo * m_spthermo
Pointer to the calculation manager for species reference-state thermodynamic properties.
void updateAB()
Update the a and b parameters.
const doublereal * moleFractdivMMW() const
Returns a const pointer to the start of the moleFraction/MW array.
size_t getFloatArray(const Cantera::XML_Node &node, std::vector< doublereal > &v, const bool convert, const std::string &unitsString, const std::string &nodeName)
This function reads the current node or a child node of the current node with the default name...
XML_Node * get_XML_NameID(const std::string &nameTarget, const std::string &file_ID, XML_Node *root)
This routine will locate an XML node in either the input XML tree or in another input file specified ...
size_t nChildren(bool discardComments=false) const
Return the number of children.
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional activity coefficients at the current solution temperature, pressure, and solution concentration.
virtual void setDensity(const doublereal density_)
Set the internally stored density (kg/m^3) of the phase Note the density of a phase is an independent...
vector_fp m_h0_RT
Temporary storage for dimensionless reference state enthalpies.
vector_fp m_cp0_R
Temporary storage for dimensionless reference state heat capacities.