[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:
Ray Speth 2017-02-17 23:31:51 -05:00
parent dfb32f0c7e
commit 3a119381e8
5 changed files with 123 additions and 24 deletions

View file

@ -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

View file

@ -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) {

View file

@ -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
View 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>

View file

@ -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
{