TEST(HMWSoln, fromScratch) { // Regression test based on HMW_test_3 HMWSoln p; auto sH2O = make_species("H2O(l)", "H:2, O:1", h2oliq_nasa_coeffs); auto sCl = make_species("Cl-", "Cl:1, E:1", 0.0, 298.15, -52.8716, 333.15, -52.8716, 1e5); sCl->charge = -1; auto sH = make_species("H+", "H:1, E:-1", 0.0, 298.15, 0.0, 333.15, 0.0, 1e5); sH->charge = 1; auto sNa = make_species("Na+", "Na:1, E:-1", 0.0, 298.15, -125.5213, 333.15, -125.5213, 1e5); sNa->charge = 1; auto sOH = make_species("OH-", "O:1, H:1, E:1", 0.0, 298.15, -91.523, 333.15, -91.523, 1e5); sOH->charge = -1; for (auto& s : {sH2O, sCl, sH, sNa, sOH}) { p.addSpecies(s); } std::unique_ptr<PDSS_Water> ss(new PDSS_Water()); p.installPDSS(0, std::move(ss)); size_t k = 1; for (double v : {1.3, 1.3, 1.3, 1.3}) { std::unique_ptr<PDSS_ConstVol> ss(new PDSS_ConstVol()); ss->setMolarVolume(v); p.installPDSS(k++, std::move(ss)); } p.setPitzerTempModel("complex"); p.setA_Debye(1.175930); p.initThermo(); set_hmw_interactions(p); p.setMolalitiesByName("Na+:6.0997 Cl-:6.0996986044628 H+:2.1628E-9 OH-:1.3977E-6"); p.setState_TP(150 + 273.15, 101325); size_t N = p.nSpecies(); vector_fp acMol(N), mf(N), activities(N), moll(N), mu0(N); p.getMolalityActivityCoefficients(acMol.data()); p.getMoleFractions(mf.data()); p.getActivities(activities.data()); p.getMolalities(moll.data()); p.getStandardChemPotentials(mu0.data()); double acMolRef[] = {0.9341, 1.0191, 3.9637, 1.0191, 0.4660}; double mfRef[] = {0.8198, 0.0901, 0.0000, 0.0901, 0.0000}; double activitiesRef[] = {0.7658, 6.2164, 0.0000, 6.2164, 0.0000}; double mollRef[] = {55.5084, 6.0997, 0.0000, 6.0997, 0.0000}; double mu0Ref[] = {-317.175788, -186.014558, 0.0017225, -441.615429, -322.000412}; // kJ/gmol for (size_t k = 0 ; k < N; k++) { EXPECT_NEAR(acMol[k], acMolRef[k], 2e-4); EXPECT_NEAR(mf[k], mfRef[k], 2e-4); EXPECT_NEAR(activities[k], activitiesRef[k], 2e-4); EXPECT_NEAR(moll[k], mollRef[k], 2e-4); EXPECT_NEAR(mu0[k]/1e6, mu0Ref[k], 2e-6); } }
TEST(HMWSoln, fromScratch_HKFT) { HMWSoln p; auto sH2O = make_species("H2O(l)", "H:2, O:1", h2oliq_nasa_coeffs); auto sNa = make_species("Na+", "Na:1, E:-1", 0.0, 298.15, -125.5213, 333.15, -125.5213, 1e5); sNa->charge = 1; auto sCl = make_species("Cl-", "Cl:1, E:1", 0.0, 298.15, -52.8716, 333.15, -52.8716, 1e5); sCl->charge = -1; auto sH = make_species("H+", "H:1, E:-1", 0.0, 298.15, 0.0, 333.15, 0.0, 1e5); sH->charge = 1; auto sOH = make_species("OH-", "O:1, H:1, E:1", 0.0, 298.15, -91.523, 333.15, -91.523, 1e5); sOH->charge = -1; for (auto& s : {sH2O, sNa, sCl, sH, sOH}) { p.addSpecies(s); } double h0[] = {-57433, Undef, 0.0, -54977}; double g0[] = {Undef, -31379, 0.0, -37595}; double s0[] = {13.96, 13.56, Undef, -2.56}; double a[][4] = {{0.1839, -228.5, 3.256, -27260}, {0.4032, 480.1, 5.563, -28470}, {0.0, 0.0, 0.0, 0.0}, {0.12527, 7.38, 1.8423, -27821}}; double c[][2] = {{18.18, -29810}, {-4.4, -57140}, {0.0, 0.0}, {4.15, -103460}}; double omega[] = {33060, 145600, 0.0, 172460}; std::unique_ptr<PDSS_Water> ss(new PDSS_Water()); p.installPDSS(0, std::move(ss)); for (size_t k = 0; k < 4; k++) { std::unique_ptr<PDSS_HKFT> ss(new PDSS_HKFT()); if (h0[k] != Undef) { ss->setDeltaH0(h0[k] * toSI("cal/gmol")); } if (g0[k] != Undef) { ss->setDeltaG0(g0[k] * toSI("cal/gmol")); } if (s0[k] != Undef) { ss->setS0(s0[k] * toSI("cal/gmol/K")); } a[k][0] *= toSI("cal/gmol/bar"); a[k][1] *= toSI("cal/gmol"); a[k][2] *= toSI("cal-K/gmol/bar"); a[k][3] *= toSI("cal-K/gmol"); c[k][0] *= toSI("cal/gmol/K"); c[k][1] *= toSI("cal-K/gmol"); ss->set_a(a[k]); ss->set_c(c[k]); ss->setOmega(omega[k] * toSI("cal/gmol")); p.installPDSS(k+1, std::move(ss)); } p.setPitzerTempModel("complex"); p.setA_Debye(-1); p.initThermo(); set_hmw_interactions(p); p.setMolalitiesByName("Na+:6.0954 Cl-:6.0954 H+:2.1628E-9 OH-:1.3977E-6"); p.setState_TP(50 + 273.15, 101325); size_t N = p.nSpecies(); vector_fp mv(N), h(N), mu(N), ac(N), acoeff(N); p.getPartialMolarVolumes(mv.data()); p.getPartialMolarEnthalpies(h.data()); p.getChemPotentials(mu.data()); p.getActivities(ac.data()); p.getActivityCoefficients(acoeff.data()); double mvRef[] = {0.01815224, 0.00157182, 0.01954605, 0.00173137, -0.0020266}; for (size_t k = 0; k < N; k++) { EXPECT_NEAR(mv[k], mvRef[k], 2e-8); } }
int main(int argc, char** argv) { int retn = 0; size_t i; string commandFile; try { char iFile[80]; strcpy(iFile, "HMW_NaCl.xml"); if (argc > 1) { strcpy(iFile, argv[1]); } double Temp = 273.15 + 275.; double aTemp[7]; aTemp[0] = 298.15; aTemp[1] = 273.15 + 100.; aTemp[2] = 273.15 + 150.; aTemp[3] = 273.15 + 200.; aTemp[4] = 273.15 + 250.; aTemp[5] = 273.15 + 275.; aTemp[6] = 273.15 + 300.; HMWSoln* HMW = new HMWSoln(iFile, "NaCl_electrolyte"); size_t nsp = HMW->nSpecies(); double acMol[100]; double act[100]; double mf[100]; double moll[100]; for (i = 0; i < 100; i++) { acMol[i] = 1.0; act[i] = 1.0; mf[i] = 0.0; moll[i] = 0.0; } HMW->getMoleFractions(mf); string sName; FILE* ff; char fname[64]; for (int jTemp = 0; jTemp < 7; jTemp++) { Temp = aTemp[jTemp]; sprintf(fname, "T%3.0f.csv", Temp); ff = fopen(fname, "w"); HMW->setState_TP(Temp, 1.01325E5); printf(" Temperature = %g K\n", Temp); size_t i1 = HMW->speciesIndex("Na+"); size_t i2 = HMW->speciesIndex("Cl-"); size_t i3 = HMW->speciesIndex("H2O(L)"); for (i = 1; i < nsp; i++) { moll[i] = 0.0; } HMW->setState_TPM(Temp, OneAtm, moll); double Itop = 10.; double Ibot = 0.0; double ISQRTtop = sqrt(Itop); double ISQRTbot = sqrt(Ibot); double ISQRT; double Is = 0.0; size_t its = 100; bool doneSp = false; fprintf(ff," Is, sqrtIs, meanAc," " log10(meanAC), acMol_Na+," " acMol_Cl-, ac_Water, act_Water, OsmoticCoeff\n"); for (i = 0; i < its; i++) { ISQRT = ISQRTtop*((double)i)/(its - 1.0) + ISQRTbot*(1.0 - (double)i/(its - 1.0)); Is = ISQRT * ISQRT; if (!doneSp) { if (Is > 6.146) { Is = 6.146; doneSp = true; i = i - 1; } } moll[i1] = Is; moll[i2] = Is; HMW->setMolalities(moll); HMW->getMolalityActivityCoefficients(acMol); HMW->getActivities(act); double oc = HMW->osmoticCoefficient(); double meanAC = sqrt(acMol[i1] * acMol[i2]); fprintf(ff,"%15g, %15g, %15g, %15g, %15g, %15g, %15g, %15g, %15g\n", Is, ISQRT, meanAC, log10(meanAC), acMol[i1], acMol[i2], acMol[i3], act[i3], oc); } fclose(ff); } delete HMW; HMW = 0; Cantera::appdelete(); return retn; } catch (CanteraError& err) { std::cout << err.what() << std::endl; return -1; } }