[Thermo] Fix creation of IonsFromNeutralVPSSTP objects
Added a mock input file derived from the initialization code in IonsFromNeutralVPSSTP and PDSS_IonsFromNeutral.
This commit is contained in:
parent
dfb32f0c7e
commit
3a119381e8
5 changed files with 123 additions and 24 deletions
|
|
@ -291,6 +291,7 @@ public:
|
|||
|
||||
virtual void initThermo();
|
||||
virtual void initThermoXML(XML_Node& phaseNode, const std::string& id);
|
||||
virtual void setParametersFromXML(const XML_Node& thermoNode);
|
||||
|
||||
private:
|
||||
//! Initialize lengths of local variables after all species have
|
||||
|
|
|
|||
|
|
@ -532,6 +532,29 @@ static double factorOverlap(const std::vector<std::string>& elnamesVN ,
|
|||
}
|
||||
return fMax;
|
||||
}
|
||||
|
||||
void IonsFromNeutralVPSSTP::setParametersFromXML(const XML_Node& thermoNode)
|
||||
{
|
||||
GibbsExcessVPSSTP::setParametersFromXML(thermoNode);
|
||||
// Find the Neutral Molecule Phase
|
||||
if (!thermoNode.hasChild("neutralMoleculePhase")) {
|
||||
throw CanteraError("IonsFromNeutralVPSSTP::initThermoXML",
|
||||
"no neutralMoleculePhase XML node");
|
||||
}
|
||||
XML_Node& neutralMoleculeNode = thermoNode.child("neutralMoleculePhase");
|
||||
|
||||
XML_Node* neut_ptr = get_XML_Node(neutralMoleculeNode["datasrc"], 0);
|
||||
if (!neut_ptr) {
|
||||
throw CanteraError("IonsFromNeutralVPSSTP::initThermoXML",
|
||||
"neut_ptr = 0");
|
||||
}
|
||||
|
||||
// Create the neutralMolecule ThermoPhase if we haven't already
|
||||
if (!neutralMoleculePhase_) {
|
||||
neutralMoleculePhase_ = newPhase(*neut_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void IonsFromNeutralVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id_)
|
||||
{
|
||||
if (id_.size() > 0 && phaseNode.id() != id_) {
|
||||
|
|
@ -553,24 +576,6 @@ void IonsFromNeutralVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string
|
|||
+ thermoNode["model"]);
|
||||
}
|
||||
|
||||
// Find the Neutral Molecule Phase
|
||||
if (!thermoNode.hasChild("neutralMoleculePhase")) {
|
||||
throw CanteraError("IonsFromNeutralVPSSTP::initThermoXML",
|
||||
"no neutralMoleculePhase XML node");
|
||||
}
|
||||
XML_Node& neutralMoleculeNode = thermoNode.child("neutralMoleculePhase");
|
||||
|
||||
XML_Node* neut_ptr = get_XML_Node(neutralMoleculeNode["datasrc"], 0);
|
||||
if (!neut_ptr) {
|
||||
throw CanteraError("IonsFromNeutralVPSSTP::initThermoXML",
|
||||
"neut_ptr = 0");
|
||||
}
|
||||
|
||||
// Create the neutralMolecule ThermoPhase if we haven't already
|
||||
if (!neutralMoleculePhase_) {
|
||||
neutralMoleculePhase_ = newPhase(*neut_ptr);
|
||||
}
|
||||
|
||||
cationList_.clear();
|
||||
for (size_t k = 0; k < m_kk; k++) {
|
||||
if (charge(k) > 0) {
|
||||
|
|
|
|||
|
|
@ -379,6 +379,14 @@ static SpeciesThermoInterpType* newAdsorbateThermoFromXML(const XML_Node& f)
|
|||
|
||||
SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& thermo)
|
||||
{
|
||||
std::string model = ba::to_lower_copy(thermo["model"]);
|
||||
if (model == "hkft" || model == "ionfromneutral") {
|
||||
// Some PDSS species use the 'thermo' node, but don't specify a
|
||||
// SpeciesThermoInterpType parameterization. This function needs to
|
||||
// just ignore this data.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the children of the thermo XML node. In the next bit of code we take
|
||||
// out the comments that may have been children of the thermo XML node by
|
||||
// doing a selective copy. These shouldn't interfere with the algorithm at
|
||||
|
|
@ -408,7 +416,6 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& thermo)
|
|||
"Too many regions in thermo parameterization.");
|
||||
}
|
||||
|
||||
std::string model = ba::to_lower_copy(thermo["model"]);
|
||||
if (model == "mineraleq3") {
|
||||
if (thermoType != "mineq3") {
|
||||
throw CanteraError("newSpeciesThermoInterpType",
|
||||
|
|
@ -427,11 +434,6 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& thermo)
|
|||
return newNasa9ThermoFromXML(tp);
|
||||
} else if (thermoType == "adsorbate") {
|
||||
return newAdsorbateThermoFromXML(*tp[0]);
|
||||
} else if (model == "hkft" || model == "ionfromneutral") {
|
||||
// Some PDSS species use the 'thermo' node, but don't specify a
|
||||
// SpeciesThermoInterpType parameterization. This function needs to just
|
||||
// ignore this data.
|
||||
return 0;
|
||||
} else {
|
||||
throw CanteraError("newSpeciesThermoInterpType",
|
||||
"Unknown species thermo model '" + thermoType + "'.");
|
||||
|
|
|
|||
81
test/data/mock_ion.xml
Normal file
81
test/data/mock_ion.xml
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
|
||||
<?xml version="1.0"?>
|
||||
<ctml>
|
||||
<validate reactions="yes" species="yes"/>
|
||||
|
||||
<phase dim="3" id="mock_ion_phase">
|
||||
<elementArray datasrc="elements.xml">
|
||||
K Cl
|
||||
</elementArray>
|
||||
<speciesArray datasrc="#species_data">
|
||||
K+ Cl-
|
||||
</speciesArray>
|
||||
<thermo model="IonsFromNeutralMolecule">
|
||||
<neutralMoleculePhase datasrc="../data/mock_ion.xml#mock_neutral" />
|
||||
<variablePressureStandardStateManager model="general" />
|
||||
<standardConc model="constant_volume" />
|
||||
</thermo>
|
||||
<transport model="None"/>
|
||||
<kinetics model="none"/>
|
||||
</phase>
|
||||
|
||||
<phase dim="3" id="mock_neutral">
|
||||
<elementArray datasrc="elements.xml">
|
||||
K Cl
|
||||
</elementArray>
|
||||
<speciesArray datasrc="#species_data">
|
||||
KCl(L)
|
||||
</speciesArray>
|
||||
<thermo model="Margules">
|
||||
<standardConc model="constant_volume" />
|
||||
<activityCoefficients model="Margules" TempModel="constant">
|
||||
</activityCoefficients>
|
||||
</thermo>
|
||||
<transport model="None"/>
|
||||
<kinetics model="none"/>
|
||||
</phase>
|
||||
|
||||
<!-- species definitions -->
|
||||
<speciesData id="species_data">
|
||||
<species name="K+">
|
||||
<atomArray> K:1 </atomArray>
|
||||
<charge> 1 </charge>
|
||||
<standardState model="IonFromNeutral" />
|
||||
<thermo model="IonFromNeutral">
|
||||
<neutralSpeciesMultipliers>
|
||||
KCl(L):1.2
|
||||
</neutralSpeciesMultipliers>
|
||||
</thermo>
|
||||
<density units="g/cm3"> 0.0 </density>
|
||||
</species>
|
||||
|
||||
<species name="Cl-">
|
||||
<atomArray> Cl:1 </atomArray>
|
||||
<charge> -1 </charge>
|
||||
<standardState model="IonFromNeutral" />
|
||||
<thermo model="IonFromNeutral">
|
||||
<specialSpecies/>
|
||||
<neutralSpeciesMultipliers>
|
||||
KCl(L):1.5
|
||||
</neutralSpeciesMultipliers>
|
||||
</thermo>
|
||||
<density units="g/cm3"> 0.0 </density>
|
||||
</species>
|
||||
|
||||
<species name="KCl(L)">
|
||||
<atomArray> K:1 Cl:1 </atomArray>
|
||||
<thermo>
|
||||
<Shomate Pref="1 bar" Tmax="2000.0" Tmin="700.0">
|
||||
<floatArray size="7">
|
||||
73.59698, 0.0, 0.0,
|
||||
0.0, 0.0, -443.7341,
|
||||
175.7209
|
||||
</floatArray>
|
||||
</Shomate>
|
||||
</thermo>
|
||||
<standardState model="constant_incompressible">
|
||||
<molarVolume units="cm3/gmol"> 37.57 </molarVolume>
|
||||
</standardState>
|
||||
</species>
|
||||
</speciesData>
|
||||
</ctml>
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
#include "cantera/thermo/PureFluidPhase.h"
|
||||
#include "cantera/thermo/WaterSSTP.h"
|
||||
#include "cantera/thermo/RedlichKwongMFTP.h"
|
||||
#include "cantera/thermo/IonsFromNeutralVPSSTP.h"
|
||||
#include "cantera/thermo/NasaPoly2.h"
|
||||
#include "cantera/thermo/ShomatePoly.h"
|
||||
#include "cantera/thermo/IdealGasPhase.h"
|
||||
|
|
@ -37,6 +38,15 @@ TEST_F(FixedChemPotSstpConstructorTest, SimpleConstructor)
|
|||
ASSERT_DOUBLE_EQ(-2.3e7, mu);
|
||||
}
|
||||
|
||||
TEST(IonsFromNeutralConstructor, fromXML)
|
||||
{
|
||||
std::unique_ptr<ThermoPhase> p(newPhase("../data/mock_ion.xml",
|
||||
"mock_ion_phase"));
|
||||
ASSERT_EQ((int) p->nSpecies(), 2);
|
||||
vector_fp mu(p->nSpecies());
|
||||
p->getPartialMolarEnthalpies(mu.data());
|
||||
}
|
||||
|
||||
#ifndef HAS_NO_PYTHON // skip these tests if the Python converter is unavailable
|
||||
class CtiConversionTest : public testing::Test
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue