Introduce basic registration capabilities for factories

This commit is contained in:
Ray Speth 2016-07-04 15:59:29 -04:00
parent 64bb049647
commit f985169e93
14 changed files with 166 additions and 192 deletions

View file

@ -7,6 +7,8 @@
#include <vector>
#include <mutex>
#include <unordered_map>
#include "cantera/base/ctexceptions.h"
namespace Cantera
{
@ -53,6 +55,36 @@ private:
//! statically held list of Factories.
static std::vector<FactoryBase*> s_vFactoryRegistry;
};
//! Factory class that supports registering functions to create objects
//!
//! Template arguments for the class are the base type created by the factory,
//! followed by the types of any arguments which need to be passed to the
//! functions used to create objects, e.g. arguments to the constructor.
template <class T, typename ... Args>
class Factory : public FactoryBase {
public:
virtual ~Factory() {}
//! Create an object using the object construction function corresponding to
//! "name" and the provided constructor arguments
T* create(const std::string& name, Args... args) {
try {
return m_creators.at(name)(args...);
} catch (std::out_of_range&) {
throw CanteraError("Factory::create", "No such type: '{}'", name);
}
}
//! Register a new object construction function
void reg(const std::string& name, std::function<T*(Args...)> f) {
m_creators[name] = f;
}
protected:
std::unordered_map<std::string, std::function<T*(Args...)>> m_creators;
};
}
#endif

View file

