mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
Add Interface class as a specialized version of Solution
This class provides access to the thermo and kinetics objects as the correct derived types, i.e. SurfPhase and InterfaceKinetics, so methods defined only for these derived types can be called easily.
This commit is contained in:
committed by
Ingmar Schoegl
parent
eff534ff50
commit
7785d6cf0e
@@ -48,6 +48,7 @@ phases:
|
||||
X: {CH4: 0.095, O2: 0.21, AR: 0.79}
|
||||
- name: Pt_surf
|
||||
thermo: ideal-surface
|
||||
adjacent-phases: [gas]
|
||||
elements: [Pt, H, O, C]
|
||||
species: [PT(S), H(S), H2O(S), OH(S), CO(S), CO2(S), CH3(S), CH2(S)s,
|
||||
CH(S), C(S), O(S)]
|
||||
|
||||
99
include/cantera/base/Interface.h
Normal file
99
include/cantera/base/Interface.h
Normal file
@@ -0,0 +1,99 @@
|
||||
//! @file Interface.h
|
||||
|
||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
||||
// at https://cantera.org/license.txt for license and copyright information.
|
||||
|
||||
#ifndef CT_INTERFACE_H
|
||||
#define CT_INTERFACE_H
|
||||
|
||||
#include "cantera/base/Solution.h"
|
||||
#include "cantera/thermo/SurfPhase.h"
|
||||
#include "cantera/kinetics/InterfaceKinetics.h"
|
||||
|
||||
namespace Cantera
|
||||
{
|
||||
|
||||
//! A container class holding managers for all pieces defining an interface
|
||||
class Interface : public Solution
|
||||
{
|
||||
private:
|
||||
Interface();
|
||||
|
||||
public:
|
||||
~Interface() {}
|
||||
Interface(const Interface&) = delete;
|
||||
Interface& operator=(const Interface&) = delete;
|
||||
|
||||
//! Create an empty Interface object
|
||||
static shared_ptr<Interface> create() {
|
||||
return shared_ptr<Interface>(new Interface());
|
||||
}
|
||||
|
||||
//! Set the reacting phase thermo object
|
||||
void setThermo(shared_ptr<ThermoPhase> thermo) override;
|
||||
|
||||
//! Set the Kinetics object
|
||||
void setKinetics(shared_ptr<Kinetics> kinetics) override;
|
||||
|
||||
//! Get the surface phase thermo object
|
||||
shared_ptr<SurfPhase> thermo() {
|
||||
return m_surf;
|
||||
}
|
||||
|
||||
//! Get the surface phase Kinetics object
|
||||
shared_ptr<InterfaceKinetics> kinetics() {
|
||||
return m_surfkin;
|
||||
}
|
||||
|
||||
protected:
|
||||
shared_ptr<SurfPhase> m_surf; //!< Surface phase ThermoPhase manager
|
||||
shared_ptr<InterfaceKinetics> m_surfkin; //!< Kinetics manager
|
||||
};
|
||||
|
||||
//! Create and initialize a new Interface from an input file
|
||||
/*!
|
||||
* This constructor wraps newPhase() and newKinetics()
|
||||
*
|
||||
* @param infile name of the input file
|
||||
* @param name name of the surface phase in the file.
|
||||
* If this is blank, the first phase in the file is used.
|
||||
* @param adjacent vector containing names of adjacent phases that participate in this
|
||||
* phases kinetics. If empty, adjacent phases will be instantiated based
|
||||
* on the phase definition.
|
||||
* @returns an initialized Interface object.
|
||||
*/
|
||||
shared_ptr<Interface> newInterface(const std::string& infile,
|
||||
const std::string& name="", const std::vector<std::string>& adjacent={});
|
||||
|
||||
|
||||
//! Create and initialize a new Interface from an input file
|
||||
/*!
|
||||
* This constructor wraps newPhase() and newKinetics()
|
||||
*
|
||||
* @param infile name of the input file
|
||||
* @param name name of the phase in the file. If this is the empty string, the first
|
||||
* phase in the file is used.
|
||||
* @param adjacent vector containing adjacent Solution objects. If empty, adjacent
|
||||
* phases will be instantiated based on the phase definition.
|
||||
* @returns an initialized Interface object.
|
||||
*/
|
||||
shared_ptr<Interface> newInterface(const std::string& infile,
|
||||
const std::string& name, const std::vector<shared_ptr<Solution>>& adjacent);
|
||||
|
||||
//! Create and initialize a new Interface from AnyMap objects
|
||||
/*!
|
||||
* This constructor wraps newPhase() and newKinetics()
|
||||
*
|
||||
* @param phaseNode the node containing the phase definition (i.e. thermo model,
|
||||
* list of species, and initial state)
|
||||
* @param rootNode the root node of the tree containing the phase definition, which
|
||||
* will be used as the default location from which to read species definitions.
|
||||
* @param adjacent vector containing adjacent Solution objects. If empty, adjacent
|
||||
* phases will be instantiated based on the phase definition.
|
||||
* @returns an initialized Interface object.
|
||||
*/
|
||||
shared_ptr<Interface> newInterface(AnyMap& phaseNode, const AnyMap& rootNode=AnyMap(),
|
||||
const std::vector<shared_ptr<Solution>>& adjacent={});
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -19,11 +19,11 @@ class Transport;
|
||||
//! A container class holding managers for all pieces defining a phase
|
||||
class Solution
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
Solution();
|
||||
|
||||
public:
|
||||
~Solution() {}
|
||||
virtual ~Solution() {}
|
||||
Solution(const Solution&) = delete;
|
||||
Solution& operator=(const Solution&) = delete;
|
||||
|
||||
@@ -39,13 +39,13 @@ public:
|
||||
void setName(const std::string& name);
|
||||
|
||||
//! Set the ThermoPhase object
|
||||
void setThermo(shared_ptr<ThermoPhase> thermo);
|
||||
virtual void setThermo(shared_ptr<ThermoPhase> thermo);
|
||||
|
||||
//! Set the Kinetics object
|
||||
void setKinetics(shared_ptr<Kinetics> kinetics);
|
||||
virtual void setKinetics(shared_ptr<Kinetics> kinetics);
|
||||
|
||||
//! Set the Transport object
|
||||
void setTransport(shared_ptr<Transport> transport);
|
||||
virtual void setTransport(shared_ptr<Transport> transport);
|
||||
|
||||
//! Accessor for the ThermoPhase pointer
|
||||
shared_ptr<ThermoPhase> thermo() {
|
||||
|
||||
74
src/base/Interface.cpp
Normal file
74
src/base/Interface.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
//! @file Interface.cpp
|
||||
|
||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
||||
// at https://cantera.org/license.txt for license and copyright information.
|
||||
|
||||
#include "cantera/base/Interface.h"
|
||||
#include "cantera/thermo/ThermoFactory.h"
|
||||
#include "cantera/kinetics/KineticsFactory.h"
|
||||
|
||||
namespace Cantera
|
||||
{
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
Interface::Interface() {}
|
||||
|
||||
void Interface::setThermo(shared_ptr<ThermoPhase> thermo) {
|
||||
Solution::setThermo(thermo);
|
||||
auto surf = std::dynamic_pointer_cast<SurfPhase>(thermo);
|
||||
if (!surf) {
|
||||
throw CanteraError("Interface::setThermo",
|
||||
"Thermo object of type '{}' does not descend from SurfPhase.",
|
||||
thermo->type());
|
||||
}
|
||||
m_surf = surf;
|
||||
}
|
||||
|
||||
void Interface::setKinetics(shared_ptr<Kinetics> kinetics) {
|
||||
Solution::setKinetics(kinetics);
|
||||
auto surfkin = std::dynamic_pointer_cast<InterfaceKinetics>(kinetics);
|
||||
if (!surfkin) {
|
||||
throw CanteraError("Interface::setKinetics",
|
||||
"Kinetics object of type '{}' does not descend from InterfaceKinetics.",
|
||||
kinetics->kineticsType());
|
||||
}
|
||||
m_surfkin = surfkin;
|
||||
}
|
||||
|
||||
shared_ptr<Interface> newInterface(const std::string& infile,
|
||||
const std::string& name, const std::vector<std::string>& adjacent)
|
||||
{
|
||||
auto sol = newSolution(infile, name, "", adjacent);
|
||||
auto iface = std::dynamic_pointer_cast<Interface>(sol);
|
||||
if (!iface) {
|
||||
auto rootNode = AnyMap::fromYamlFile(infile);
|
||||
AnyMap& phaseNode = rootNode["phases"].getMapWhere("name", name);
|
||||
throw InputFileError("newInterface", phaseNode,
|
||||
"Phase definition does not define a surface phase");
|
||||
}
|
||||
return iface;
|
||||
}
|
||||
|
||||
shared_ptr<Interface> newInterface(const std::string& infile,
|
||||
const std::string& name, const std::vector<shared_ptr<Solution>>& adjacent)
|
||||
{
|
||||
auto rootNode = AnyMap::fromYamlFile(infile);
|
||||
AnyMap& phaseNode = rootNode["phases"].getMapWhere("name", name);
|
||||
return newInterface(phaseNode, rootNode, adjacent);
|
||||
}
|
||||
|
||||
shared_ptr<Interface> newInterface(AnyMap& phaseNode, const AnyMap& rootNode,
|
||||
const std::vector<shared_ptr<Solution>>& adjacent)
|
||||
{
|
||||
auto sol = newSolution(phaseNode, rootNode, "", adjacent);
|
||||
auto iface = std::dynamic_pointer_cast<Interface>(sol);
|
||||
if (!iface) {
|
||||
throw InputFileError("newInterface", phaseNode,
|
||||
"Phase definition does not define a surface phase");
|
||||
}
|
||||
return iface;
|
||||
}
|
||||
|
||||
} // end namespace Cantera
|
||||
@@ -7,6 +7,7 @@
|
||||
// at https://cantera.org/license.txt for license and copyright information.
|
||||
|
||||
#include "cantera/base/Solution.h"
|
||||
#include "cantera/base/Interface.h"
|
||||
#include "cantera/thermo/ThermoPhase.h"
|
||||
#include "cantera/thermo/ThermoFactory.h"
|
||||
#include "cantera/kinetics/Kinetics.h"
|
||||
@@ -193,12 +194,20 @@ shared_ptr<Solution> newSolution(const AnyMap& phaseNode,
|
||||
const std::string& transport,
|
||||
const std::vector<shared_ptr<Solution>>& adjacent)
|
||||
{
|
||||
// instantiate Solution object
|
||||
auto sol = Solution::create();
|
||||
sol->setSource("custom YAML");
|
||||
|
||||
// thermo phase
|
||||
sol->setThermo(shared_ptr<ThermoPhase>(newPhase(phaseNode, rootNode)));
|
||||
auto thermo = shared_ptr<ThermoPhase>(newPhase(phaseNode, rootNode));
|
||||
|
||||
// instantiate Solution object of the correct derived type
|
||||
shared_ptr<Solution> sol;
|
||||
switch (thermo->nDim()) {
|
||||
case 2:
|
||||
sol = Interface::create();
|
||||
break;
|
||||
default:
|
||||
sol = Solution::create();
|
||||
}
|
||||
sol->setSource("custom YAML");
|
||||
sol->setThermo(thermo);
|
||||
|
||||
// Add explicitly-specified adjacent phases
|
||||
for (auto& adj : adjacent) {
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
#include "cantera/thermo.h"
|
||||
#include "cantera/kinetics.h"
|
||||
#include "cantera/thermo/IdealGasPhase.h"
|
||||
#include "cantera/thermo/SurfPhase.h"
|
||||
#include "cantera/kinetics/GasKinetics.h"
|
||||
#include "cantera/base/Solution.h"
|
||||
#include "cantera/base/Interface.h"
|
||||
|
||||
namespace Cantera
|
||||
{
|
||||
@@ -202,16 +202,14 @@ TEST_F(NegativePreexponentialFactor, fromYaml)
|
||||
}
|
||||
|
||||
TEST(InterfaceReaction, CoverageDependency) {
|
||||
IdealGasPhase gas("ptcombust.yaml", "gas");
|
||||
SurfPhase surf("ptcombust.yaml", "Pt_surf");
|
||||
shared_ptr<Kinetics> kin(newKinetics({&surf, &gas}, "ptcombust.yaml", "Pt_surf"));
|
||||
ASSERT_EQ(kin->nReactions(), (size_t) 24);
|
||||
auto iface = newInterface("ptcombust.yaml", "Pt_surf");
|
||||
ASSERT_EQ(iface->kinetics()->nReactions(), (size_t) 24);
|
||||
|
||||
double T = 500;
|
||||
surf.setState_TP(T, 101325);
|
||||
surf.setCoveragesByName("PT(S):0.7, H(S):0.3");
|
||||
vector_fp kf(kin->nReactions());
|
||||
kin->getFwdRateConstants(&kf[0]);
|
||||
iface->thermo()->setState_TP(T, 101325);
|
||||
iface->thermo()->setCoveragesByName("PT(S):0.7, H(S):0.3");
|
||||
vector_fp kf(iface->kinetics()->nReactions());
|
||||
iface->kinetics()->getFwdRateConstants(&kf[0]);
|
||||
EXPECT_NEAR(kf[0], 4.4579e7 * pow(T, 0.5), 1e-14*kf[0]);
|
||||
// Energies in XML file are converted from J/mol to J/kmol
|
||||
EXPECT_NEAR(kf[1], 3.7e20 * exp(-(67.4e6-6e6*0.3)/(GasConstant*T)), 1e-14*kf[1]);
|
||||
|
||||
@@ -22,6 +22,7 @@ phases:
|
||||
species: [CB-CB3]
|
||||
- name: soot_interface
|
||||
thermo: ideal-surface
|
||||
adjacent-phases: [gas, soot]
|
||||
elements: [H, C]
|
||||
species: [Csoot-*, Csoot-H]
|
||||
kinetics: surface
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Gas Temperature = 1.4e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
Gas Phase: gas (2)
|
||||
Name Conc MoleF SrcRate
|
||||
(kmol/m^3) (kmol/m^2/s)
|
||||
0 H 8.7e-05 0.00999 -2.366e-03
|
||||
@@ -15,7 +15,7 @@ Gas Phase: gas (0)
|
||||
9 O2 8.7e-06 0.000999 -9.061e-07
|
||||
Sum of gas mole fractions= 1
|
||||
|
||||
Bulk Phase: soot (10)
|
||||
Bulk Phase: soot (12)
|
||||
Bulk Temperature = 1.4e+03
|
||||
Bulk Pressure = 1.01e+05
|
||||
Name Conc MoleF SrcRate
|
||||
@@ -28,7 +28,7 @@ Density of bulk phase = 3.52e+03 kg / m^3
|
||||
= 3.52 gm / cm^3
|
||||
Sum of bulk mole fractions= 1
|
||||
|
||||
Surface Phase: soot_interface (11)
|
||||
Surface Phase: soot_interface (0)
|
||||
Surface Temperature = 1.4e+03
|
||||
Surface Pressure = 1.01e+05
|
||||
Name Coverage SrcRate
|
||||
@@ -37,7 +37,7 @@ Surface Pressure = 1.01e+05
|
||||
Sum of coverages = 1
|
||||
Gas Temperature = 1.4e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
Gas Phase: gas (2)
|
||||
Name Conc MoleF SrcRate
|
||||
(kmol/m^3) (kmol/m^2/s)
|
||||
0 H 0.000113 0.013 -3.122e-03
|
||||
@@ -52,7 +52,7 @@ Gas Phase: gas (0)
|
||||
9 O2 8.7e-06 0.000999 -9.129e-07
|
||||
Sum of gas mole fractions= 1
|
||||
|
||||
Bulk Phase: soot (10)
|
||||
Bulk Phase: soot (12)
|
||||
Bulk Temperature = 1.4e+03
|
||||
Bulk Pressure = 1.01e+05
|
||||
Name Conc MoleF SrcRate
|
||||
@@ -65,7 +65,7 @@ Density of bulk phase = 3.52e+03 kg / m^3
|
||||
= 3.52 gm / cm^3
|
||||
Sum of bulk mole fractions= 1
|
||||
|
||||
Surface Phase: soot_interface (11)
|
||||
Surface Phase: soot_interface (0)
|
||||
Surface Temperature = 1.4e+03
|
||||
Surface Pressure = 1.01e+05
|
||||
Name Coverage SrcRate
|
||||
@@ -74,7 +74,7 @@ Surface Pressure = 1.01e+05
|
||||
Sum of coverages = 1
|
||||
Gas Temperature = 1.5e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
Gas Phase: gas (2)
|
||||
Name Conc MoleF SrcRate
|
||||
(kmol/m^3) (kmol/m^2/s)
|
||||
0 H 0.000106 0.013 -3.833e-03
|
||||
@@ -89,7 +89,7 @@ Gas Phase: gas (0)
|
||||
9 O2 8.14e-06 0.000999 -1.324e-06
|
||||
Sum of gas mole fractions= 1
|
||||
|
||||
Bulk Phase: soot (10)
|
||||
Bulk Phase: soot (12)
|
||||
Bulk Temperature = 1.5e+03
|
||||
Bulk Pressure = 1.01e+05
|
||||
Name Conc MoleF SrcRate
|
||||
@@ -102,7 +102,7 @@ Density of bulk phase = 3.52e+03 kg / m^3
|
||||
= 3.52 gm / cm^3
|
||||
Sum of bulk mole fractions= 1
|
||||
|
||||
Surface Phase: soot_interface (11)
|
||||
Surface Phase: soot_interface (0)
|
||||
Surface Temperature = 1.5e+03
|
||||
Surface Pressure = 1.01e+05
|
||||
Name Coverage SrcRate
|
||||
@@ -111,7 +111,7 @@ Surface Pressure = 1.01e+05
|
||||
Sum of coverages = 1
|
||||
Gas Temperature = 1.5e+03
|
||||
Gas Pressure = 1.01e+05
|
||||
Gas Phase: gas (0)
|
||||
Gas Phase: gas (2)
|
||||
Name Conc MoleF SrcRate
|
||||
(kmol/m^3) (kmol/m^2/s)
|
||||
0 H 0.000106 0.013 -3.833e-03
|
||||
@@ -126,7 +126,7 @@ Gas Phase: gas (0)
|
||||
9 O2 8.14e-06 0.000999 -1.324e-06
|
||||
Sum of gas mole fractions= 1
|
||||
|
||||
Bulk Phase: soot (10)
|
||||
Bulk Phase: soot (12)
|
||||
Bulk Temperature = 1.5e+03
|
||||
Bulk Pressure = 1.01e+05
|
||||
Name Conc MoleF SrcRate
|
||||
@@ -139,7 +139,7 @@ Density of bulk phase = 3.52e+03 kg / m^3
|
||||
= 3.52 gm / cm^3
|
||||
Sum of bulk mole fractions= 1
|
||||
|
||||
Surface Phase: soot_interface (11)
|
||||
Surface Phase: soot_interface (0)
|
||||
Surface Temperature = 1.5e+03
|
||||
Surface Pressure = 1.01e+05
|
||||
Name Coverage SrcRate
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
||||
// at https://cantera.org/license.txt for license and copyright information.
|
||||
|
||||
#include "cantera/thermo/ThermoFactory.h"
|
||||
#include "cantera/base/Interface.h"
|
||||
#include "cantera/thermo/SurfPhase.h"
|
||||
#include "cantera/kinetics.h"
|
||||
#include "cantera/kinetics/ImplicitSurfChem.h"
|
||||
#include "cantera/kinetics/InterfaceKinetics.h"
|
||||
@@ -141,27 +142,22 @@ int main(int argc, char** argv)
|
||||
int ioflag = 1;
|
||||
|
||||
try {
|
||||
/*************************************************************/
|
||||
|
||||
|
||||
/************************************************************/
|
||||
ThermoPhase* gasTP = newPhase(infile, gasPhaseName);
|
||||
auto iface = newInterface(infile, surfParticlePhaseName);
|
||||
ThermoPhase* gasTP = iface->adjacent(gasPhaseName)->thermo().get();
|
||||
size_t nspGas = gasTP->nSpecies();
|
||||
cout << "Number of species = " << nspGas << endl;
|
||||
|
||||
ThermoPhase* bulkPhaseTP = newPhase(infile, bulkParticlePhaseName);
|
||||
ThermoPhase* bulkPhaseTP = iface->adjacent(bulkParticlePhaseName)->thermo().get();
|
||||
size_t nspBulk = bulkPhaseTP->nSpecies();
|
||||
cout << "Number of species in bulk phase named " <<
|
||||
bulkParticlePhaseName << " = " << nspBulk << endl;
|
||||
|
||||
ThermoPhase* surfPhaseTP = newPhase(infile, surfParticlePhaseName);
|
||||
ThermoPhase* surfPhaseTP = iface->thermo().get();
|
||||
size_t nsp_d100 = surfPhaseTP->nSpecies();
|
||||
cout << "Number of species in surface phase, " << surfParticlePhaseName
|
||||
<< " = " << nsp_d100 << endl;
|
||||
|
||||
auto kin = newKinetics({gasTP, bulkPhaseTP, surfPhaseTP},
|
||||
infile, surfParticlePhaseName);
|
||||
InterfaceKinetics* iKin_ptr = dynamic_cast<InterfaceKinetics*>(kin.get());
|
||||
InterfaceKinetics* iKin_ptr = iface->kinetics().get();
|
||||
size_t nr = iKin_ptr->nReactions();
|
||||
cout << "Number of reactions = " << nr << endl;
|
||||
|
||||
@@ -248,13 +244,6 @@ int main(int argc, char** argv)
|
||||
printGas(ofile, gasTP, iKin_ptr, src);
|
||||
printBulk(ofile, bulkPhaseTP, iKin_ptr, src);
|
||||
printSurf(ofile, surfPhaseTP, iKin_ptr, src) ;
|
||||
|
||||
delete gasTP;
|
||||
gasTP = 0;
|
||||
delete bulkPhaseTP;
|
||||
bulkPhaseTP = 0;
|
||||
delete surfPhaseTP;
|
||||
surfPhaseTP = 0;
|
||||
appdelete();
|
||||
} catch (CanteraError& err) {
|
||||
std::cout << err.what() << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user