From f1937bfadae6bcd4a9f289289f4cdebf31b25b90 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Mon, 4 Feb 2019 23:52:32 -0500 Subject: [PATCH] [Input] Create IdealSolidSolnPhase objects from YAML definitions --- include/cantera/thermo/IdealSolidSolnPhase.h | 15 +++---- src/thermo/IdealSolidSolnPhase.cpp | 37 +++++++++++++++-- src/thermo/ThermoFactory.cpp | 1 + test/data/thermo-models.yaml | 42 ++++++++++++++++++++ test/thermo/thermoFromYaml.cpp | 10 +++++ 5 files changed, 95 insertions(+), 10 deletions(-) diff --git a/include/cantera/thermo/IdealSolidSolnPhase.h b/include/cantera/thermo/IdealSolidSolnPhase.h index adf632e69..7de203f6c 100644 --- a/include/cantera/thermo/IdealSolidSolnPhase.h +++ b/include/cantera/thermo/IdealSolidSolnPhase.h @@ -575,19 +575,20 @@ public: //@{ virtual bool addSpecies(shared_ptr 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. diff --git a/src/thermo/IdealSolidSolnPhase.cpp b/src/thermo/IdealSolidSolnPhase.cpp index f82d4d472..07e10ab96 100644 --- a/src/thermo/IdealSolidSolnPhase.cpp +++ b/src/thermo/IdealSolidSolnPhase.cpp @@ -359,7 +359,29 @@ bool IdealSolidSolnPhase::addSpecies(shared_ptr 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(); + 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 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", diff --git a/src/thermo/ThermoFactory.cpp b/src/thermo/ThermoFactory.cpp index f8fd0e835..6ad6777ae 100644 --- a/src/thermo/ThermoFactory.cpp +++ b/src/thermo/ThermoFactory.cpp @@ -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(); }); diff --git a/test/data/thermo-models.yaml b/test/data/thermo-models.yaml index 5c6fe5220..f3076f73b 100644 --- a/test/data/thermo-models.yaml +++ b/test/data/thermo-models.yaml @@ -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 diff --git a/test/thermo/thermoFromYaml.cpp b/test/thermo/thermoFromYaml.cpp index cf8e23a6c..8f894eaa2 100644 --- a/test/thermo/thermoFromYaml.cpp +++ b/test/thermo/thermoFromYaml.cpp @@ -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); +}