added factories for FlowDevice and Wall objects

This commit is contained in:
Ingmar Schoegl 2019-04-27 23:56:24 -05:00 committed by Ray Speth
parent 751afa3c2b
commit 5d62f3bacc
25 changed files with 709 additions and 340 deletions

View file

@ -1,7 +1,7 @@
//! @file FlowDevice.h
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#ifndef CT_FLOWDEVICE_H
#define CT_FLOWDEVICE_H
@ -27,9 +27,7 @@ const int Valve_Type = 3;
class FlowDevice
{
public:
FlowDevice() : m_mdot(0.0), m_func(0), m_type(0),
m_nspin(0), m_nspout(0),
m_in(0), m_out(0) {}
FlowDevice();
virtual ~FlowDevice() {}
FlowDevice(const FlowDevice&) = delete;

View file

@ -0,0 +1,72 @@
//! @file FlowDeviceFactory.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 FLOWDEVICE_FACTORY_H
#define FLOWDEVICE_FACTORY_H
#include "cantera/base/FactoryBase.h"
#include "cantera/zeroD/FlowDevice.h"
namespace Cantera
{
class FlowDeviceFactory : public Factory<FlowDevice>
{
public:
static FlowDeviceFactory* factory() {
std::unique_lock<std::mutex> lock(flowDevice_mutex);
if (!s_factory) {
s_factory = new FlowDeviceFactory;
}
return s_factory;
}
virtual void deleteFactory() {
std::unique_lock<std::mutex> lock(flowDevice_mutex);
delete s_factory;
s_factory = 0;
}
//! Create a new flow device by type identifier.
/*!
* @param n the type to be created.
*/
virtual FlowDevice* newFlowDevice(int n);
//! Create a new flow device by type name.
/*!
* @param flowDeviceType the type to be created.
*/
virtual FlowDevice* newFlowDevice(const std::string& flowDeviceType);
//! Register a new flow device type identifier.
/*!
* @param name the name of the flow device type.
* @param type the type identifier of the flow device.
* Integer type identifiers are used by clib and matlab interfaces.
*/
void reg_type(const std::string& name, const int type) {
m_types[type] = name;
}
protected:
//! Map containing flow device type identifier / type name pairs.
std::unordered_map<int, std::string> m_types;
private:
static FlowDeviceFactory* s_factory;
static std::mutex flowDevice_mutex;
FlowDeviceFactory();
};
//! Create a FlowDevice object of the specified type
inline FlowDevice* newFlowDevice(const std::string& model)
{
return FlowDeviceFactory::factory()->newFlowDevice(model);
}
}
#endif

View file

@ -1,7 +1,7 @@
//! @file FlowReactor.h
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#ifndef CT_FLOWREACTOR_H
#define CT_FLOWREACTOR_H

View file

@ -1,7 +1,7 @@
//! @file ConstPressureReactor.h
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#ifndef CT_IDEALGASCONSTP_REACTOR_H
#define CT_IDEALGASCONSTP_REACTOR_H

View file

@ -1,7 +1,7 @@
//! @file IdealGasReactor.h
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#ifndef CT_IDEALGASREACTOR_H
#define CT_IDEALGASREACTOR_H

View file

@ -1,7 +1,7 @@
//! @file Reactor.h
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#ifndef CT_REACTOR_H
#define CT_REACTOR_H

View file

@ -1,7 +1,7 @@
//! @file ReactorBase.h
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#ifndef CT_REACTORBASE_H
#define CT_REACTORBASE_H
@ -12,7 +12,7 @@
namespace Cantera
{
class FlowDevice;
class Wall;
class WallBase;
class ReactorNet;
class ReactorSurface;
@ -111,12 +111,12 @@ public:
/*!
* `lr` = 0 if this reactor is to the left of the wall and `lr` = 1 if
* this reactor is to the right of the wall. This method is called
* automatically for both the left and right reactors by Wall::install.
* automatically for both the left and right reactors by WallBase::install.
*/
void addWall(Wall& w, int lr);
void addWall(WallBase& w, int lr);
//! Return a reference to the *n*-th Wall connected to this reactor.
Wall& wall(size_t n);
WallBase& wall(size_t n);
void addSurface(ReactorSurface* surf);
@ -239,7 +239,7 @@ protected:
doublereal m_pressure;
vector_fp m_state;
std::vector<FlowDevice*> m_inlet, m_outlet;
std::vector<Wall*> m_wall;
std::vector<WallBase*> m_wall;
std::vector<ReactorSurface*> m_surfaces;
vector_int m_lr;
std::string m_name;

View file

@ -1,12 +1,12 @@
//! @file ReactorFactory.h
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#ifndef REACTOR_FACTORY_H
#define REACTOR_FACTORY_H
#include "ReactorBase.h"
#include "cantera/zeroD/ReactorBase.h"
#include "cantera/base/FactoryBase.h"
namespace Cantera
@ -29,13 +29,32 @@ public:
s_factory = 0;
}
/**
* Create a new reactor.
//! Create a new reactor by type identifier.
/*!
* @param n the type to be created.
*/
virtual ReactorBase* newReactor(int n);
//! Create a new reactor by type name.
/*!
* @param reactorType the type to be created.
*/
virtual ReactorBase* newReactor(const std::string& reactorType);
//! Register a new reactor type identifier.
/*!
* @param name the name of the reactor type.
* @param type the type identifier of the reactor.
* Integer type identifiers are used by clib and matlab interfaces.
*/
void reg_type(const std::string& name, const int type) {
m_types[type] = name;
}
protected:
//! Map containing reactor type identifier / reactor type name pairs.
std::unordered_map<int, std::string> m_types;
private:
static ReactorFactory* s_factory;
static std::mutex reactor_mutex;

View file

@ -1,7 +1,7 @@
//! @file Reservoir.h
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#ifndef CT_RESERVOIR_H
#define CT_RESERVOIR_H

View file

@ -1,127 +1,81 @@
//! @file Wall.h Header file for class Wall.
//! @file Wall.h Header file for base class WallBase.
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#ifndef CT_WALL_H
#define CT_WALL_H
#include "cantera/base/ctexceptions.h"
#include "cantera/numerics/Func1.h"
#include "cantera/zeroD/ReactorBase.h"
#include "cantera/zeroD/ReactorSurface.h"
#include "cantera/zeroD/ReactorBase.h"
namespace Cantera
{
class Kinetics;
class SurfPhase;
class Func1;
//! Represents a wall between between two ReactorBase objects.
/*!
* Walls can move (changing the volume of the adjacent reactors) and allow heat
* transfer between reactors.
const int WallType = 1;
/**
* Base class for 'walls' (walls, pistons, etc.) connecting reactors.
* @ingroup reactor0
*/
class Wall
class WallBase
{
public:
Wall();
WallBase();
virtual ~Wall() {}
Wall(const Wall&) = delete;
Wall& operator=(const Wall&) = delete;
virtual ~WallBase() {}
WallBase(const WallBase&) = delete;
WallBase& operator=(const WallBase&) = delete;
//! String indicating the wall model implemented. Usually
//! corresponds to the name of the derived class.
virtual std::string type() const {
return "WallBase";
}
//! Rate of volume change (m^3/s) for the adjacent reactors.
/*!
* The volume rate of change is given by
* \f[
* \dot V = K A (P_{left} - P_{right}) + F(t)
* \f]
* where *K* is the specified expansion rate coefficient, *A* is the wall
* area, and *F(t)* is a specified function of time. Positive values for
* `vdot` correspond to increases in the volume of reactor on left, and
* decreases in the volume of the reactor on the right.
* This method is called by Reactor::evalWalls(). Base class method
* does nothing (i.e. constant volume), but may be overloaded.
*/
virtual doublereal vdot(doublereal t);
virtual double vdot(double t) {
return 0.0;
}
//! Heat flow rate through the wall (W).
/*!
* The heat flux is given by
* \f[
* Q = h A (T_{left} - T_{right}) + A G(t)
* \f]
* where *h* is the heat transfer coefficient, *A* is the wall area, and
* *G(t)* is a specified function of time. Positive values denote a flux
* from left to right.
* This method is called by Reactor::evalWalls(). Base class method
* does nothing (i.e. adiabatic wall), but may be overloaded.
*/
virtual doublereal Q(doublereal t);
virtual double Q(double t) {
return 0.0;
}
//! Area in m^2.
doublereal area() {
//! Area in (m^2).
double area() {
return m_area;
}
//! Set the area [m^2].
void setArea(doublereal a) {
m_area = a;
m_surf[0].setArea(a);
m_surf[1].setArea(a);
}
virtual void setArea(double a);
//! Get the area [m^2]
/*!
* Redundant function (same as WallBase::area()).
* @deprecated To be removed after Cantera 2.5.
*/
double getArea() const {
warn_deprecated("WallBase::getArea()",
"To be removed after Cantera 2.5. "
"Replace with WallBase::area().");
return m_area;
}
void setThermalResistance(doublereal Rth) {
m_rrth = 1.0/Rth;
}
//! Set the overall heat transfer coefficient [W/m^2/K].
void setHeatTransferCoeff(doublereal U) {
m_rrth = U;
}
//! Get the overall heat transfer coefficient [W/m^2/K].
double getHeatTransferCoeff() const {
return m_rrth;
}
//! Set the emissivity.
void setEmissivity(doublereal epsilon) {
if (epsilon > 1.0 || epsilon < 0.0) {
throw CanteraError("Wall::setEmissivity",
"emissivity must be between 0.0 and 1.0");
}
m_emiss = epsilon;
}
double getEmissivity() const {
return m_emiss;
}
//! Set the wall velocity to a specified function of time
void setVelocity(Func1* f=0) {
if (f) {
m_vf = f;
}
}
//! Set the expansion rate coefficient.
void setExpansionRateCoeff(doublereal k) {
m_k = k;
}
//! Get the expansion rate coefficient
double getExpansionRateCoeff() const {
return m_k;
}
//! Specify the heat flux function \f$ q_0(t) \f$.
void setHeatFlux(Func1* q) {
m_qf = q;
}
//! Install the wall between two reactors or reservoirs
bool install(ReactorBase& leftReactor, ReactorBase& rightReactor);
@ -149,12 +103,118 @@ protected:
std::vector<ReactorSurface> m_surf;
doublereal m_area, m_k, m_rrth;
doublereal m_emiss;
Func1* m_vf;
Func1* m_qf;
double m_area;
};
//! Represents a wall between between two ReactorBase objects.
/*!
* Walls can move (changing the volume of the adjacent reactors) and allow heat
* transfer between reactors.
*/
class Wall : public WallBase
{
public:
Wall();
//! String indicating the wall model implemented. Usually
//! corresponds to the name of the derived class.
virtual std::string type() const {
return "Wall";
}
//! Set the wall velocity to a specified function of time, i.e. \f$ v(t) \f$.
void setVelocity(Func1* f=0) {
if (f) {
m_vf = f;
}
}
//! Rate of volume change (m^3/s) for the adjacent reactors.
/*!
* The volume rate of change is given by
* \f[
* \dot V = K A (P_{left} - P_{right}) + F(t)
* \f]
* where *K* is the specified expansion rate coefficient, *A* is the wall
* area, and *F(t)* is a specified function of time. Positive values for
* `vdot` correspond to increases in the volume of reactor on left, and
* decreases in the volume of the reactor on the right.
*/
virtual double vdot(double t);
//! Specify the heat flux function \f$ q_0(t) \f$.
void setHeatFlux(Func1* q) {
m_qf = q;
}
//! Heat flow rate through the wall (W).
/*!
* The heat flux is given by
* \f[
* Q = h A (T_{left} - T_{right}) + A G(t)
* \f]
* where *h* is the heat transfer coefficient, *A* is the wall area, and
* *G(t)* is a specified function of time. Positive values denote a flux
* from left to right.
*/
virtual double Q(double t);
void setThermalResistance(double Rth) {
m_rrth = 1.0/Rth;
}
//! Set the overall heat transfer coefficient [W/m^2/K].
void setHeatTransferCoeff(double U) {
m_rrth = U;
}
//! Get the overall heat transfer coefficient [W/m^2/K].
double getHeatTransferCoeff() const {
return m_rrth;
}
//! Set the emissivity.
void setEmissivity(double epsilon) {
if (epsilon > 1.0 || epsilon < 0.0) {
throw CanteraError("WallBase::setEmissivity",
"emissivity must be between 0.0 and 1.0");
}
m_emiss = epsilon;
}
//! Get the emissivity.
double getEmissivity() const {
return m_emiss;
}
//! Set the expansion rate coefficient.
void setExpansionRateCoeff(double k) {
m_k = k;
}
//! Get the expansion rate coefficient
double getExpansionRateCoeff() const {
return m_k;
}
protected:
//! expansion rate coefficient
double m_k;
//! heat transfer coefficient
double m_rrth;
//! emissivity
double m_emiss;
//! Velocity function
Func1* m_vf;
//! Heat flux function
Func1* m_qf;
};
}
#endif

View file

@ -0,0 +1,72 @@
//! @file WallFactory.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 WALL_FACTORY_H
#define WALL_FACTORY_H
#include "cantera/base/FactoryBase.h"
#include "cantera/zeroD/Wall.h"
namespace Cantera
{
class WallFactory : public Factory<WallBase>
{
public:
static WallFactory* factory() {
std::unique_lock<std::mutex> lock(wall_mutex);
if (!s_factory) {
s_factory = new WallFactory;
}
return s_factory;
}
virtual void deleteFactory() {
std::unique_lock<std::mutex> lock(wall_mutex);
delete s_factory;
s_factory = 0;
}
//! Create a new wall by type identifier.
/*!
* @param n the type to be created.
*/
virtual WallBase* newWall(int n);
//! Create a new wall by type name.
/*!
* @param wallType the type to be created.
*/
virtual WallBase* newWall(const std::string& wallType);
//! Register a new wall type identifier.
/*!
* @param name the name of the wall type.
* @param type the type identifier of the wall.
* Integer type identifiers are used by clib and matlab interfaces.
*/
void reg_type(const std::string& name, const int type) {
m_types[type] = name;
}
protected:
//! Map containing wall type identifier / wall type name pairs.
std::unordered_map<int, std::string> m_types;
private:
static WallFactory* s_factory;
static std::mutex wall_mutex;
WallFactory();
};
//! Create a Wall object of the specified type
inline WallBase* newWall(const std::string& model)
{
return WallFactory::factory()->newWall(model);
}
}
#endif

View file

@ -1,17 +1,16 @@
//! @file flowControllers.h Some flow devices derived from class FlowDevice.
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#ifndef CT_FLOWCONTR_H
#define CT_FLOWCONTR_H
#include "FlowDevice.h"
#include "ReactorBase.h"
#include "cantera/numerics/Func1.h"
namespace Cantera
{
/**
* A class for mass flow controllers. The mass flow rate is constant or
* specified as a function of time..
@ -19,9 +18,7 @@ namespace Cantera
class MassFlowController : public FlowDevice
{
public:
MassFlowController() : FlowDevice() {
m_type = MFC_Type;
}
MassFlowController();
virtual bool ready() {
return FlowDevice::ready() && m_mdot >= 0.0;
@ -30,12 +27,7 @@ public:
/// If a function of time has been specified for mdot, then update the
/// stored mass flow rate. Otherwise, mdot is a constant, and does not
/// need updating.
virtual void updateMassFlowRate(doublereal time) {
if (m_func) {
m_mdot = m_func->eval(time);
}
m_mdot = std::max(m_mdot, 0.0);
}
virtual void updateMassFlowRate(double time);
};
/**
@ -46,9 +38,7 @@ public:
class PressureController : public FlowDevice
{
public:
PressureController() : FlowDevice(), m_master(0) {
m_type = PressureController_Type;
}
PressureController();
virtual bool ready() {
return FlowDevice::ready() && m_master != 0 && m_coeffs.size() == 1;
@ -68,15 +58,7 @@ public:
m_coeffs = {c};
}
virtual void updateMassFlowRate(doublereal time) {
if (!ready()) {
throw CanteraError("PressureController::updateMassFlowRate",
"Device is not ready; some parameters have not been set.");
}
m_mdot = m_master->massFlowRate(time)
+ m_coeffs[0]*(in().pressure() - out().pressure());
m_mdot = std::max(m_mdot, 0.0);
}
virtual void updateMassFlowRate(double time);
protected:
FlowDevice* m_master;
@ -92,9 +74,7 @@ protected:
class Valve : public FlowDevice
{
public:
Valve() : FlowDevice() {
m_type = Valve_Type;
}
Valve();
virtual bool ready() {
return FlowDevice::ready() && (m_coeffs.size() == 1 || m_func);
@ -111,19 +91,7 @@ public:
}
/// Compute the currrent mass flow rate, based on the pressure difference.
virtual void updateMassFlowRate(doublereal time) {
if (!ready()) {
throw CanteraError("Valve::updateMassFlowRate",
"Device is not ready; some parameters have not been set.");
}
double delta_P = in().pressure() - out().pressure();
if (m_func) {
m_mdot = m_func->eval(delta_P);
} else {
m_mdot = m_coeffs[0]*delta_P;
}
m_mdot = std::max(m_mdot, 0.0);
}
virtual void updateMassFlowRate(double time);
};
}

View file

@ -1,13 +1,34 @@
//! @file zerodim.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_INCL_ZERODIM_H
#define CT_INCL_ZERODIM_H
#include "zeroD/Reactor.h"
// reactor network
#include "zeroD/ReactorNet.h"
#include "zeroD/Reservoir.h"
#include "zeroD/Wall.h"
#include "zeroD/flowControllers.h"
#include "zeroD/FlowReactor.h"
#include "zeroD/ConstPressureReactor.h"
#include "zeroD/IdealGasReactor.h"
#include "zeroD/IdealGasConstPressureReactor.h"
// reactors
#include "cantera/zeroD/Reservoir.h"
#include "cantera/zeroD/Reactor.h"
#include "cantera/zeroD/FlowReactor.h"
#include "cantera/zeroD/ConstPressureReactor.h"
#include "cantera/zeroD/IdealGasReactor.h"
#include "cantera/zeroD/IdealGasConstPressureReactor.h"
// flow devices
#include "cantera/zeroD/flowControllers.h"
// walls
#include "cantera/zeroD/Wall.h"
// surface
#include "cantera/zeroD/ReactorSurface.h"
// factories
#include "cantera/zeroD/ReactorFactory.h"
#include "cantera/zeroD/FlowDeviceFactory.h"
#include "cantera/zeroD/WallFactory.h"
#endif

View file

@ -1,5 +1,5 @@
# This file is part of Cantera. See License.txt in the top-level directory or
# at http://www.cantera.org/license.txt for license and copyright information.
# at https://cantera.org/license.txt for license and copyright information.
# cython: language_level=3
from libcpp.vector cimport vector
@ -466,11 +466,20 @@ cdef extern from "cantera/equil/MultiPhase.h" namespace "Cantera":
double volume() except +translate_exception
cdef extern from "cantera/zeroD/ReactorBase.h" namespace "Cantera":
cdef extern from "cantera/zerodim.h" namespace "Cantera":
cdef cppclass CxxWall "Cantera::Wall"
cdef cppclass CxxReactorSurface "Cantera::ReactorSurface"
cdef cppclass CxxFlowDevice "Cantera::FlowDevice"
# factories
cdef CxxReactorBase* newReactor(string) except +translate_exception
cdef CxxFlowDevice* newFlowDevice(string) except +translate_exception
cdef CxxWallBase* newWall(string) except +translate_exception
# reactors
cdef cppclass CxxReactorBase "Cantera::ReactorBase":
CxxReactorBase()
void setThermoMgr(CxxThermoPhase&) except +translate_exception
@ -481,8 +490,6 @@ cdef extern from "cantera/zeroD/ReactorBase.h" namespace "Cantera":
void setName(string)
void setInitialVolume(double)
cdef extern from "cantera/zeroD/Reactor.h":
cdef cppclass CxxReactor "Cantera::Reactor" (CxxReactorBase):
CxxReactor()
void setKineticsMgr(CxxKinetics&)
@ -500,30 +507,20 @@ cdef extern from "cantera/zeroD/Reactor.h":
void addSensitivitySpeciesEnthalpy(size_t) except +translate_exception
size_t nSensParams()
cdef extern from "cantera/zeroD/FlowReactor.h":
cdef cppclass CxxFlowReactor "Cantera::FlowReactor" (CxxReactor):
CxxFlowReactor()
void setMassFlowRate(double) except +translate_exception
double speed()
double distance()
# walls
cdef extern from "cantera/zeroD/Wall.h":
cdef cppclass CxxWall "Cantera::Wall":
CxxWall()
cdef cppclass CxxWallBase "Cantera::WallBase":
CxxWallBase()
string type()
cbool install(CxxReactorBase&, CxxReactorBase&)
void setExpansionRateCoeff(double)
double getExpansionRateCoeff()
double area()
void setArea(double)
double getArea()
void setHeatTransferCoeff(double)
double getHeatTransferCoeff()
void setEmissivity(double) except +translate_exception
double getEmissivity()
void setVelocity(CxxFunc1*)
void setHeatFlux(CxxFunc1*)
void setKinetics(CxxKinetics*, CxxKinetics*)
void setCoverages(int, double*)
void setCoverages(int, Composition&) except +translate_exception
@ -534,8 +531,19 @@ cdef extern from "cantera/zeroD/Wall.h":
void addSensitivityReaction(int, size_t) except +translate_exception
size_t nSensParams(int)
cdef cppclass CxxWall "Cantera::Wall" (CxxWallBase):
CxxWall()
void setExpansionRateCoeff(double)
double getExpansionRateCoeff()
void setHeatTransferCoeff(double)
double getHeatTransferCoeff()
void setEmissivity(double) except +translate_exception
double getEmissivity()
void setVelocity(CxxFunc1*)
void setHeatFlux(CxxFunc1*)
# reactor surface
cdef extern from "cantera/zeroD/ReactorSurface.h":
cdef cppclass CxxReactorSurface "Cantera::ReactorSurface":
CxxReactorSurface()
double area()
@ -547,8 +555,8 @@ cdef extern from "cantera/zeroD/ReactorSurface.h":
void addSensitivityReaction(size_t) except +translate_exception
size_t nSensParams()
# flow devices
cdef extern from "cantera/zeroD/flowControllers.h":
cdef cppclass CxxFlowDevice "Cantera::FlowDevice":
CxxFlowDevice()
double massFlowRate(double) except +translate_exception
@ -567,8 +575,8 @@ cdef extern from "cantera/zeroD/flowControllers.h":
void setPressureCoeff(double)
void setMaster(CxxFlowDevice*)
# reactor net
cdef extern from "cantera/zeroD/ReactorNet.h":
cdef cppclass CxxReactorNet "Cantera::ReactorNet":
CxxReactorNet()
void addReactor(CxxReactor&)
@ -612,9 +620,6 @@ cdef extern from "cantera/transport/TransportFactory.h" namespace "Cantera":
cdef CxxTransport* newDefaultTransportMgr(CxxThermoPhase*) except +translate_exception
cdef CxxTransport* newTransportMgr(string, CxxThermoPhase*) except +translate_exception
cdef extern from "cantera/zeroD/ReactorFactory.h" namespace "Cantera":
cdef CxxReactorBase* newReactor(string) except +translate_exception
cdef extern from "cantera/oneD/Domain1D.h":
cdef cppclass CxxDomain1D "Cantera::Domain1D":
size_t domainIndex()
@ -974,13 +979,13 @@ cdef class ReactorSurface:
cdef Kinetics _kinetics
cdef class WallSurface:
cdef CxxWall* cxxwall
cdef CxxWallBase* cxxwall
cdef object wall
cdef int side
cdef Kinetics _kinetics
cdef class Wall:
cdef CxxWall wall
cdef class WallBase:
cdef CxxWallBase* wall
cdef WallSurface left_surface
cdef WallSurface right_surface
cdef object _velocity_func
@ -989,6 +994,9 @@ cdef class Wall:
cdef ReactorBase _right_reactor
cdef str name
cdef class Wall(WallBase):
pass
cdef class FlowDevice:
cdef CxxFlowDevice* dev
cdef Func1 _rate_func

View file

@ -1,5 +1,5 @@
# This file is part of Cantera. See License.txt in the top-level directory or
# at http://www.cantera.org/license.txt for license and copyright information.
# at https://cantera.org/license.txt for license and copyright information.
from collections import defaultdict as _defaultdict
import numbers as _numbers
@ -450,33 +450,13 @@ cdef class ReactorSurface:
self.surface.addSensitivityReaction(m)
cdef class Wall:
r"""
A Wall separates two reactors, or a reactor and a reservoir. A wall has a
finite area, may conduct or radiate heat between the two reactors on either
side, and may move like a piston.
Walls are stateless objects in Cantera, meaning that no differential
equation is integrated to determine any wall property. Since it is the wall
(piston) velocity that enters the energy equation, this means that it is
the velocity, not the acceleration or displacement, that is specified.
The wall velocity is computed from
.. math:: v = K(P_{\rm left} - P_{\rm right}) + v_0(t),
where :math:`K` is a non-negative constant, and :math:`v_0(t)` is a
specified function of time. The velocity is positive if the wall is
moving to the right.
The heat flux through the wall is computed from
.. math:: q = U(T_{\rm left} - T_{\rm right}) + \epsilon\sigma (T_{\rm left}^4 - T_{\rm right}^4) + q_0(t),
where :math:`U` is the overall heat transfer coefficient for
conduction/convection, and :math:`\epsilon` is the emissivity. The function
:math:`q_0(t)` is a specified function of time. The heat flux is positive
when heat flows from the reactor on the left to the reactor on the right.
cdef class WallBase:
"""
Common base class for walls.
"""
wall_type = "None"
def __cinit__(self, *args, **kwargs):
self.wall = newWall(stringify(self.wall_type))
# The signature of this function causes warnings for Sphinx documentation
def __init__(self, left, right, *, name=None, A=None, K=None, U=None,
@ -540,6 +520,11 @@ cdef class Wall:
self._left_reactor = left
self._right_reactor = right
property type:
""" The left surface of this wall. """
def __get__(self):
return pystr(self.wall.type())
property left:
""" The left surface of this wall. """
def __get__(self):
@ -550,16 +535,6 @@ cdef class Wall:
def __get__(self):
return self.right_surface
property expansion_rate_coeff:
"""
The coefficient *K* [m/s/Pa] that determines the velocity of the wall
as a function of the pressure difference between the adjacent reactors.
"""
def __get__(self):
return self.wall.getExpansionRateCoeff()
def __set__(self, double val):
self.wall.setExpansionRateCoeff(val)
property area:
""" The wall area [m^2]. """
def __get__(self):
@ -567,48 +542,6 @@ cdef class Wall:
def __set__(self, double value):
self.wall.setArea(value)
property heat_transfer_coeff:
"""the overall heat transfer coefficient [W/m^2/K]"""
def __get__(self):
return self.wall.getHeatTransferCoeff()
def __set__(self, double value):
self.wall.setHeatTransferCoeff(value)
property emissivity:
"""The emissivity (nondimensional)"""
def __get__(self):
return self.wall.getEmissivity()
def __set__(self, double value):
self.wall.setEmissivity(value)
def set_velocity(self, v):
"""
The wall velocity [m/s]. May be either a constant or an arbitrary
function of time. See `Func1`.
"""
cdef Func1 f
if isinstance(v, Func1):
f = v
else:
f = Func1(v)
self._velocity_func = f
self.wall.setVelocity(f.func)
def set_heat_flux(self, q):
"""
Heat flux [W/m^2] across the wall. May be either a constant or
an arbitrary function of time. See `Func1`.
"""
cdef Func1 f
if isinstance(q, Func1):
f = q
else:
f = Func1(q)
self._heat_flux_func = f
self.wall.setHeatFlux(f.func)
def vdot(self, double t):
"""
The rate of volumetric change [m^3/s] associated with the wall
@ -626,6 +559,88 @@ cdef class Wall:
return self.wall.Q(t)
cdef class Wall(WallBase):
r"""
A Wall separates two reactors, or a reactor and a reservoir. A wall has a
finite area, may conduct or radiate heat between the two reactors on either
side, and may move like a piston.
Walls are stateless objects in Cantera, meaning that no differential
equation is integrated to determine any wall property. Since it is the wall
(piston) velocity that enters the energy equation, this means that it is
the velocity, not the acceleration or displacement, that is specified.
The wall velocity is computed from
.. math:: v = K(P_{\rm left} - P_{\rm right}) + v_0(t),
where :math:`K` is a non-negative constant, and :math:`v_0(t)` is a
specified function of time. The velocity is positive if the wall is
moving to the right.
The heat flux through the wall is computed from
.. math:: q = U(T_{\rm left} - T_{\rm right}) + \epsilon\sigma (T_{\rm left}^4 - T_{\rm right}^4) + q_0(t),
where :math:`U` is the overall heat transfer coefficient for
conduction/convection, and :math:`\epsilon` is the emissivity. The function
:math:`q_0(t)` is a specified function of time. The heat flux is positive
when heat flows from the reactor on the left to the reactor on the right.
"""
wall_type = "Wall"
property expansion_rate_coeff:
"""
The coefficient *K* [m/s/Pa] that determines the velocity of the wall
as a function of the pressure difference between the adjacent reactors.
"""
def __get__(self):
return (<CxxWall*>(self.wall)).getExpansionRateCoeff()
def __set__(self, double val):
(<CxxWall*>(self.wall)).setExpansionRateCoeff(val)
property heat_transfer_coeff:
"""the overall heat transfer coefficient [W/m^2/K]"""
def __get__(self):
return (<CxxWall*>(self.wall)).getHeatTransferCoeff()
def __set__(self, double value):
(<CxxWall*>(self.wall)).setHeatTransferCoeff(value)
property emissivity:
"""The emissivity (nondimensional)"""
def __get__(self):
return (<CxxWall*>(self.wall)).getEmissivity()
def __set__(self, double value):
(<CxxWall*>(self.wall)).setEmissivity(value)
def set_velocity(self, v):
"""
The wall velocity [m/s]. May be either a constant or an arbitrary
function of time. See `Func1`.
"""
cdef Func1 f
if isinstance(v, Func1):
f = v
else:
f = Func1(v)
self._velocity_func = f
(<CxxWall*>(self.wall)).setVelocity(f.func)
def set_heat_flux(self, q):
"""
Heat flux [W/m^2] across the wall. May be either a constant or
an arbitrary function of time. See `Func1`.
"""
cdef Func1 f
if isinstance(q, Func1):
f = q
else:
f = Func1(q)
self._heat_flux_func = f
(<CxxWall*>self.wall).setHeatFlux(f.func)
cdef class FlowDevice:
"""
Base class for devices that allow flow between reactors.
@ -637,9 +652,9 @@ cdef class FlowDevice:
across a FlowDevice, and the pressure difference equals the difference in
pressure between the upstream and downstream reactors.
"""
flowdevice_type = "None"
def __cinit__(self, *args, **kwargs):
# Children of this abstract class are responsible for allocating dev
self.dev = NULL
self.dev = newFlowDevice(stringify(self.flowdevice_type))
# The signature of this function causes warnings for Sphinx documentation
def __init__(self, upstream, downstream, *, name=None):
@ -698,8 +713,7 @@ cdef class MassFlowController(FlowDevice):
that this capability should be used with caution, since no account is
taken of the work required to do this.
"""
def __cinit__(self, *args, **kwargs):
self.dev = new CxxMassFlowController()
flowdevice_type = "MassFlowController"
# The signature of this function causes warnings for Sphinx documentation
def __init__(self, upstream, downstream, *, name=None, mdot=None):
@ -751,8 +765,7 @@ cdef class Valve(FlowDevice):
value, very small pressure differences will result in flow between the
reactors that counteracts the pressure difference.
"""
def __cinit__(self, *args, **kwargs):
self.dev = new CxxValve()
flowdevice_type = "Valve"
# The signature of this function causes warnings for Sphinx documentation
def __init__(self, upstream, downstream, *, name=None, K=None):
@ -797,8 +810,7 @@ cdef class PressureController(FlowDevice):
.. math:: \dot m = \dot m_{\rm master} + K_v(P_1 - P_2).
"""
def __cinit__(self, *args, **kwargs):
self.dev = new CxxPressureController()
flowdevice_type = "PressureController"
# The signature of this function causes warnings for Sphinx documentation
def __init__(self, upstream, downstream, *, name=None, master=None, K=None):

View file

@ -156,6 +156,11 @@ class TestReactor(utilities.CanteraTest):
self.assertLessEqual(self.net.time, max_steps * max_step_size)
self.assertEqual(self.net.max_steps, max_steps)
def test_wall_type(self):
self.make_reactors(P1=101325, P2=300000)
self.add_wall(K=0.1, A=1.0)
self.assertEqual(self.w.type, "Wall")
def test_equalize_pressure(self):
self.make_reactors(P1=101325, P2=300000)
self.add_wall(K=0.1, A=1.0)

View file

@ -3,18 +3,14 @@
*/
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#define CANTERA_USE_INTERNAL
#include "cantera/clib/ctreactor.h"
// Cantera includes
#include "cantera/zeroD/Reactor.h"
#include "cantera/zeroD/FlowReactor.h"
#include "cantera/zeroD/ReactorNet.h"
#include "cantera/zeroD/ReactorFactory.h"
#include "cantera/zeroD/Wall.h"
#include "cantera/zeroD/flowControllers.h"
#include "cantera/numerics/Func1.h"
#include "cantera/zerodim.h"
#include "Cabinet.h"
using namespace Cantera;
@ -23,7 +19,7 @@ using namespace std;
typedef Cabinet<ReactorBase> ReactorCabinet;
typedef Cabinet<ReactorNet> NetworkCabinet;
typedef Cabinet<FlowDevice> FlowDeviceCabinet;
typedef Cabinet<Wall> WallCabinet;
typedef Cabinet<WallBase> WallCabinet;
typedef Cabinet<Func1> FuncCabinet;
typedef Cabinet<ThermoPhase> ThermoCabinet;
typedef Cabinet<Kinetics> KineticsCabinet;
@ -351,21 +347,8 @@ extern "C" {
int flowdev_new(int type)
{
try {
FlowDevice* r;
switch (type) {
case MFC_Type:
r = new MassFlowController();
break;
case PressureController_Type:
r = new PressureController();
break;
case Valve_Type:
r = new Valve();
break;
default:
r = new FlowDevice();
}
return FlowDeviceCabinet::add(r);
FlowDevice* f = FlowDeviceFactory::factory()->newFlowDevice(type);
return FlowDeviceCabinet::add(f);
} catch (...) {
return handleAllExceptions(-1, ERR);
}
@ -450,7 +433,8 @@ extern "C" {
int wall_new(int type)
{
try {
return WallCabinet::add(new Wall());
WallBase* w = WallFactory::factory()->newWall(type);
return WallCabinet::add(w);
} catch (...) {
return handleAllExceptions(-1, ERR);
}
@ -517,7 +501,7 @@ extern "C" {
int wall_setThermalResistance(int i, double rth)
{
try {
WallCabinet::item(i).setThermalResistance(rth);
WallCabinet::get<Wall>(i).setThermalResistance(rth);
return 0;
} catch (...) {
return handleAllExceptions(-1, ERR);
@ -527,7 +511,7 @@ extern "C" {
int wall_setHeatTransferCoeff(int i, double u)
{
try {
WallCabinet::item(i).setHeatTransferCoeff(u);
WallCabinet::get<Wall>(i).setHeatTransferCoeff(u);
return 0;
} catch (...) {
return handleAllExceptions(-1, ERR);
@ -537,7 +521,7 @@ extern "C" {
int wall_setHeatFlux(int i, int n)
{
try {
WallCabinet::item(i).setHeatFlux(&FuncCabinet::item(n));
WallCabinet::get<Wall>(i).setHeatFlux(&FuncCabinet::item(n));
return 0;
} catch (...) {
return handleAllExceptions(-1, ERR);
@ -547,7 +531,7 @@ extern "C" {
int wall_setExpansionRateCoeff(int i, double k)
{
try {
WallCabinet::item(i).setExpansionRateCoeff(k);
WallCabinet::get<Wall>(i).setExpansionRateCoeff(k);
return 0;
} catch (...) {
return handleAllExceptions(-1, ERR);
@ -557,7 +541,7 @@ extern "C" {
int wall_setVelocity(int i, int n)
{
try {
WallCabinet::item(i).setVelocity(&FuncCabinet::item(n));
WallCabinet::get<Wall>(i).setVelocity(&FuncCabinet::item(n));
return 0;
} catch (...) {
return handleAllExceptions(-1, ERR);
@ -567,7 +551,7 @@ extern "C" {
int wall_setEmissivity(int i, double epsilon)
{
try {
WallCabinet::item(i).setEmissivity(epsilon);
WallCabinet::get<Wall>(i).setEmissivity(epsilon);
return 0;
} catch (...) {
return handleAllExceptions(-1, ERR);

View file

@ -10,6 +10,10 @@
namespace Cantera
{
FlowDevice::FlowDevice() : m_mdot(0.0), m_func(0), m_type(0),
m_nspin(0), m_nspout(0),
m_in(0), m_out(0) {}
bool FlowDevice::install(ReactorBase& in, ReactorBase& out)
{
if (m_in || m_out) {

View file

@ -0,0 +1,43 @@
//! @file FlowDeviceFactory.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/zeroD/FlowDeviceFactory.h"
#include "cantera/zeroD/flowControllers.h"
using namespace std;
namespace Cantera
{
FlowDeviceFactory* FlowDeviceFactory::s_factory = 0;
std::mutex FlowDeviceFactory::flowDevice_mutex;
FlowDeviceFactory::FlowDeviceFactory()
{
reg("MassFlowController", []() { return new MassFlowController(); });
reg("PressureController", []() { return new PressureController(); });
reg("Valve", []() { return new Valve(); });
// only used by clib
reg_type("MassFlowController", MFC_Type);
reg_type("PressureController", PressureController_Type);
reg_type("Valve", Valve_Type);
}
FlowDevice* FlowDeviceFactory::newFlowDevice(const std::string& flowDeviceType)
{
return create(flowDeviceType);
}
FlowDevice* FlowDeviceFactory::newFlowDevice(int ir)
{
try {
return create(m_types.at(ir));
} catch (out_of_range&) {
throw CanteraError("FlowDeviceFactory::newFlowDevice",
"unknown flowDevice type!");
}
}
}

View file

@ -1,7 +1,7 @@
//! @file Reactor.cpp A zero-dimensional reactor
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#include "cantera/zeroD/Reactor.h"
#include "cantera/zeroD/FlowDevice.h"
@ -87,7 +87,7 @@ void Reactor::initialize(doublereal t0)
m_intEnergy = m_thermo->intEnergy_mass();
for (size_t n = 0; n < m_wall.size(); n++) {
Wall* W = m_wall[n];
WallBase* W = m_wall[n];
W->initialize();
}

View file

@ -1,7 +1,7 @@
//! @file ReactorBase.cpp
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#include "cantera/zeroD/ReactorBase.h"
#include "cantera/zeroD/FlowDevice.h"
@ -54,7 +54,7 @@ void ReactorBase::addOutlet(FlowDevice& outlet)
m_outlet.push_back(&outlet);
}
void ReactorBase::addWall(Wall& w, int lr)
void ReactorBase::addWall(WallBase& w, int lr)
{
m_wall.push_back(&w);
if (lr == 0) {
@ -64,7 +64,7 @@ void ReactorBase::addWall(Wall& w, int lr)
}
}
Wall& ReactorBase::wall(size_t n)
WallBase& ReactorBase::wall(size_t n)
{
return *m_wall[n];
}

View file

@ -1,7 +1,7 @@
//! @file ReactorFactory.cpp
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#include "cantera/zeroD/ReactorFactory.h"
#include "cantera/zeroD/Reservoir.h"
@ -15,6 +15,8 @@ using namespace std;
namespace Cantera
{
class Reservoir;
ReactorFactory* ReactorFactory::s_factory = 0;
std::mutex ReactorFactory::reactor_mutex;
@ -26,6 +28,14 @@ ReactorFactory::ReactorFactory()
reg("FlowReactor", []() { return new FlowReactor(); });
reg("IdealGasReactor", []() { return new IdealGasReactor(); });
reg("IdealGasConstPressureReactor", []() { return new IdealGasConstPressureReactor(); });
// only used by clib
reg_type("Reservoir", ReservoirType);
reg_type("Reactor", ReactorType);
reg_type("ConstPressureReactor", ConstPressureReactorType);
reg_type("FlowReactor", FlowReactorType);
reg_type("IdealGasReactor", IdealGasReactorType);
reg_type("IdealGasConstPressureReactor", IdealGasConstPressureReactorType);
}
ReactorBase* ReactorFactory::newReactor(const std::string& reactorType)
@ -33,20 +43,10 @@ ReactorBase* ReactorFactory::newReactor(const std::string& reactorType)
return create(reactorType);
}
ReactorBase* ReactorFactory::newReactor(int ir)
{
static const unordered_map<int, string> types {
{ReservoirType, "Reservoir"},
{ReactorType, "Reactor"},
{ConstPressureReactorType, "ConstPressureReactor"},
{FlowReactorType, "FlowReactor"},
{IdealGasReactorType, "IdealGasReactor"},
{IdealGasConstPressureReactorType, "IdealGasConstPressureReactor"}
};
try {
return create(types.at(ir));
return create(m_types.at(ir));
} catch (out_of_range&) {
throw CanteraError("ReactorFactory::newReactor",
"unknown reactor type!");

View file

@ -1,24 +1,19 @@
//! @file Wall.cpp
//! @file WallBase.cpp
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
// at https://cantera.org/license.txt for license and copyright information.
#include "cantera/zeroD/Wall.h"
#include "cantera/zeroD/ReactorNet.h"
#include "cantera/numerics/Func1.h"
#include "cantera/thermo/SurfPhase.h"
#include "cantera/base/stringUtils.h"
#include "cantera/numerics/Func1.h"
#include "cantera/zeroD/Wall.h"
#include "cantera/thermo/SurfPhase.h"
namespace Cantera
{
Wall::Wall() : m_left(0), m_right(0),
m_surf(2),
m_area(1.0), m_k(0.0), m_rrth(0.0), m_emiss(0.0),
m_vf(0), m_qf(0)
{
}
bool Wall::install(ReactorBase& rleft, ReactorBase& rright)
WallBase::WallBase() : m_left(0), m_right(0), m_surf(2), m_area(1.0) {}
bool WallBase::install(ReactorBase& rleft, ReactorBase& rright)
{
// check if wall is already installed
if (m_left || m_right) {
@ -33,16 +28,25 @@ bool Wall::install(ReactorBase& rleft, ReactorBase& rright)
return true;
}
doublereal Wall::vdot(doublereal t)
{
double rate1 = m_k * m_area * (m_left->pressure() - m_right->pressure());
if (m_vf) {
rate1 += m_area * m_vf->eval(t);
}
return rate1;
void WallBase::setArea(double a) {
m_area = a;
m_surf[0].setArea(a);
m_surf[1].setArea(a);
}
doublereal Wall::Q(doublereal t)
Wall::Wall() : WallBase(), m_k(0.0), m_rrth(0.0), m_emiss(0.0), m_vf(0), m_qf(0) {}
double Wall::vdot(double t)
{
double rate = m_k * m_area * (m_left->pressure() - m_right->pressure());
if (m_vf) {
rate += m_area * m_vf->eval(t);
}
return rate;
}
double Wall::Q(double t)
{
double q1 = (m_area * m_rrth) *
(m_left->temperature() - m_right->temperature());
@ -51,10 +55,11 @@ doublereal Wall::Q(doublereal t)
double tr = m_right->temperature();
q1 += m_emiss * m_area * StefanBoltz * (tl*tl*tl*tl - tr*tr*tr*tr);
}
if (m_qf) {
q1 += m_area * m_qf->eval(t);
}
return q1;
}
}

39
src/zeroD/WallFactory.cpp Normal file
View file

@ -0,0 +1,39 @@
//! @file WallFactory.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/zeroD/WallFactory.h"
#include "cantera/zeroD/Wall.h"
using namespace std;
namespace Cantera
{
WallFactory* WallFactory::s_factory = 0;
std::mutex WallFactory::wall_mutex;
WallFactory::WallFactory()
{
reg("Wall", []() { return new Wall(); });
// only used by clib
reg_type("Wall", WallType);
}
WallBase* WallFactory::newWall(const std::string& wallType)
{
return create(wallType);
}
WallBase* WallFactory::newWall(int ir)
{
try {
return create(m_types.at(ir));
} catch (out_of_range&) {
throw CanteraError("WallFactory::newWall",
"unknown wall type!");
}
}
}

View file

@ -0,0 +1,59 @@
//! @file flowControllers.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/zeroD/flowControllers.h"
#include "cantera/zeroD/ReactorBase.h"
#include "cantera/numerics/Func1.h"
namespace Cantera
{
MassFlowController::MassFlowController() : FlowDevice() {
m_type = MFC_Type;
}
void MassFlowController::updateMassFlowRate(double time)
{
if (m_func) {
m_mdot = m_func->eval(time);
}
m_mdot = std::max(m_mdot, 0.0);
}
PressureController::PressureController() : FlowDevice(), m_master(0) {
m_type = PressureController_Type;
}
void PressureController::updateMassFlowRate(double time)
{
if (!ready()) {
throw CanteraError("PressureController::updateMassFlowRate",
"Device is not ready; some parameters have not been set.");
}
m_mdot = m_master->massFlowRate(time)
+ m_coeffs[0]*(in().pressure() - out().pressure());
m_mdot = std::max(m_mdot, 0.0);
}
Valve::Valve() : FlowDevice() {
m_type = Valve_Type;
}
void Valve::updateMassFlowRate(double time)
{
if (!ready()) {
throw CanteraError("Valve::updateMassFlowRate",
"Device is not ready; some parameters have not been set.");
}
double delta_P = in().pressure() - out().pressure();
if (m_func) {
m_mdot = m_func->eval(delta_P);
} else {
m_mdot = m_coeffs[0]*delta_P;
}
m_mdot = std::max(m_mdot, 0.0);
}
}