[Base] implement initialization of C++ Solution from input files
- implement constructor that loads ThermoPhase, Kinetics, and Transport from input files (wrapping factory class methods) - logic for selection of transport manager follows Python object - add convenience methods to type-cast frequently used classes
This commit is contained in:
parent
43d02e95e3
commit
40ae5b5fb5
13 changed files with 155 additions and 27 deletions
|
|
@ -20,16 +20,38 @@ class Solution : public std::enable_shared_from_this<Solution>
|
|||
{
|
||||
private:
|
||||
Solution();
|
||||
Solution(const std::string& infile, std::string name, std::string transport,
|
||||
std::vector<shared_ptr<Solution> > adjacent);
|
||||
|
||||
public:
|
||||
~Solution() {}
|
||||
Solution(const Solution&) = delete;
|
||||
Solution& operator=(const Solution&) = delete;
|
||||
|
||||
//! Create an empty Solution object
|
||||
static shared_ptr<Solution> create() {
|
||||
return shared_ptr<Solution>( new Solution );
|
||||
}
|
||||
|
||||
//! Create and initialize a Solution object from an input file
|
||||
/*!
|
||||
* This constructor wraps newPhase(), newKinetics() and
|
||||
* newTransportMgr() routines for initialization.
|
||||
*
|
||||
* @param infile name of the input file
|
||||
* @param name name of the phase in the file.
|
||||
* If this is blank, the first phase in the file is used.
|
||||
* @param transport name of the transport model.
|
||||
* @param adjacent vector containing adjacent solution objects.
|
||||
* @returns an initialized Solution object.
|
||||
*/
|
||||
static shared_ptr<Solution> create(const std::string& infile,
|
||||
std::string name="",
|
||||
std::string transport="",
|
||||
std::vector<shared_ptr<Solution> > adjacent={}) {
|
||||
return shared_ptr<Solution>( new Solution(infile, name, transport, adjacent) );
|
||||
}
|
||||
|
||||
//! Return the name of this Solution object
|
||||
std::string name() const;
|
||||
|
||||
|
|
@ -60,11 +82,35 @@ public:
|
|||
return *m_transport;
|
||||
}
|
||||
|
||||
//! Accessor for the ThermoPhase pointer
|
||||
shared_ptr<ThermoPhase> thermoPtr() {
|
||||
return m_thermo;
|
||||
}
|
||||
|
||||
//! Accessor for the Kinetics pointer
|
||||
shared_ptr<Kinetics> kineticsPtr() {
|
||||
return m_kinetics;
|
||||
}
|
||||
|
||||
//! Accessor for the Transport pointer
|
||||
shared_ptr<Transport> transportPtr() {
|
||||
return m_transport;
|
||||
}
|
||||
|
||||
protected:
|
||||
shared_ptr<ThermoPhase> m_thermo; //!< ThermoPhase manager
|
||||
shared_ptr<Kinetics> m_kinetics; //!< Kinetics manager
|
||||
shared_ptr<Transport> m_transport; //!< Transport manager
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new solution manager.
|
||||
*/
|
||||
inline shared_ptr<Solution> newSolution(const std::string& infile, std::string name="",
|
||||
std::string transport="",
|
||||
std::vector<shared_ptr<Solution> > adjacent={}) {
|
||||
return Solution::create(infile, name, transport, adjacent);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -119,6 +119,19 @@ protected:
|
|||
void updateKc();
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a pointer to an GasKinetics object contained in Solution.
|
||||
*/
|
||||
inline shared_ptr<GasKinetics> getGasKineticsPtr(shared_ptr<Solution> sol) {
|
||||
auto kin = sol->kineticsPtr();
|
||||
if (kin->kineticsType()=="Surf") {
|
||||
return std::dynamic_pointer_cast<GasKinetics>(kin);
|
||||
} else {
|
||||
throw CanteraError("getGasKineticsPtr",
|
||||
"Incompatible kinetics");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -678,6 +678,20 @@ protected:
|
|||
//! EdgeKinetics)
|
||||
size_t m_nDim;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a pointer to an InterfaceKinetics object contained in Solution.
|
||||
*/
|
||||
inline shared_ptr<InterfaceKinetics> getInterfaceKineticsPtr(shared_ptr<Solution> sol) {
|
||||
auto kin = sol->kineticsPtr();
|
||||
if (kin->kineticsType()=="Surf") {
|
||||
return std::dynamic_pointer_cast<InterfaceKinetics>(kin);
|
||||
} else {
|
||||
throw CanteraError("getInterfaceKineticsPtr",
|
||||
"Incompatible kinetics");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@
|
|||
namespace Cantera
|
||||
{
|
||||
|
||||
class Solution;
|
||||
|
||||
/**
|
||||
* @defgroup chemkinetics Chemical Kinetics
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -631,6 +631,20 @@ private:
|
|||
*/
|
||||
void _updateThermo() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a pointer to an IdealGasPhase object contained in Solution.
|
||||
*/
|
||||
inline shared_ptr<IdealGasPhase> getIdealGasPhasePtr(shared_ptr<Solution> sol) {
|
||||
auto ph = sol->thermoPtr();
|
||||
if (ph->type()=="IdealGas") {
|
||||
return std::dynamic_pointer_cast<IdealGasPhase>(ph);
|
||||
} else {
|
||||
throw CanteraError("getIdealGasPhasePtr",
|
||||
"Incompatible phase");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#define CT_PHASE_H
|
||||
|
||||
#include "cantera/base/ctexceptions.h"
|
||||
#include "cantera/base/Solution.h"
|
||||
#include "cantera/thermo/Elements.h"
|
||||
#include "cantera/thermo/Species.h"
|
||||
#include "cantera/base/ValueCache.h"
|
||||
|
|
@ -29,8 +30,6 @@ namespace Cantera
|
|||
* support thermodynamic calculations (see \ref thermoprops).
|
||||
*/
|
||||
|
||||
class Solution;
|
||||
|
||||
//! Class Phase is the base class for phases of matter, managing the species and
|
||||
//! elements in a phase, as well as the independent variables of temperature,
|
||||
//! mass density, species mass/mole fraction, and other generalized forces and
|
||||
|
|
|
|||
|
|
@ -447,6 +447,20 @@ private:
|
|||
*/
|
||||
void _updateThermo(bool force=false) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a pointer to an SurfPhase object contained in Solution.
|
||||
*/
|
||||
inline shared_ptr<SurfPhase> getSurfPhasePtr(shared_ptr<Solution> sol) {
|
||||
auto ph = sol->thermoPtr();
|
||||
if (ph->type()=="Surf") {
|
||||
return std::dynamic_pointer_cast<SurfPhase>(ph);
|
||||
} else {
|
||||
throw CanteraError("getSurfPhasePtr",
|
||||
"Incompatible phase");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -74,8 +74,6 @@ const VelocityBasis VB_SPECIES_2 = 2;
|
|||
const VelocityBasis VB_SPECIES_3 = 3;
|
||||
//@}
|
||||
|
||||
class Solution;
|
||||
|
||||
//! Base class for transport property managers.
|
||||
/*!
|
||||
* All classes that compute transport properties for a single phase derive from
|
||||
|
|
|
|||
|
|
@ -64,6 +64,11 @@ public:
|
|||
setKineticsMgr(contents);
|
||||
}
|
||||
|
||||
void insert(shared_ptr<Solution> sol) {
|
||||
setThermoMgr(sol->thermo());
|
||||
setKineticsMgr(sol->kinetics());
|
||||
}
|
||||
|
||||
virtual void setKineticsMgr(Kinetics& kin);
|
||||
|
||||
virtual void setChemistry(bool cflag = true) {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ public:
|
|||
void insert(ThermoPhase& contents) {
|
||||
setThermoMgr(contents);
|
||||
}
|
||||
|
||||
void insert(shared_ptr<Solution> sol) {
|
||||
setThermoMgr(sol->thermo());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,14 +8,39 @@
|
|||
|
||||
#include "cantera/base/Solution.h"
|
||||
#include "cantera/thermo/ThermoPhase.h"
|
||||
#include "cantera/thermo/ThermoFactory.h"
|
||||
#include "cantera/kinetics/Kinetics.h"
|
||||
#include "cantera/kinetics/KineticsFactory.h"
|
||||
#include "cantera/transport/TransportBase.h"
|
||||
#include "cantera/transport/TransportFactory.h"
|
||||
|
||||
namespace Cantera
|
||||
{
|
||||
|
||||
Solution::Solution() {}
|
||||
|
||||
Solution::Solution(const std::string& infile, std::string name, std::string transport,
|
||||
std::vector<shared_ptr<Solution> > adjacent) {
|
||||
|
||||
// thermo phase
|
||||
m_thermo = shared_ptr<ThermoPhase>(newPhase(infile, name));
|
||||
|
||||
// kinetics
|
||||
std::vector<ThermoPhase*> phases;
|
||||
for (auto & adj : adjacent) {
|
||||
phases.push_back(adj->thermoPtr().get());
|
||||
}
|
||||
phases.push_back(m_thermo.get());
|
||||
m_kinetics = std::move(newKinetics(phases, infile, name));
|
||||
|
||||
// transport
|
||||
if (transport=="") {
|
||||
m_transport = shared_ptr<Transport>(newDefaultTransportMgr(m_thermo.get()));
|
||||
} else if (transport!="None") {
|
||||
m_transport = shared_ptr<Transport>(newTransportMgr(transport, m_thermo.get()));
|
||||
}
|
||||
}
|
||||
|
||||
std::string Solution::name() const {
|
||||
if (m_thermo) {
|
||||
return m_thermo->name();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "cantera/base/Units.h"
|
||||
#include "cantera/IdealGasMix.h"
|
||||
#include "cantera/kinetics/GasKinetics.h"
|
||||
#include "cantera/thermo/SurfPhase.h"
|
||||
#include "cantera/kinetics/KineticsFactory.h"
|
||||
#include "cantera/thermo/ThermoFactory.h"
|
||||
|
|
@ -9,15 +9,13 @@ using namespace Cantera;
|
|||
|
||||
TEST(Reaction, ElementaryFromYaml)
|
||||
{
|
||||
// @TODO: Use of XML input files in these tests of the YAML format needs to
|
||||
// be eliminated before we can deprecate the XML format.
|
||||
IdealGasMix gas("gri30.xml");
|
||||
auto sol = newSolution("gri30.yaml");
|
||||
AnyMap rxn = AnyMap::fromYamlString(
|
||||
"{equation: N + NO <=> N2 + O,"
|
||||
" rate-constant: [-2.70000E+13 cm^3/mol/s, 0, 355 cal/mol],"
|
||||
" negative-A: true}");
|
||||
|
||||
auto R = newReaction(rxn, gas);
|
||||
auto R = newReaction(rxn, sol->kinetics());
|
||||
EXPECT_EQ(R->reactants.at("NO"), 1);
|
||||
EXPECT_EQ(R->products.at("N2"), 1);
|
||||
EXPECT_EQ(R->reaction_type, ELEMENTARY_RXN);
|
||||
|
|
@ -31,14 +29,14 @@ TEST(Reaction, ElementaryFromYaml)
|
|||
|
||||
TEST(Reaction, ThreeBodyFromYaml1)
|
||||
{
|
||||
IdealGasMix gas("gri30.xml");
|
||||
auto sol = newSolution("gri30.yaml");
|
||||
AnyMap rxn = AnyMap::fromYamlString(
|
||||
"{equation: 2 O + M = O2 + M,"
|
||||
" type: three-body,"
|
||||
" rate-constant: [1.20000E+17 cm^6/mol^2/s, -1, 0],"
|
||||
" efficiencies: {AR: 0.83, H2O: 5}}");
|
||||
|
||||
auto R = newReaction(rxn, gas);
|
||||
auto R = newReaction(rxn, sol->kinetics());
|
||||
EXPECT_EQ(R->reactants.count("M"), (size_t) 0);
|
||||
|
||||
auto TBR = dynamic_cast<ThreeBodyReaction&>(*R);
|
||||
|
|
@ -49,18 +47,18 @@ TEST(Reaction, ThreeBodyFromYaml1)
|
|||
|
||||
TEST(Reaction, ThreeBodyFromYaml2)
|
||||
{
|
||||
IdealGasMix gas("gri30.xml");
|
||||
auto sol = newSolution("gri30.yaml");
|
||||
AnyMap rxn = AnyMap::fromYamlString(
|
||||
"{equation: 2 O <=> O2," // Missing "M" on each side of the equation
|
||||
" type: three-body,"
|
||||
" rate-constant: [1.20000E+17, -1, 0]}");
|
||||
|
||||
EXPECT_THROW(newReaction(rxn, gas), CanteraError);
|
||||
EXPECT_THROW(newReaction(rxn, sol->kinetics()), CanteraError);
|
||||
}
|
||||
|
||||
TEST(Reaction, FalloffFromYaml1)
|
||||
{
|
||||
IdealGasMix gas("gri30.xml");
|
||||
auto sol = newSolution("gri30.yaml");
|
||||
AnyMap rxn = AnyMap::fromYamlString(
|
||||
"{equation: N2O (+M) = N2 + O (+ M),"
|
||||
" type: falloff,"
|
||||
|
|
@ -69,7 +67,7 @@ TEST(Reaction, FalloffFromYaml1)
|
|||
" SRI: {A: 1.1, B: 700.0, C: 1234.0, D: 56.0, E: 0.7},"
|
||||
" efficiencies: {AR: 0.625}}");
|
||||
|
||||
auto R = newReaction(rxn, gas);
|
||||
auto R = newReaction(rxn, sol->kinetics());
|
||||
auto FR = dynamic_cast<FalloffReaction&>(*R);
|
||||
EXPECT_DOUBLE_EQ(FR.third_body.efficiency("AR"), 0.625);
|
||||
EXPECT_DOUBLE_EQ(FR.third_body.efficiency("N2"), 1.0);
|
||||
|
|
@ -77,7 +75,7 @@ TEST(Reaction, FalloffFromYaml1)
|
|||
|
||||
TEST(Reaction, FalloffFromYaml2)
|
||||
{
|
||||
IdealGasMix gas("gri30.xml");
|
||||
auto sol = newSolution("gri30.yaml");
|
||||
AnyMap rxn = AnyMap::fromYamlString(
|
||||
"{equation: H + CH2 (+ N2) <=> CH3 (+N2),"
|
||||
" type: falloff,"
|
||||
|
|
@ -86,7 +84,7 @@ TEST(Reaction, FalloffFromYaml2)
|
|||
" Troe: {A: 0.562, T3: 91, T1: 5836},"
|
||||
" source: somewhere}");
|
||||
|
||||
auto R = newReaction(rxn, gas);
|
||||
auto R = newReaction(rxn, sol->kinetics());
|
||||
auto FR = dynamic_cast<FalloffReaction&>(*R);
|
||||
EXPECT_DOUBLE_EQ(FR.third_body.efficiency("N2"), 1.0);
|
||||
EXPECT_DOUBLE_EQ(FR.third_body.efficiency("H2O"), 0.0);
|
||||
|
|
@ -103,7 +101,7 @@ TEST(Reaction, FalloffFromYaml2)
|
|||
|
||||
TEST(Reaction, ChemicallyActivatedFromYaml)
|
||||
{
|
||||
IdealGasMix gas("gri30.xml");
|
||||
auto sol = newSolution("gri30.yaml");
|
||||
AnyMap rxn = AnyMap::fromYamlString(
|
||||
"{equation: CH3 + OH (+M) <=> CH2O + H2 (+M),"
|
||||
" units: {length: cm, quantity: mol},"
|
||||
|
|
@ -111,7 +109,7 @@ TEST(Reaction, ChemicallyActivatedFromYaml)
|
|||
" high-P-rate-constant: [5.88E-14, 6.721, -3022.227],"
|
||||
" low-P-rate-constant: [282320.078, 1.46878, -3270.56495]}");
|
||||
|
||||
auto R = newReaction(rxn, gas);
|
||||
auto R = newReaction(rxn, sol->kinetics());
|
||||
auto CAR = dynamic_cast<ChemicallyActivatedReaction&>(*R);
|
||||
EXPECT_DOUBLE_EQ(CAR.high_rate.preExponentialFactor(), 5.88e-14);
|
||||
EXPECT_DOUBLE_EQ(CAR.low_rate.preExponentialFactor(), 2.82320078e2);
|
||||
|
|
@ -120,7 +118,7 @@ TEST(Reaction, ChemicallyActivatedFromYaml)
|
|||
|
||||
TEST(Reaction, PlogFromYaml)
|
||||
{
|
||||
IdealGasMix gas("gri30.xml");
|
||||
auto sol = newSolution("gri30.yaml");
|
||||
AnyMap rxn = AnyMap::fromYamlString(
|
||||
"equation: 'H + CH4 <=> H2 + CH3'\n"
|
||||
"units: {pressure: atm}\n"
|
||||
|
|
@ -131,7 +129,7 @@ TEST(Reaction, PlogFromYaml)
|
|||
"- {P: 1.0 atm, A: 1.230000e+04, b: 2.68, Ea: 6335.0}\n"
|
||||
"- {P: 1.01325 MPa, A: 1.680000e+16, b: -0.6, Ea: 14754.0}");
|
||||
|
||||
auto R = newReaction(rxn, gas);
|
||||
auto R = newReaction(rxn, sol->kinetics());
|
||||
auto PR = dynamic_cast<PlogReaction&>(*R);
|
||||
const auto& rates = PR.rate.rates();
|
||||
EXPECT_EQ(rates.size(), (size_t) 4);
|
||||
|
|
@ -145,7 +143,7 @@ TEST(Reaction, PlogFromYaml)
|
|||
|
||||
TEST(Reaction, ChebyshevFromYaml)
|
||||
{
|
||||
IdealGasMix gas("gri30.xml");
|
||||
auto sol = newSolution("gri30.yaml");
|
||||
AnyMap rxn = AnyMap::fromYamlString(
|
||||
"equation: 'CH4 <=> CH3 + H'\n"
|
||||
"type: Chebyshev\n"
|
||||
|
|
@ -158,7 +156,7 @@ TEST(Reaction, ChebyshevFromYaml)
|
|||
" [-2.26210e-01, 1.69190e-01, 4.85810e-03, -2.38030e-03],\n"
|
||||
" [-1.43220e-01, 7.71110e-02, 1.27080e-02, -6.41540e-04]]\n");
|
||||
|
||||
auto R = newReaction(rxn, gas);
|
||||
auto R = newReaction(rxn, sol->kinetics());
|
||||
EXPECT_EQ(R->reactants.size(), (size_t) 1);
|
||||
auto CR = dynamic_cast<ChebyshevReaction&>(*R);
|
||||
double logP = std::log10(2e6);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "cantera/thermo/NasaPoly1.h"
|
||||
#include "cantera/IdealGasMix.h"
|
||||
#include "cantera/thermo/IdealGasPhase.h"
|
||||
|
||||
namespace Cantera
|
||||
{
|
||||
|
|
@ -94,7 +94,7 @@ TEST_F(NasaPoly1Test, updatePropertiesTemp)
|
|||
|
||||
|
||||
TEST(Nasa9Test, Nasa9Thermo) {
|
||||
IdealGasMix g("../data/gasNASA9.xml", "nasa9");
|
||||
IdealGasPhase g("gasNASA9.xml", "nasa9");
|
||||
size_t nsp = g.nSpecies();
|
||||
double pres = 1.0E5;
|
||||
vector_fp Xset(nsp, 0.0);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue