[Input] Create IdealSolidSolnPhase objects from YAML definitions

This commit is contained in:
Ray Speth 2019-02-04 23:52:32 -05:00
parent 3011374ff6
commit f1937bfada
5 changed files with 95 additions and 10 deletions

View file

@ -575,19 +575,20 @@ public:
//@{
virtual bool addSpecies(shared_ptr<Species> spec);
virtual void initThermo();
virtual void initThermoXML(XML_Node& phaseNode, const std::string& id);
virtual void setToEquilState(const doublereal* lambda_RT);
//! Set the form for the standard and generalized concentrations
/*!
* Must be one of 'unity', 'molar_volume', or 'solvent_volume'.
* The default is 'unity'.
* Must be one of 'unity', 'species-molar-volume', or
* 'solvent-molar-volume'. The default is 'unity'.
*
* | m_formGC | GeneralizedConc | StandardConc |
* | ----------- | --------------- | ------------ |
* | unity | X_k | 1.0 |
* | molar_volume | X_k / V_k | 1.0 / V_k |
* | solvent_volume | X_k / V_N | 1.0 / V_N |
* | m_formGC | GeneralizedConc | StandardConc |
* | -------------------- | --------------- | ------------ |
* | unity | X_k | 1.0 |
* | species-molar-volume | X_k / V_k | 1.0 / V_k |
* | solvent-molar-volume | X_k / V_N | 1.0 / V_N |
*
* The value and form of the generalized concentration will affect
* reaction rate constants involving species in this phase.

View file

@ -359,7 +359,29 @@ bool IdealSolidSolnPhase::addSpecies(shared_ptr<Species> spec)
m_s0_R.push_back(0.0);
m_pe.push_back(0.0);;
m_pp.push_back(0.0);
if (spec->extra.hasKey("molar_volume")) {
if (spec->input.hasKey("equation-of-state")) {
auto& eos = spec->input["equation-of-state"].as<AnyMap>();
if (eos.getString("model", "") != "constant-volume") {
throw CanteraError("IdealSolidSolnPhase::initThermo",
"ideal-condensed model requires constant-volume "
"species model for species '{}'", spec->name);
}
double mv;
if (eos.hasKey("density")) {
mv = molecularWeight(m_kk-1) / eos.convert("density", "kg/m^3");
} else if (eos.hasKey("molar-density")) {
mv = 1.0 / eos.convert("molar-density", "kmol/m^3");
} else if (eos.hasKey("molar-volume")) {
mv = eos.convert("molar-volume", "m^3/kmol");
} else {
throw CanteraError("IdealSolidSolnPhase::initThermo",
"equation-of-state entry for species '{}' is missing "
"'density', 'molar-volume', or 'molar-density' "
"specification", spec->name);
}
m_speciesMolarVolume.push_back(mv);
} else if (spec->extra.hasKey("molar_volume")) {
// From XML
m_speciesMolarVolume.push_back(spec->extra["molar_volume"].asDouble());
} else {
throw CanteraError("IdealSolidSolnPhase::addSpecies",
@ -370,6 +392,13 @@ bool IdealSolidSolnPhase::addSpecies(shared_ptr<Species> spec)
return added;
}
void IdealSolidSolnPhase::initThermo()
{
if (m_input.hasKey("standard-concentration-basis")) {
setStandardConcentrationModel(m_input["standard-concentration-basis"].asString());
}
ThermoPhase::initThermo();
}
void IdealSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_)
{
@ -428,9 +457,11 @@ void IdealSolidSolnPhase::setStandardConcentrationModel(const std::string& model
{
if (caseInsensitiveEquals(model, "unity")) {
m_formGC = 0;
} else if (caseInsensitiveEquals(model, "molar_volume")) {
} else if (caseInsensitiveEquals(model, "species-molar-volume")
|| caseInsensitiveEquals(model, "molar_volume")) {
m_formGC = 1;
} else if (caseInsensitiveEquals(model, "solvent_volume")) {
} else if (caseInsensitiveEquals(model, "solvent-molar-volume")
|| caseInsensitiveEquals(model, "solvent_volume")) {
m_formGC = 2;
} else {
throw CanteraError("IdealSolidSolnPhase::setStandardConcentrationModel",

View file

@ -67,6 +67,7 @@ ThermoFactory::ThermoFactory()
reg("HMW", []() { return new HMWSoln(); });
m_synonyms["HMW-electrolyte"] = "HMW";
reg("IdealSolidSolution", []() { return new IdealSolidSolnPhase(); });
m_synonyms["ideal-condensed"] = "IdealSolidSolution";
reg("DebyeHuckel", []() { return new DebyeHuckel(); });
m_synonyms["Debye-Huckel"] = "DebyeHuckel";
reg("IdealMolalSolution", []() { return new IdealMolalSoln(); });

View file

@ -185,6 +185,12 @@ phases:
species: [NaCl(s), KCl(s)]
state: {T: 320, P: 1 atm}
- name: IdealSolidSolnPhase
thermo: ideal-condensed
standard-concentration-basis: unity
species: [{ISSP-species: all}]
state: {T: 500, P: 2 bar, X: {sp1: 0.1, sp2: 0.89, sp3: 0.01}}
species:
- name: NaCl(s)
@ -611,3 +617,39 @@ HKFT-species:
a: [0.12527, 7.38, 1.8423, -27821]
c: [4.15, -103460.]
omega: 172460.
ISSP-species:
- name: sp1
composition: {C: 2, H: 2}
thermo:
model: NASA7
temperature-ranges: [200.0, 1000.0]
data:
- [3.78245636, -0.00299673416, 9.84730201e-06, -9.68129509e-09, 3.24372837e-12,
-1063.94356, 3.65767573]
equation-of-state:
model: constant-volume
molar-volume: 1.5
- name: sp2
composition: {C: 1}
thermo:
model: NASA7
temperature-ranges: [200.0, 1000.0]
data:
- [4.19864056, -0.0020364341, 6.52040211e-06, -5.48797062e-09, 1.77197817e-12,
-30293.7267, -0.849032208]
equation-of-state:
model: constant-volume
molar-volume: 1.3
- name: sp3
composition: {H: 2}
thermo:
model: NASA7
temperature-ranges: [200.0, 1000.0]
data:
- [2.34433112, 0.00798052075, -1.9478151e-05, 2.01572094e-08, -7.37611761e-12,
-917.935173, 0.683010238]
equation-of-state:
model: constant-volume
molar-volume: 0.1

View file

@ -338,3 +338,13 @@ TEST(ThermoFromYaml, ConstDensityThermo)
auto thermo = newThermo("thermo-models.yaml", "const-density");
EXPECT_DOUBLE_EQ(thermo->density(), 700.0);
}
TEST(ThermoFromYaml, IdealSolidSolnPhase)
{
auto thermo = newThermo("thermo-models.yaml", "IdealSolidSolnPhase");
// Regression test following IdealSolidSolnPhase.fromScratch
EXPECT_NEAR(thermo->density(), 10.1786978, 1e-6);
EXPECT_NEAR(thermo->enthalpy_mass(), -15642803.3884617, 1e-4);
EXPECT_NEAR(thermo->gibbs_mole(), -313642293.1654253, 1e-4);
}