mirror of
https://github.com/Cantera/cantera.git
synced 2026-08-09 12:38:22 -05:00
559 lines
21 KiB
C++
559 lines
21 KiB
C++
#include "gtest/gtest.h"
|
|
#include "cantera/thermo/ThermoFactory.h"
|
|
#include "cantera/thermo/SurfPhase.h"
|
|
#include "cantera/base/YamlWriter.h"
|
|
#include "cantera/thermo/Species.h"
|
|
#include "cantera/thermo/PlasmaPhase.h"
|
|
|
|
using namespace Cantera;
|
|
typedef vector<string> strvec;
|
|
|
|
class ThermoToYaml : public testing::Test
|
|
{
|
|
public:
|
|
void setup(const string& fileName, const string& phaseName="") {
|
|
thermo = newThermo(fileName, phaseName);
|
|
// Because ThermoPhase::input may already contain the data we are trying
|
|
// to check for here, clear it so that the only parameters are those
|
|
// added by the overrides of getParameters.
|
|
thermo->input().clear();
|
|
data = thermo->parameters();
|
|
data.applyUnits();
|
|
|
|
speciesData.resize(thermo->nSpecies());
|
|
eosData.resize(thermo->nSpecies());
|
|
for (size_t k = 0; k < thermo->nSpecies(); k++) {
|
|
thermo->getSpeciesParameters(thermo->speciesName(k), speciesData[k]);
|
|
speciesData[k].applyUnits();
|
|
if (speciesData[k].hasKey("equation-of-state")) {
|
|
// Get the first EOS node, for convenience
|
|
eosData[k] = speciesData[k]["equation-of-state"].asVector<AnyMap>()[0];
|
|
}
|
|
}
|
|
}
|
|
|
|
shared_ptr<ThermoPhase> thermo;
|
|
AnyMap data;
|
|
vector<AnyMap> speciesData;
|
|
vector<AnyMap> eosData;
|
|
};
|
|
|
|
TEST_F(ThermoToYaml, simpleIdealGas)
|
|
{
|
|
setup("ideal-gas.yaml", "simple");
|
|
thermo->setState_TP(1010, 2e5);
|
|
double rho = thermo->density();
|
|
data = thermo->parameters();
|
|
data.applyUnits();
|
|
|
|
ASSERT_EQ(data["thermo"], "ideal-gas");
|
|
ASSERT_EQ(data["state"]["T"], 1010);
|
|
ASSERT_EQ(data["state"]["density"], rho);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, IdealSolidSoln)
|
|
{
|
|
setup("thermo-models.yaml", "IdealSolidSolnPhase2");
|
|
EXPECT_EQ(data["name"], "IdealSolidSolnPhase2");
|
|
EXPECT_EQ(data["species"].asVector<string>().size(), thermo->nSpecies());
|
|
EXPECT_EQ(data["standard-concentration-basis"], "solvent-molar-volume");
|
|
|
|
EXPECT_DOUBLE_EQ(eosData[0]["molar-volume"].asDouble(), 1.5);
|
|
EXPECT_DOUBLE_EQ(eosData[2]["molar-volume"].asDouble(), 0.1);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, BinarySolutionTabulated)
|
|
{
|
|
setup("thermo-models.yaml", "graphite-anode");
|
|
EXPECT_EQ(data["tabulated-species"], "Li[anode]");
|
|
auto& tabThermo = data["tabulated-thermo"].as<AnyMap>();
|
|
auto& X = tabThermo["mole-fractions"].asVector<double>();
|
|
auto& h = tabThermo["enthalpy"].asVector<double>();
|
|
auto& s = tabThermo["entropy"].asVector<double>();
|
|
EXPECT_DOUBLE_EQ(X[0], 5.75e-3);
|
|
EXPECT_DOUBLE_EQ(h[1], -9.69664e6);
|
|
EXPECT_DOUBLE_EQ(s[2], 1.27000e4);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, StoichSubstance1)
|
|
{
|
|
setup("thermo-models.yaml", "NaCl(s)");
|
|
EXPECT_EQ(eosData[0]["model"], "constant-volume");
|
|
EXPECT_DOUBLE_EQ(eosData[0]["density"].asDouble(), 2165.0);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, StoichSubstance2)
|
|
{
|
|
setup("thermo-models.yaml", "KCl(s)");
|
|
EXPECT_EQ(eosData[0]["model"], "constant-volume");
|
|
EXPECT_DOUBLE_EQ(eosData[0]["molar-volume"].asDouble(), 0.0376521717);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, Lattice)
|
|
{
|
|
setup("thermo-models.yaml", "Li7Si3-interstitial");
|
|
EXPECT_DOUBLE_EQ(data["site-density"].asDouble(), 1.046344e+01);
|
|
EXPECT_DOUBLE_EQ(eosData[0]["molar-volume"].asDouble(), 0.2);
|
|
EXPECT_EQ(eosData[1].size(), (size_t) 0);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, LatticeSolid)
|
|
{
|
|
setup("thermo-models.yaml", "Li7Si3_and_interstitials");
|
|
EXPECT_DOUBLE_EQ(data["composition"]["Li7Si3(s)"].asDouble(), 1.0);
|
|
EXPECT_DOUBLE_EQ(data["composition"]["Li7Si3-interstitial"].asDouble(), 1.0);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, Metal)
|
|
{
|
|
setup("thermo-models.yaml", "Metal");
|
|
EXPECT_EQ(data["thermo"], "electron-cloud");
|
|
EXPECT_DOUBLE_EQ(data["density"].asDouble(), 9.0);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, PureFluid)
|
|
{
|
|
setup("thermo-models.yaml", "nitrogen");
|
|
EXPECT_EQ(data["thermo"], "pure-fluid");
|
|
EXPECT_EQ(data["pure-fluid-name"], "nitrogen");
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, RedlichKwong)
|
|
{
|
|
setup("thermo-models.yaml", "CO2-RK");
|
|
auto a = eosData[0]["a"].asVector<double>();
|
|
EXPECT_DOUBLE_EQ(a[0], 7.54e6);
|
|
EXPECT_DOUBLE_EQ(a[1], -4.13e3);
|
|
EXPECT_DOUBLE_EQ(eosData[0]["b"].asDouble(), 27.80e-3);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, Surface)
|
|
{
|
|
setup("surface-phases.yaml", "Pt-surf");
|
|
EXPECT_EQ(data["thermo"], "ideal-surface");
|
|
EXPECT_DOUBLE_EQ(data["site-density"].asDouble(), 2.7063e-8);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, Edge)
|
|
{
|
|
setup("surface-phases.yaml", "TPB");
|
|
EXPECT_EQ(data["thermo"], "edge");
|
|
EXPECT_DOUBLE_EQ(data["site-density"].asDouble(), 5e-18);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, CoverageDependentSurface)
|
|
{
|
|
setup("copt_covdepsurf_example.yaml", "covdep");
|
|
EXPECT_EQ(data["thermo"], "coverage-dependent-surface");
|
|
EXPECT_DOUBLE_EQ(data["site-density"].asDouble(), 2.72e-8);
|
|
EXPECT_DOUBLE_EQ(data["reference-state-coverage"].asDouble(), 0.22);
|
|
UnitSystem us;
|
|
EXPECT_EQ(speciesData[1]["coverage-dependencies"]["OC_Pt"]["model"], "linear");
|
|
EXPECT_DOUBLE_EQ(
|
|
speciesData[1]["coverage-dependencies"]["OC_Pt"]["enthalpy"]
|
|
.asDouble(), us.convertFrom(0.48, "eV/molec"));
|
|
EXPECT_EQ(
|
|
speciesData[2]["coverage-dependencies"]["OC_Pt"]["model"], "piecewise-linear");
|
|
EXPECT_DOUBLE_EQ(
|
|
speciesData[2]["coverage-dependencies"]["OC_Pt"]["entropy-high"]
|
|
.asDouble(), us.convertFrom(-0.1, "eV/molec"));
|
|
EXPECT_EQ(
|
|
speciesData[1]["coverage-dependencies"]["O_Pt"]["model"], "interpolative");
|
|
EXPECT_DOUBLE_EQ(
|
|
speciesData[1]["coverage-dependencies"]["O_Pt"]["enthalpies"]
|
|
.asVector<double>()[3], us.convertFrom(2.7, "kcal/mol"));
|
|
EXPECT_EQ(
|
|
speciesData[4]["coverage-dependencies"]["O_Pt"]["model"], "polynomial");
|
|
EXPECT_DOUBLE_EQ(
|
|
speciesData[4]["coverage-dependencies"]["O_Pt"]["enthalpy-coefficients"]
|
|
.asVector<double>()[3], us.convertFrom(2.11, "eV/molec"));
|
|
EXPECT_DOUBLE_EQ(
|
|
speciesData[3]["coverage-dependencies"]["C_Pt"]["heat-capacity-a"]
|
|
.asDouble(), us.convertFrom(0.07e-3, "eV/molec"));
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, Margules)
|
|
{
|
|
setup("thermo-models.yaml", "molten-salt-Margules");
|
|
auto& interactions = data["interactions"].asVector<AnyMap>();
|
|
EXPECT_EQ(interactions.size(), (size_t) 1);
|
|
EXPECT_EQ(interactions[0]["species"].asVector<string>()[0], "KCl(l)");
|
|
EXPECT_EQ(interactions[0]["excess-enthalpy"].asVector<double>()[1], -377e3);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, RedlichKister)
|
|
{
|
|
setup("thermo-models.yaml", "Redlich-Kister-LiC6");
|
|
auto& interactions = data["interactions"].asVector<AnyMap>();
|
|
EXPECT_EQ(interactions.size(), (size_t) 1);
|
|
auto& I = interactions[0];
|
|
EXPECT_EQ(I["excess-enthalpy"].asVector<double>().size(), (size_t) 15);
|
|
EXPECT_EQ(I["excess-entropy"].asVector<double>().size(), (size_t) 1);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, DebyeHuckel_B_dot_ak)
|
|
{
|
|
setup("thermo-models.yaml", "debye-huckel-B-dot-ak");
|
|
auto& ac = data["activity-data"];
|
|
EXPECT_EQ(ac["model"], "B-dot-with-variable-a");
|
|
EXPECT_DOUBLE_EQ(ac["B-dot"].asDouble(), 0.0410);
|
|
EXPECT_DOUBLE_EQ(ac["max-ionic-strength"].asDouble(), 50.0);
|
|
EXPECT_DOUBLE_EQ(ac["default-ionic-radius"].asDouble(), 4e-10);
|
|
EXPECT_FALSE(ac.as<AnyMap>().hasKey("A_Debye"));
|
|
EXPECT_FALSE(ac.as<AnyMap>().hasKey("B_Debye"));
|
|
|
|
EXPECT_EQ(eosData[0]["model"], "liquid-water-IAPWS95");
|
|
EXPECT_EQ(eosData[1]["model"], "constant-volume");
|
|
EXPECT_DOUBLE_EQ(eosData[1]["molar-volume"].asDouble(), 1.3);
|
|
|
|
EXPECT_FALSE(speciesData[0].hasKey("Debye-Huckel"));
|
|
EXPECT_FALSE(speciesData[1].hasKey("Debye-Huckel")); // defaults are ok
|
|
EXPECT_DOUBLE_EQ(speciesData[2]["Debye-Huckel"]["ionic-radius"].asDouble(), 3e-10);
|
|
EXPECT_DOUBLE_EQ(speciesData[5]["Debye-Huckel"]["weak-acid-charge"].asDouble(), -1);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, DebyeHuckel_beta_ij)
|
|
{
|
|
setup("thermo-models.yaml", "debye-huckel-beta_ij");
|
|
EXPECT_EQ(data["activity-data"]["model"], "beta_ij");
|
|
EXPECT_TRUE(data["activity-data"]["use-Helgeson-fixed-form"].asBool());
|
|
auto& beta = data["activity-data"]["beta"].asVector<AnyMap>();
|
|
ASSERT_EQ(beta.size(), (size_t) 3);
|
|
for (size_t i = 0; i < 3; i++) {
|
|
auto species = beta[i]["species"].asVector<string>();
|
|
std::sort(species.begin(), species.end());
|
|
if (species[0] == "Cl-" && species[1] == "H+") {
|
|
EXPECT_DOUBLE_EQ(beta[i]["beta"].asDouble(), 0.27);
|
|
} else if (species[0] == "Cl-" && species[1] == "Na+") {
|
|
EXPECT_DOUBLE_EQ(beta[i]["beta"].asDouble(), 0.15);
|
|
} else {
|
|
EXPECT_EQ(species[0], "Na+");
|
|
EXPECT_EQ(species[1], "OH-");
|
|
EXPECT_DOUBLE_EQ(beta[i]["beta"].asDouble(), 0.06);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, HMWSoln1)
|
|
{
|
|
setup("thermo-models.yaml", "HMW-NaCl-electrolyte");
|
|
EXPECT_EQ(data["activity-data"]["temperature-model"], "complex");
|
|
auto& interactions = data["activity-data"]["interactions"].asVector<AnyMap>();
|
|
EXPECT_EQ(interactions.size(), (size_t) 7);
|
|
for (auto& item : interactions) {
|
|
auto species = item["species"].asVector<string>();
|
|
std::sort(species.begin(), species.end());
|
|
if (species == strvec{"Cl-", "Na+"}) {
|
|
auto& beta0 = item["beta0"].asVector<double>();
|
|
EXPECT_EQ(beta0.size(), (size_t) 5);
|
|
EXPECT_DOUBLE_EQ(beta0[1], 0.008946);
|
|
} else if (species == strvec{"Cl-", "H+"}) {
|
|
EXPECT_TRUE(item.hasKey("beta2"));
|
|
EXPECT_TRUE(item.hasKey("Cphi"));
|
|
} else if (species == strvec{"Na+", "OH-"}) {
|
|
EXPECT_DOUBLE_EQ(item["beta2"].asDouble(), 0.0);
|
|
} else if (species == strvec{"Cl-", "OH-"}) {
|
|
EXPECT_DOUBLE_EQ(item["theta"].asDouble(), -0.05);
|
|
} else if (species == strvec{"Cl-", "Na+", "OH-"}) {
|
|
EXPECT_DOUBLE_EQ(item["psi"].asDouble(), -0.006);
|
|
} else if (species == strvec{"H+", "Na+"}) {
|
|
EXPECT_DOUBLE_EQ(item["theta"].asDouble(), 0.036);
|
|
} else if (species == strvec{"Cl-", "H+", "Na+"}) {
|
|
EXPECT_DOUBLE_EQ(item["psi"].asDouble(), -0.004);
|
|
} else {
|
|
FAIL(); // unexpected set of species
|
|
}
|
|
}
|
|
EXPECT_EQ(eosData[0]["model"], "liquid-water-IAPWS95");
|
|
EXPECT_EQ(eosData[1]["model"], "constant-volume");
|
|
EXPECT_DOUBLE_EQ(eosData[2]["molar-volume"].asDouble(), 1.3);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, HMWSoln2)
|
|
{
|
|
setup("thermo-models.yaml", "HMW-bogus");
|
|
EXPECT_EQ(data["activity-data"]["temperature-model"], "linear");
|
|
auto& interactions = data["activity-data"]["interactions"].asVector<AnyMap>();
|
|
EXPECT_EQ(interactions.size(), (size_t) 4);
|
|
for (auto& item : interactions) {
|
|
auto species = item["species"].asVector<string>();
|
|
std::sort(species.begin(), species.end());
|
|
if (species == strvec{"Cl-", "NaCl(aq)"}) {
|
|
EXPECT_DOUBLE_EQ(item["lambda"].asVector<double>()[0], 0.3);
|
|
} else if (species == strvec{"Na+", "NaCl(aq)"}) {
|
|
EXPECT_DOUBLE_EQ(item["lambda"].asVector<double>()[1], 0.02);
|
|
} else if (species == strvec{"Na+", "NaCl(aq)", "OH-"}) {
|
|
EXPECT_DOUBLE_EQ(item["zeta"].asVector<double>()[0], 0.5);
|
|
} else if (species == strvec{"NaCl(aq)"}) {
|
|
EXPECT_DOUBLE_EQ(item["mu"].asVector<double>()[1], 0.3);
|
|
} else {
|
|
FAIL(); // unexpected set of species
|
|
}
|
|
}
|
|
auto& crop = data["activity-data"]["cropping-coefficients"];
|
|
EXPECT_DOUBLE_EQ(crop["ln_gamma_k_min"].asDouble(), -8.0);
|
|
EXPECT_DOUBLE_EQ(crop["ln_gamma_k_max"].asDouble(), 20);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, HMWSoln_HKFT)
|
|
{
|
|
setup("thermo-models.yaml", "HMW-NaCl-HKFT");
|
|
EXPECT_DOUBLE_EQ(eosData[1]["h0"].asDouble(), -57433 * 4184);
|
|
EXPECT_DOUBLE_EQ(eosData[1]["s0"].asDouble(), 13.96 * 4184);
|
|
EXPECT_DOUBLE_EQ(eosData[2]["a"].asVector<double>()[2], 5.563 * 4184 / 1e5);
|
|
EXPECT_DOUBLE_EQ(eosData[4]["c"].asVector<double>()[1], -103460 * 4184);
|
|
EXPECT_DOUBLE_EQ(eosData[4]["omega"].asDouble(), 172460 * 4184);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, IdealMolalSolution)
|
|
{
|
|
setup("thermo-models.yaml", "ideal-molal-aqueous");
|
|
auto& cutoff = data["cutoff"];
|
|
EXPECT_EQ(cutoff["model"], "polyexp");
|
|
EXPECT_EQ(cutoff.as<AnyMap>().size(), (size_t) 2); // other values are defaults
|
|
EXPECT_DOUBLE_EQ(cutoff["gamma_o"].asDouble(), 0.0001);
|
|
|
|
EXPECT_EQ(eosData[2]["model"], "constant-volume");
|
|
EXPECT_DOUBLE_EQ(eosData[2]["molar-density"].asDouble(), 10);
|
|
|
|
EXPECT_EQ(eosData[3]["model"], "constant-volume");
|
|
EXPECT_DOUBLE_EQ(eosData[3]["density"].asDouble(), 160.43);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, IsotropicElectronEnergyPlasma)
|
|
{
|
|
setup("oxygen-plasma.yaml", "isotropic-electron-energy-plasma");
|
|
auto& electronEnergyDist = data["electron-energy-distribution"].as<AnyMap>();
|
|
EXPECT_EQ(electronEnergyDist["type"], "isotropic");
|
|
EXPECT_DOUBLE_EQ(electronEnergyDist["shape-factor"].asDouble(), 2.0);
|
|
}
|
|
|
|
TEST_F(ThermoToYaml, DiscretizedElectronEnergyPlasma)
|
|
{
|
|
setup("oxygen-plasma.yaml", "discretized-electron-energy-plasma");
|
|
auto& electronEnergyDist = data["electron-energy-distribution"].as<AnyMap>();
|
|
vector<double> levels = electronEnergyDist["energy-levels"].asVector<double>();
|
|
vector<double> dist = electronEnergyDist["distribution"].asVector<double>();
|
|
EXPECT_EQ(electronEnergyDist["type"], "discretized");
|
|
EXPECT_DOUBLE_EQ(levels[3], 10.0);
|
|
EXPECT_DOUBLE_EQ(dist[3], 0.01);
|
|
}
|
|
|
|
|
|
class ThermoYamlRoundTrip : public testing::Test
|
|
{
|
|
public:
|
|
void roundtrip(const string& fileName, const string& phaseName="",
|
|
const vector<string> extraPhases={}) {
|
|
original = newThermo(fileName, phaseName);
|
|
YamlWriter writer;
|
|
writer.addPhase(original);
|
|
for (const auto& name : extraPhases) {
|
|
shared_ptr<ThermoPhase> p(newThermo(fileName, name));
|
|
writer.addPhase(p);
|
|
}
|
|
writer.skipUserDefined();
|
|
AnyMap input1 = AnyMap::fromYamlString(writer.toYamlString());
|
|
duplicate = newThermo(input1["phases"].getMapWhere("name", phaseName), input1);
|
|
skip_cp = false;
|
|
skip_activities = false;
|
|
skip_entropy = false;
|
|
rtol = 1e-14;
|
|
}
|
|
|
|
void compareThermo(double T, double P, const string& X="") {
|
|
size_t kk = original->nSpecies();
|
|
ASSERT_EQ(original->nSpecies(), duplicate->nSpecies());
|
|
|
|
if (X.empty()) {
|
|
original->setState_TP(T, P);
|
|
duplicate->setState_TP(T, P);
|
|
} else {
|
|
original->setState_TPX(T, P, X);
|
|
duplicate->setState_TPX(T, P, X);
|
|
}
|
|
|
|
double rhoOrig = original->density();
|
|
double rhoDup = duplicate->density();
|
|
if (rhoOrig != rhoDup) {
|
|
EXPECT_NEAR(original->density(), duplicate->density(),
|
|
rtol * original->density());
|
|
}
|
|
if (!skip_cp) {
|
|
EXPECT_NEAR(original->cp_mass(), duplicate->cp_mass(),
|
|
rtol * original->cp_mass());
|
|
}
|
|
if (!skip_entropy) {
|
|
EXPECT_NEAR(original->entropy_mass(), duplicate->entropy_mass(),
|
|
rtol * fabs(original->entropy_mass()));
|
|
}
|
|
EXPECT_NEAR(original->enthalpy_mole(), duplicate->enthalpy_mole(),
|
|
rtol * fabs(original->enthalpy_mole()));
|
|
|
|
vector<double> Y1(kk), Y2(kk), h1(kk), h2(kk), s1(kk), s2(kk);
|
|
vector<double> mu1(kk), mu2(kk), v1(kk), v2(kk), a1(kk), a2(kk);
|
|
original->getMassFractions(Y1.data());
|
|
duplicate->getMassFractions(Y2.data());
|
|
original->getPartialMolarEnthalpies(h1.data());
|
|
duplicate->getPartialMolarEnthalpies(h2.data());
|
|
original->getPartialMolarEntropies(s1.data());
|
|
duplicate->getPartialMolarEntropies(s2.data());
|
|
original->getChemPotentials(mu1.data());
|
|
duplicate->getChemPotentials(mu2.data());
|
|
original->getPartialMolarVolumes(v1.data());
|
|
duplicate->getPartialMolarVolumes(v2.data());
|
|
if (!skip_activities) {
|
|
original->getActivityCoefficients(a1.data());
|
|
duplicate->getActivityCoefficients(a2.data());
|
|
}
|
|
|
|
for (size_t k = 0; k < kk; k++) {
|
|
EXPECT_NEAR(Y1[k], Y2[k], 1e-20 + rtol*fabs(Y1[k])) << k;
|
|
EXPECT_NEAR(h1[k], h2[k], 1e-20 + rtol*fabs(h1[k])) << k;
|
|
EXPECT_NEAR(s1[k], s2[k], 1e-20 + rtol*fabs(s1[k])) << k;
|
|
EXPECT_NEAR(mu1[k], mu2[k], 1e-20 + rtol*fabs(mu1[k])) << k;
|
|
EXPECT_NEAR(v1[k], v2[k], 1e-20 + rtol*fabs(v1[k])) << k;
|
|
EXPECT_NEAR(a1[k], a2[k], 1e-20 + rtol*fabs(a1[k])) << k;
|
|
}
|
|
}
|
|
|
|
shared_ptr<ThermoPhase> original;
|
|
shared_ptr<ThermoPhase> duplicate;
|
|
bool skip_cp;
|
|
bool skip_activities;
|
|
bool skip_entropy;
|
|
double rtol;
|
|
};
|
|
|
|
TEST_F(ThermoYamlRoundTrip, RedlichKwong)
|
|
{
|
|
roundtrip("nDodecane_Reitz.yaml", "nDodecane_RK");
|
|
compareThermo(500, 6e5, "c12h26: 0.2, o2: 0.1, co2: 0.4, c2h2: 0.3");
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, RedlichKwong_crit_props)
|
|
{
|
|
roundtrip("thermo-models.yaml", "CO2-RK-params");
|
|
compareThermo(400, 1e6, "CO2:0.8, H2O:0.1, H2:0.1");
|
|
auto params = duplicate->species("CO2")->parameters(duplicate.get());
|
|
params.applyUnits();
|
|
double Tc = params["critical-parameters"]["critical-temperature"].asDouble();
|
|
EXPECT_NEAR(Tc, 304.128, 1e-3);
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, PengRobinson)
|
|
{
|
|
roundtrip("co2_PR_example.yaml");
|
|
compareThermo(400, 20e5, "CO2:0.9, H2O:0.07, CH4:0.03");
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, PengRobinson_crit_props)
|
|
{
|
|
roundtrip("thermo-models.yaml", "CO2-PR-params");
|
|
// rtol = 1e-13;
|
|
compareThermo(400, 1e6, "CO2:0.8, H2O:0.1, H2:0.1");
|
|
auto params = duplicate->species("CO2")->parameters(duplicate.get());
|
|
params.applyUnits();
|
|
double Tc = params["critical-parameters"]["critical-temperature"].asDouble();
|
|
EXPECT_NEAR(Tc, 304.128, 1e-3);
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, BinarySolutionTabulated)
|
|
{
|
|
roundtrip("BinarySolutionTabulatedThermo.yaml", "anode");
|
|
compareThermo(310, 2e5, "Li[anode]:0.4, V[anode]:0.6");
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, Margules)
|
|
{
|
|
roundtrip("LiKCl_liquid.yaml", "MoltenSalt_electrolyte");
|
|
compareThermo(920, 3e5, "KCl(L):0.35, LiCl(L):0.65");
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, DebyeHuckel)
|
|
{
|
|
roundtrip("thermo-models.yaml", "debye-huckel-B-dot-ak");
|
|
compareThermo(305, 2e5);
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, IdealMolalSolution)
|
|
{
|
|
roundtrip("thermo-models.yaml", "ideal-molal-aqueous");
|
|
compareThermo(308, 1.1e5, "H2O(l): 0.95, H2S(aq): 0.01, CO2(aq): 0.04");
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, IdealSolutionVpss)
|
|
{
|
|
roundtrip("thermo-models.yaml", "IdealSolnGas-liquid");
|
|
compareThermo(320, 1.5e5, "Li(l):1.0");
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, LatticeSolid)
|
|
{
|
|
roundtrip("thermo-models.yaml", "Li7Si3_and_interstitials",
|
|
{"Li7Si3(s)", "Li7Si3-interstitial"});
|
|
compareThermo(710, 10e5);
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, HMWSoln)
|
|
{
|
|
roundtrip("thermo-models.yaml", "HMW-NaCl-electrolyte");
|
|
rtol = 1e-10; // @todo: Determine why more stringent tolerances can't be met
|
|
compareThermo(350.15, 101325,
|
|
"H2O(L): 0.8198, Na+:0.09, Cl-:0.09, H+:4.4e-6, OH-:4.4e-6");
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, PureFluid_Nitrogen)
|
|
{
|
|
roundtrip("thermo-models.yaml", "nitrogen");
|
|
compareThermo(90, 19e5);
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, RedlichKister)
|
|
{
|
|
roundtrip("thermo-models.yaml", "Redlich-Kister-LiC6");
|
|
compareThermo(310, 2e5);
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, Surface)
|
|
{
|
|
roundtrip("surface-phases.yaml", "Pt-surf");
|
|
skip_activities = true;
|
|
compareThermo(800, 2*OneAtm);
|
|
auto origSurf = std::dynamic_pointer_cast<SurfPhase>(original);
|
|
auto duplSurf = std::dynamic_pointer_cast<SurfPhase>(duplicate);
|
|
EXPECT_DOUBLE_EQ(origSurf->siteDensity(), duplSurf->siteDensity());
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, CoverageDependentSurface)
|
|
{
|
|
roundtrip("copt_covdepsurf_example.yaml", "covdep");
|
|
skip_activities = true;
|
|
compareThermo(800, 2*OneAtm,
|
|
"Pt: 0.2, OC_Pt: 0.2, CO2_Pt: 0.2, C_Pt: 0.2, O_Pt: 0.2");
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, IsotropicElectronEnergyPlasma)
|
|
{
|
|
roundtrip("oxygen-plasma.yaml", "isotropic-electron-energy-plasma");
|
|
skip_cp = true; // Not implemented for PlasmaPhase
|
|
skip_entropy = true; // Not implemented for PlasmaPhase
|
|
compareThermo(800, 2*OneAtm);
|
|
auto origPlasma = std::dynamic_pointer_cast<PlasmaPhase>(original);
|
|
auto duplPlasma = std::dynamic_pointer_cast<PlasmaPhase>(duplicate);
|
|
vector<double> origDist(origPlasma->nElectronEnergyLevels());
|
|
vector<double> duplDist(duplPlasma->nElectronEnergyLevels());
|
|
origPlasma->getElectronEnergyLevels(origDist.data());
|
|
duplPlasma->getElectronEnergyLevels(duplDist.data());
|
|
EXPECT_DOUBLE_EQ(origDist[2], duplDist[2]);
|
|
}
|
|
|
|
TEST_F(ThermoYamlRoundTrip, DiscretizedElectronEnergyPlasma)
|
|
{
|
|
roundtrip("oxygen-plasma.yaml", "discretized-electron-energy-plasma");
|
|
skip_cp = true; // Not implemented for PlasmaPhase
|
|
skip_entropy = true; // Not implemented for PlasmaPhase
|
|
compareThermo(800, 2*OneAtm);
|
|
EXPECT_DOUBLE_EQ(original->electronTemperature(), duplicate->electronTemperature());
|
|
}
|