cantera/src/thermo/VPSSMgrFactory.cpp

388 lines
14 KiB
C++

/**
* @file VPSSMgrFactory.cpp
* Definitions for factory to build instances of classes that manage the
* calculation of standard state properties for all the species in a phase
* (see \ref spthermo and class
* \link Cantera::VPSSMgrFactory VPSSMgrFactory\endlink);
*/
/*
* Copyright (2005) Sandia Corporation. Under the terms of
* Contract DE-AC04-94AL85000 with Sandia Corporation, the
* U.S. Government retains certain rights in this software.
*/
#include "cantera/thermo/SpeciesThermo.h"
#include "cantera/thermo/VPSSMgr.h"
#include "VPSSMgrFactory.h"
#include "cantera/thermo/VPStandardStateTP.h"
#include "cantera/thermo/VPSSMgr_IdealGas.h"
#include "cantera/thermo/VPSSMgr_ConstVol.h"
#include "cantera/thermo/VPSSMgr_Water_ConstVol.h"
#include "cantera/thermo/VPSSMgr_Water_HKFT.h"
#include "cantera/thermo/VPSSMgr_General.h"
#include "cantera/thermo/VPSSMgr_types.h"
#include "cantera/thermo/SpeciesThermoMgr.h"
#include "cantera/thermo/speciesThermoTypes.h"
#include "cantera/thermo/SpeciesThermo.h"
#include "cantera/thermo/SpeciesThermoFactory.h"
#include "cantera/thermo/GeneralSpeciesThermo.h"
#include "cantera/thermo/mix_defs.h"
#include "cantera/base/xml.h"
#include "cantera/base/ctml.h"
using namespace ctml;
using namespace std;
namespace Cantera
{
VPSSMgrFactory* VPSSMgrFactory::s_factory = 0;
// Defn of the static mutex variable that locks the %VPSSMgr factory singleton
mutex_t VPSSMgrFactory::vpss_species_thermo_mutex;
//! Examine the types of species thermo parameterizations, and return a flag indicating the type of parameterization
//! needed by the species.
/*!
*
* @param spDataNodeList Species Data XML node. This node contains a list
* of species XML nodes underneath it.
* @param has_nasa_idealGas Boolean indicating that one species has a nasa ideal gas standard state
* @param has_nasa_constVol Boolean indicating that one species has a nasa ideal solution standard state
* @param has_shomate_idealGas Boolean indicating that one species has a shomate ideal gas standard state
* @param has_shomate_constVol Boolean indicating that one species has a shomate ideal solution standard state
* @param has_simple_idealGas Boolean indicating that one species has a simple ideal gas standard state
* @param has_simple_constVol Boolean indicating that one species has a simple ideal solution standard state
* @param has_water Boolean indicating that one species has a water standard state
* @param has_tpx Boolean indicating that one species has a tpx standard state
* @param has_hptx Boolean indicating that one species has a htpx standard state
* @param has_other Boolean indicating that one species has different standard state than the ones listed above
*
* @todo Make sure that spDadta_node is species Data XML node by checking
* its name is speciesData
*/
static void getVPSSMgrTypes(std::vector<XML_Node*> & spDataNodeList,
int& has_nasa_idealGas,
int& has_nasa_constVol,
int& has_shomate_idealGas,
int& has_shomate_constVol,
int& has_simple_idealGas,
int& has_simple_constVol,
int& has_water,
int& has_tpx,
int& has_hptx,
int& has_other)
{
XML_Node* ss_ptr = 0;
string ssModel = "idealGas";
size_t ns = spDataNodeList.size();
for (size_t n = 0; n < ns; n++) {
bool ifound = false;
XML_Node* spNode = spDataNodeList[n];
if (spNode->hasChild("standardState")) {
const XML_Node& ssN = spNode->child("standardState");
string mm = ssN["model"];
if (mm == "waterIAPWS" || mm == "waterPDSS") {
has_water++;
ifound = true;
}
if (mm == "HKFT") {
has_hptx++;
ifound = true;
}
}
if (!ifound) {
if (spNode->hasChild("thermo")) {
const XML_Node& th = spNode->child("thermo");
if (spNode->hasChild("standardState")) {
ss_ptr = &(spNode->child("standardState"));
ssModel = ss_ptr->attrib("model");
}
if (th.hasChild("NASA")) {
if (ssModel == "idealGas") {
has_nasa_idealGas++;
} else if (ssModel == "constant_incompressible" ||
ssModel == "constantVolume") {
has_nasa_constVol++;
} else if (ssModel == "temperature_polynomial" ||
ssModel == "density_temperature_polynomial" ||
ssModel == "constant") {
has_other++;
} else {
throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
spNode->attrib("name"));
}
ifound = true;
}
if (th.hasChild("Shomate")) {
if (ssModel == "idealGas") {
has_shomate_idealGas++;
} else if (ssModel == "constant_incompressible" ||
ssModel == "constantVolume") {
has_shomate_constVol++;
} else if (ssModel == "temperature_polynomial" ||
ssModel == "density_temperature_polynomial" ||
ssModel == "constant") {
has_other++;
} else {
throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
spNode->attrib("name"));
}
ifound = true;
}
if (th.hasChild("const_cp")) {
if (ssModel == "idealGas") {
has_simple_idealGas++;
} else if (ssModel == "constant_incompressible" ||
ssModel == "constantVolume") {
has_simple_constVol++;
} else if (ssModel == "temperature_polynomial" ||
ssModel == "density_temperature_polynomial" ||
ssModel == "constant") {
has_other++;
} else {
throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
spNode->attrib("name"));
}
ifound = true;
}
if (th.hasChild("poly")) {
if (th.child("poly")["order"] == "1") {
has_simple_constVol = 1;
ifound = true;
} else throw CanteraError("newSpeciesThermo",
"poly with order > 1 not yet supported");
}
if (th.hasChild("Mu0")) {
has_other++;
ifound = true;
}
if (th.hasChild("NASA9")) {
has_other++;
ifound = true;
}
if (th.hasChild("NASA9MULTITEMP")) {
has_other++;
ifound = true;
}
if (th.hasChild("adsorbate")) {
has_other++;
ifound = true;
}
if (th.hasChild("HKFT")) {
has_hptx++;
ifound = true;
}
} else {
throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
spNode->attrib("name"));
}
}
}
}
// Delete static instance of this class
/*
* If it is necessary to explicitly delete the factory before
* the process terminates (for example, when checking for
* memory leaks) then this method can be called to delete it.
*/
void VPSSMgrFactory::deleteFactory()
{
ScopedLock lock(vpss_species_thermo_mutex);
if (s_factory) {
delete s_factory;
s_factory = 0;
}
}
VPSSMgrFactory::~VPSSMgrFactory()
{
}
VPSSMgr_enumType
VPSSMgrFactory::VPSSMgr_StringConversion(std::string ssModel) const
{
std::string lssModel = lowercase(ssModel);
VPSSMgr_enumType type;
if (lssModel == "idealgas") {
type = cVPSSMGR_IDEALGAS;
} else if (lssModel == "constvol") {
type = cVPSSMGR_CONSTVOL;
} else if (lssModel == "purefuild") {
type = cVPSSMGR_PUREFLUID;
} else if (lssModel == "water_constvol") {
type = cVPSSMGR_WATER_CONSTVOL;
} else if (lssModel == "water_hkft") {
type = cVPSSMGR_WATER_HKFT;
} else if (lssModel == "general") {
type = cVPSSMGR_GENERAL;
} else {
type = cVPSSMGR_UNDEF;
}
return type;
}
// Chose the variable pressure standard state manager
// and the reference standard state manager
VPSSMgr*
VPSSMgrFactory::newVPSSMgr(VPStandardStateTP* vp_ptr,
XML_Node* phaseNode_ptr,
std::vector<XML_Node*> & spDataNodeList)
{
std::string ssManager="";
std::string vpssManager="";
VPSSMgr* vpss = 0;
// First look for any explicit instructions within the XML Database
// for the standard state manager and the variable pressure
// standard state manager
if (phaseNode_ptr) {
if (phaseNode_ptr->hasChild("thermo")) {
const XML_Node& thermoNode = phaseNode_ptr->child("thermo");
if (thermoNode.hasChild("standardStateManager")) {
const XML_Node& ssNode = thermoNode.child("standardStateManager");
ssManager = ssNode["model"];
}
if (thermoNode.hasChild("variablePressureStandardStateManager")) {
const XML_Node& vpssNode = thermoNode.child("variablePressureStandardStateManager");
vpssManager = vpssNode["model"];
}
}
}
// first get the reference state handler. If we have explicit instructions,
// use them to spawn the object.
SpeciesThermo* spth = 0;
if (ssManager != "") {
spth = newSpeciesThermoMgr(ssManager);
} else {
spth = newSpeciesThermoMgr(spDataNodeList);
}
vp_ptr->setSpeciesThermo(spth);
// Next, if we have specific directions, use them to get the VPSSSMgr object
// and return immediately
if (vpssManager != "") {
VPSSMgr_enumType type = VPSSMgr_StringConversion(vpssManager);
vpss = newVPSSMgr(type, vp_ptr);
return vpss;
}
// Handle special cases based on the VPStandardState types
if (vp_ptr->eosType() == cVPSS_IdealGas) {
vpss = new VPSSMgr_IdealGas(vp_ptr, spth);
return vpss;
} else if (vp_ptr->eosType() == cVPSS_ConstVol) {
vpss = new VPSSMgr_ConstVol(vp_ptr, spth);
return vpss;
}
int inasaIG = 0, inasaCV = 0, ishomateIG = 0, ishomateCV = 0,
isimpleIG = 0, isimpleCV = 0,
iwater = 0, itpx = 0, iother = 0;
int ihptx = 0;
try {
getVPSSMgrTypes(spDataNodeList, inasaIG, inasaCV, ishomateIG, ishomateCV,
isimpleIG, isimpleCV, iwater, itpx, ihptx, iother);
} catch (UnknownSpeciesThermoModel) {
iother = 1;
popError();
}
if (iwater == 1) {
if (ihptx == 0) {
if (inasaIG || ishomateIG || isimpleIG) {
throw CanteraError("newVPSSMgr", "Ideal gas with liquid water");
} else {
vpss = new VPSSMgr_Water_ConstVol(vp_ptr, spth);
}
} else {
if (inasaIG || ishomateIG || isimpleIG) {
throw CanteraError("newVPSSMgr", "Ideal gas with liquid water");
} else if (inasaCV || ishomateCV || isimpleCV) {
vpss = new VPSSMgr_General(vp_ptr, spth);
} else {
vpss = new VPSSMgr_Water_HKFT(vp_ptr, spth);
}
}
}
if (vpss == 0) {
if (inasaCV || ishomateCV || isimpleCV) {
if (!inasaIG && !ishomateIG && !isimpleIG && !itpx && !ihptx && !iother) {
vpss = new VPSSMgr_ConstVol(vp_ptr, spth);
}
}
}
if (vpss == 0) {
vpss = new VPSSMgr_General(vp_ptr, spth);
}
return vpss;
}
// I don't think this is currently used. However, this is a virtual
// function where additional capabilities may be added.
VPSSMgr*
VPSSMgrFactory::newVPSSMgr(VPSSMgr_enumType type, VPStandardStateTP* vp_ptr)
{
SpeciesThermo& 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 UnknownVPSSMgrModel("VPSSMgrFactory::newVPSSMgr", int2str(type));
return 0;
}
}
// I don't think this is currently used
VPSSMgr* newVPSSMgr(VPSSMgr_enumType type, VPStandardStateTP* vp_ptr,
Cantera::VPSSMgrFactory* f)
{
if (f == 0) {
f = VPSSMgrFactory::factory();
}
VPSSMgr* vpsssptherm = f->newVPSSMgr(type, vp_ptr);
return vpsssptherm;
}
VPSSMgr* newVPSSMgr(VPStandardStateTP* tp_ptr,
XML_Node* phaseNode_ptr,
std::vector<XML_Node*> & spDataNodeList,
VPSSMgrFactory* f)
{
if (f == 0) {
f = VPSSMgrFactory::factory();
}
VPSSMgr* vpsssptherm = f->newVPSSMgr(tp_ptr, phaseNode_ptr, spDataNodeList);
return vpsssptherm;
}
}