@ -25,7 +25,7 @@ namespace Cantera
*
* @ingroup falloffGroup
*/
class FalloffFactory : public FactoryBase
class FalloffFactory : public Factory<Falloff>
{
public:
/**
@ -64,7 +64,7 @@ private:
static FalloffFactory* s_factory;
//! default constructor, which is defined as private
FalloffFactory() {}
FalloffFactory();
//! Mutex for use when calling the factory
static std::mutex falloff_mutex;

View file

@ -25,7 +25,7 @@ public:
/**
* Factory for kinetics managers.
*/
class KineticsFactory : public FactoryBase
class KineticsFactory : public Factory<Kinetics>
{
public:
static KineticsFactory* factory() {
@ -70,7 +70,7 @@ public:
private:
static KineticsFactory* s_factory;
KineticsFactory() {}
KineticsFactory();
static std::mutex kinetics_mutex;
};

View file

@ -49,7 +49,7 @@ public:
* This class keeps a list of the known ThermoPhase classes, and is
* used to create new instances of these classes.
*/
class ThermoFactory : public FactoryBase
class ThermoFactory : public Factory<ThermoPhase>
{
public:
//! Static function that creates a static instance of the factory.
@ -82,7 +82,7 @@ private:
static ThermoFactory* s_factory;
//! Private constructors prevents usage
ThermoFactory() {};
ThermoFactory();
//! Decl for locking mutex for thermo factory singleton
static std::mutex thermo_mutex;
@ -102,7 +102,7 @@ inline ThermoPhase* newThermoPhase(const std::string& model,
if (f == 0) {
f = ThermoFactory::factory();
}
return f->newThermoPhase(model);
return f->create(model);
}
//! Translate the eosType id into a string

View file

@ -709,9 +709,7 @@ public:
* specification of the collision integrals. defaults to no.
* @param log_level Defaults to zero, no logging
*/
virtual void init(thermo_t* thermo, int mode=0, int log_level=0) {
throw NotImplementedError("Transport::init");
}
virtual void init(thermo_t* thermo, int mode=0, int log_level=0) {}
//! Called by TransportFactory to set parameters.
/*!

View file

@ -26,7 +26,7 @@ namespace Cantera
*
* @ingroup tranprops
*/
class TransportFactory : public FactoryBase
class TransportFactory : public Factory<Transport>
{
public:
//! Return a pointer to a TransportFactory instance.
@ -104,8 +104,7 @@ public:
* @param thermo ThermoPhase object
* @param log_level log level
*/
virtual Transport*
newTransport(thermo_t* thermo, int log_level=0);
virtual Transport* newTransport(thermo_t* thermo, int log_level=0);
//! Initialize an existing transport manager for liquid phase
/*!
@ -242,6 +241,9 @@ private:
//! Mapping between between the string name for a
//! liquid mixture transport property model and the integer name.
std::map<std::string, LiquidTranMixingModel> m_LTImodelMap;
//! Models included in this map are initialized in CK compatibility mode
std::map<std::string, bool> m_CK_mode;
};
//! Create a new transport manager instance.

View file

@ -11,7 +11,7 @@
namespace Cantera
{
class ReactorFactory : FactoryBase
class ReactorFactory : public Factory<ReactorBase>
{
public:
static ReactorFactory* factory() {
@ -38,7 +38,7 @@ public:
private:
static ReactorFactory* s_factory;
static std::mutex reactor_mutex;
ReactorFactory() {}
ReactorFactory();
};
inline ReactorBase* newReactor(const std::string& model,

View file

@ -12,22 +12,22 @@ namespace Cantera
FalloffFactory* FalloffFactory::s_factory = 0;
std::mutex FalloffFactory::falloff_mutex;
FalloffFactory::FalloffFactory()
{
reg("Simple", []() { return new Falloff(); });
reg("Troe", []() { return new Troe(); });
reg("SRI", []() { return new SRI(); });
}
Falloff* FalloffFactory::newFalloff(int type, const vector_fp& c)
{
Falloff* f;
switch (type) {
case SIMPLE_FALLOFF:
f = new Falloff();
break;
case TROE_FALLOFF:
f = new Troe();
break;
case SRI_FALLOFF:
f = new SRI();
break;
default:
return 0;
}
static const std::unordered_map<int, std::string> types {
{SIMPLE_FALLOFF, "Simple"},
{TROE_FALLOFF, "Troe"},
{SRI_FALLOFF, "SRI"}
};
Falloff* f = create(types.at(type));
f->init(c);
return f;
}

View file

@ -37,22 +37,17 @@ Kinetics* KineticsFactory::newKinetics(XML_Node& phaseData,
return k;
}
KineticsFactory::KineticsFactory() {
reg("none", []() { return new Kinetics(); });
reg("gaskinetics", []() { return new GasKinetics(); });
reg("interface", []() { return new InterfaceKinetics(); });
reg("edge", []() { return new EdgeKinetics(); });
reg("aqueouskinetics", []() { return new AqueousKinetics(); });
}
Kinetics* KineticsFactory::newKinetics(const string& model)
{
string lcmodel = lowercase(model);
if (lcmodel == "none") {
return new Kinetics();
} else if (lcmodel == "gaskinetics") {
return new GasKinetics();
} else if (lcmodel == "interface") {
return new InterfaceKinetics();
} else if (lcmodel == "edge") {
return new EdgeKinetics();
} else if (lcmodel == "aqueouskinetics") {
return new AqueousKinetics();
} else {
throw UnknownKineticsModel("KineticsFactory::newKinetics", model);
}
return create(lowercase(model));
}
}

View file

@ -77,71 +77,39 @@ static int _itypes[] = {cIdealGas, cIncompressible,
cRedlichKwongMFTP, cRedlichKwongMFTP, cMaskellSolidSolnPhase
};
ThermoFactory::ThermoFactory()
{
reg("IdealGas", []() { return new IdealGasPhase(); });
reg("Incompressible", []() { return new ConstDensityThermo(); });
reg("Surface", []() { return new SurfPhase(); });
reg("Edge", []() { return new EdgePhase(); });
reg("Metal", []() { return new MetalPhase(); });
reg("StoichSubstance", []() { return new StoichSubstance(); });
reg("PureFluid", []() { return new PureFluidPhase(); });
reg("LatticeSolid", []() { return new LatticeSolidPhase(); });
reg("Lattice", []() { return new LatticePhase(); });
reg("HMW", []() { return new HMWSoln(); });
reg("IdealSolidSolution", []() { return new IdealSolidSolnPhase(); });
reg("DebyeHuckel", []() { return new DebyeHuckel(); });
reg("IdealMolalSolution", []() { return new IdealMolalSoln(); });
reg("IdealGasVPSS", []() { return new IdealSolnGasVPSS(); });
reg("IdealSolnVPSS", []() { return new IdealSolnGasVPSS(); });
reg("MineralEQ3", []() { return new MineralEQ3(); });
reg("MetalSHEelectrons", []() { return new MetalSHEelectrons(); });
reg("Margules", []() { return new MargulesVPSSTP(); });
reg("PhaseCombo_Interaction", []() { return new PhaseCombo_Interaction(); });
reg("IonsFromNeutralMolecule", []() { return new IonsFromNeutralVPSSTP(); });
reg("FixedChemPot", []() { return new FixedChemPotSSTP(); });
reg("MolarityIonicVPSSTP", []() { return new MolarityIonicVPSSTP(); });
reg("Redlich-Kister", []() { return new RedlichKisterVPSSTP(); });
reg("RedlichKwong", []() { return new RedlichKwongMFTP(); });
reg("RedlichKwongMFTP", []() { return new RedlichKwongMFTP(); });
reg("MaskellSolidSolnPhase", []() { return new MaskellSolidSolnPhase(); });
}
ThermoPhase* ThermoFactory::newThermoPhase(const std::string& model)
{
int ieos=-1;
for (int n = 0; n < ntypes; n++) {
if (model == _types[n]) {
ieos = _itypes[n];
break;
}
}
switch (ieos) {
case cIdealGas:
return new IdealGasPhase;
case cIncompressible:
return new ConstDensityThermo;
case cSurf:
return new SurfPhase;
case cEdge:
return new EdgePhase;
case cIdealSolidSolnPhase:
return new IdealSolidSolnPhase();
case cMargulesVPSSTP:
return new MargulesVPSSTP();
case cRedlichKisterVPSSTP:
return new RedlichKisterVPSSTP();
case cMolarityIonicVPSSTP:
return new MolarityIonicVPSSTP();
case cPhaseCombo_Interaction:
return new PhaseCombo_Interaction();
case cIonsFromNeutral:
return new IonsFromNeutralVPSSTP();
case cMetal:
return new MetalPhase;
case cStoichSubstance:
return new StoichSubstance;
case cFixedChemPot:
return new FixedChemPotSSTP;
case cMineralEQ3:
return new MineralEQ3();
case cMetalSHEelectrons:
return new MetalSHEelectrons();
case cLatticeSolid:
return new LatticeSolidPhase;
case cLattice:
return new LatticePhase;
case cPureFluid:
return new PureFluidPhase;
case cRedlichKwongMFTP:
return new RedlichKwongMFTP;
case cHMW:
return new HMWSoln;
case cDebyeHuckel:
return new DebyeHuckel;
case cIdealMolalSoln:
return new IdealMolalSoln;
case cVPSS_IdealGas:
return new IdealSolnGasVPSS;
case cIdealSolnGasVPSS_iscv:
return new IdealSolnGasVPSS;
case cMaskellSolidSolnPhase:
return new MaskellSolidSolnPhase;
default:
throw UnknownThermoPhaseModel("ThermoFactory::newThermoPhase", model);
}
return create(model);
}
std::string eosTypeString(int ieos, int length)

View file

@ -183,6 +183,25 @@ static void getVPSSMgrTypes(std::vector<XML_Node*> & spDataNodeList,
}
}
VPSSMgrFactory::VPSSMgrFactory()
{
reg("idealgas",
[] (VPStandardStateTP* tp, MultiSpeciesThermo* st) {
return new VPSSMgr_IdealGas(tp, st); });
reg("constvol",
[] (VPStandardStateTP* tp, MultiSpeciesThermo* st) {
return new VPSSMgr_ConstVol(tp, st); });
reg("water_constvol",
[] (VPStandardStateTP* tp, MultiSpeciesThermo* st) {
return new VPSSMgr_Water_ConstVol(tp, st); });
reg("water_hkft",
[] (VPStandardStateTP* tp, MultiSpeciesThermo* st) {
return new VPSSMgr_Water_HKFT(tp, st); });
reg("general",
[] (VPStandardStateTP* tp, MultiSpeciesThermo* st) {
return new VPSSMgr_General(tp, st); });
}
void VPSSMgrFactory::deleteFactory()
{
std::unique_lock<std::mutex> lock(vpss_species_thermo_mutex);
@ -230,7 +249,7 @@ VPSSMgr* VPSSMgrFactory::newVPSSMgr(VPStandardStateTP* vp_ptr,
}
if (thermoNode.hasChild("variablePressureStandardStateManager")) {
const XML_Node& vpssNode = thermoNode.child("variablePressureStandardStateManager");
vpssManager = vpssNode["model"];
vpssManager = lowercase(vpssNode["model"]);
}
}
@ -241,8 +260,7 @@ VPSSMgr* VPSSMgrFactory::newVPSSMgr(VPStandardStateTP* vp_ptr,
// Next, if we have specific directions, use them to get the VPSSSMgr object
// and return immediately
if (vpssManager != "") {
VPSSMgr_enumType type = VPSSMgr_StringConversion(vpssManager);
return newVPSSMgr(type, vp_ptr);
return create(vpssManager, vp_ptr, spth);
}
// Handle special cases based on the VPStandardState types
@ -292,27 +310,15 @@ VPSSMgr* VPSSMgrFactory::newVPSSMgr(VPStandardStateTP* vp_ptr,
VPSSMgr* VPSSMgrFactory::newVPSSMgr(VPSSMgr_enumType type,
VPStandardStateTP* vp_ptr)
{
static unordered_map<int, std::string> types {
{cVPSSMGR_IDEALGAS, "idealgas"},
{cVPSSMGR_CONSTVOL, "constvol"},
{cVPSSMGR_WATER_CONSTVOL, "water_constvol"},
{cVPSSMGR_WATER_HKFT, "water_hkft"},
{cVPSSMGR_GENERAL, "general"}
};
MultiSpeciesThermo& spthermoRef = vp_ptr->speciesThermo();
switch (type) {
case cVPSSMGR_IDEALGAS:
return new VPSSMgr_IdealGas(vp_ptr, &spthermoRef);
case cVPSSMGR_CONSTVOL:
return new VPSSMgr_ConstVol(vp_ptr, &spthermoRef);
case cVPSSMGR_PUREFLUID:
throw CanteraError("VPSSMgrFactory::newVPSSMgr",
"unimplemented");
case cVPSSMGR_WATER_CONSTVOL:
return new VPSSMgr_Water_ConstVol(vp_ptr, &spthermoRef);
case cVPSSMGR_WATER_HKFT:
return new VPSSMgr_Water_HKFT(vp_ptr, &spthermoRef);
case cVPSSMGR_GENERAL:
return new VPSSMgr_General(vp_ptr, &spthermoRef);
case cVPSSMGR_UNDEF:
default:
throw CanteraError("VPSSMgrFactory::newVPSSMgr",
"Specified VPSSMgr model {} does not match any known type.", type);
return 0;
}
return create(types.at(type), vp_ptr, &spthermoRef);
}
// I don't think this is currently used

View file

@ -59,7 +59,7 @@ public:
*
* @ingroup mgrpdssthermocalc
*/
class VPSSMgrFactory : public FactoryBase
class VPSSMgrFactory : public Factory<VPSSMgr, VPStandardStateTP*, MultiSpeciesThermo*>
{
public:
//! Static method to return an instance of this class
@ -131,7 +131,7 @@ private:
//! Constructor. This is made private, so that only the static
//! method factory() can instantiate the class.
VPSSMgrFactory() {}
VPSSMgrFactory();
};
////////////////////// Convenience functions ////////////////////

View file

@ -41,6 +41,16 @@ public:
TransportFactory::TransportFactory()
{
reg("", []() { return new Transport(); });
reg("None", []() { return new Transport(); });
reg("Mix", []() { return new MixTransport(); });
reg("Multi", []() { return new MultiTransport(); });
reg("CK_Mix", []() { return new MixTransport(); });
reg("CK_Multi", []() { return new MultiTransport(); });
reg("HighP", []() { return new HighPressureGasTransport(); });
m_CK_mode["CK_Mix"] = true;
m_CK_mode["CK_Multi"] = true;
m_models["Mix"] = cMixtureAveraged;
m_models["Multi"] = cMulticomponent;
m_models["Solid"] = cSolidTransport;
@ -173,39 +183,12 @@ LiquidTranInteraction* TransportFactory::newLTI(const XML_Node& trNode,
Transport* TransportFactory::newTransport(const std::string& transportModel,
thermo_t* phase, int log_level, int ndim)
{
if (transportModel == "") {
return new Transport;
}
vector_fp state;
Transport* tr = 0, *gastr = 0;
DustyGasTransport* dtr = 0;
phase->saveState(state);
switch (m_models[transportModel]) {
case None:
tr = new Transport;
break;
case cMulticomponent:
tr = new MultiTransport;
tr->init(phase, 0, log_level);
break;
case CK_Multicomponent:
tr = new MultiTransport;
tr->init(phase, CK_Mode, log_level);
break;
case cMixtureAveraged:
tr = new MixTransport;
tr->init(phase, 0, log_level);
break;
case CK_MixtureAveraged:
tr = new MixTransport;
tr->init(phase, CK_Mode, log_level);
break;
case cHighP:
tr = new HighPressureGasTransport;
tr->init(phase, 0, log_level);
break;
case cSolidTransport:
tr = new SolidTransport;
initSolidTransport(tr, phase, log_level);
@ -229,7 +212,8 @@ Transport* TransportFactory::newTransport(const std::string& transportModel,
tr->setThermo(*phase);
break;
default:
throw CanteraError("newTransport","unknown transport model: " + transportModel);
tr = create(transportModel);
tr->init(phase, m_CK_mode[transportModel], log_level);
}
phase->restoreState(state);
return tr;

View file

@ -17,50 +17,39 @@ namespace Cantera
ReactorFactory* ReactorFactory::s_factory = 0;
std::mutex ReactorFactory::reactor_mutex;
static int ntypes = 6;
static string _types[] = {"Reservoir", "Reactor", "ConstPressureReactor",
"FlowReactor", "IdealGasReactor",
"IdealGasConstPressureReactor"
};
// these constants are defined in ReactorBase.h
static int _itypes[] = {ReservoirType, ReactorType, ConstPressureReactorType,
FlowReactorType, IdealGasReactorType,
IdealGasConstPressureReactorType
};
ReactorFactory::ReactorFactory()
{
reg("Reservoir", []() { return new Reservoir(); });
reg("Reactor", []() { return new Reactor(); });
reg("ConstPressureReactor", []() { return new ConstPressureReactor(); });
reg("FlowReactor", []() { return new FlowReactor(); });
reg("IdealGasReactor", []() { return new IdealGasReactor(); });
reg("IdealGasConstPressureReactor", []() { return new IdealGasConstPressureReactor(); });
}
ReactorBase* ReactorFactory::newReactor(const std::string& reactorType)
{
int ir=-1;
for (int n = 0; n < ntypes; n++) {
if (reactorType == _types[n]) {
ir = _itypes[n];
}
}
return newReactor(ir);
return create(reactorType);
}
ReactorBase* ReactorFactory::newReactor(int ir)
{
switch (ir) {
case ReservoirType:
return new Reservoir();
case ReactorType:
return new Reactor();
case FlowReactorType:
return new FlowReactor();
case ConstPressureReactorType:
return new ConstPressureReactor();
case IdealGasReactorType:
return new IdealGasReactor();
case IdealGasConstPressureReactorType:
return new IdealGasConstPressureReactor();
default:
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));
} catch (out_of_range&) {
throw CanteraError("ReactorFactory::newReactor",
"unknown reactor type!");
}
return 0;
}
}