cantera/Cantera/src/thermo/VPSSMgrFactory.cpp
Harry Moffat c884917c95 Bug fixes for liquid electrolyte thermo capability.
thermo XML node now takes a couple of extra XML nodes that can specify
explicitly which standardStateManager and which variblePressureStandardState
manager to use.

These are :
  <standardStateManager model="provide_specific_model_here">


and
  <variablePressureStandardStateManager model="provide_specific_model_here">

Previously, these were being determined implicitly by querying the
input deck. However, it seems a no brainer to put the capability for
putting explicit instructions in.
2008-09-23 15:57:52 +00:00

341 lines
9.3 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);
*/
/*
* $Id$
*/
/*
* Copywrite (2005) Sandia Corporation. Under the terms of
* Contract DE-AC04-94AL85000 with Sandia Corporation, the
* U.S. Government retains certain rights in this software.
*/
#ifdef WIN32
#pragma warning(disable:4786)
#endif
#include "SpeciesThermo.h"
#include "VPSSMgr.h"
#include "VPSSMgrFactory.h"
#include "VPStandardStateTP.h"
#include "VPSSMgr_IdealGas.h"
#include "VPSSMgr_ConstVol.h"
#include "VPSSMgr_Water_ConstVol.h"
#include "VPSSMgr_Water_HKFT.h"
#include "VPSSMgr_General.h"
#include "VPSSMgr_types.h"
#include "SpeciesThermoMgr.h"
#include "speciesThermoTypes.h"
#include "SpeciesThermo.h"
#include "SpeciesThermoFactory.h"
#include "GeneralSpeciesThermo.h"
#include "mix_defs.h"
#include "xml.h"
#include "ctml.h"
using namespace ctml;
using namespace std;
namespace Cantera {
VPSSMgrFactory* VPSSMgrFactory::s_factory = 0;
#if defined(THREAD_SAFE_CANTERA)
// Defn of the static mutex variable that locks the
// %VPSSMgr factory singelton
boost::mutex VPSSMgrFactory::vpss_species_thermo_mutex;
#endif
/*
* Examine the types of species thermo parameterizations,
* and return a flag indicating the type of parameterization
* needed by the species.
*
* @param spData_node Species Data XML node. This node contains a list
* of species XML nodes underneath it.
*
* @todo Make sure that spDadta_node is species Data XML node by checking its name is speciesData
*/
static void getVPSSMgrTypes(XML_Node* spData_node,
int& has_nasa, int& has_shomate, int& has_simple,
int &has_water,
int &has_tpx,
int &has_hptx,
int &has_other) {
const XML_Node& sparray = *spData_node;
std::vector<XML_Node*> sp;
// get all of the species nodes
sparray.getChildren("species",sp);
size_t n, ns = sp.size();
for (n = 0; n < ns; n++) {
bool ifound = false;
XML_Node* spNode = sp[n];
if (spNode->hasChild("standardState")) {
const XML_Node& ssN = sp[n]->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 = sp[n]->child("thermo");
if (th.hasChild("NASA")) {
has_nasa++;
ifound = true;
}
if (th.hasChild("Shomate")) {
has_shomate++;
ifound = true;
}
if (th.hasChild("const_cp")){
has_simple = 1;
ifound = true;
}
if (th.hasChild("poly")) {
if (th.child("poly")["order"] == "1") {
has_simple = 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"));
}
}
}
}
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,
XML_Node* spData_node) {
std::vector<XML_Node*> spData_nodes;
spData_nodes.push_back(spData_node);
VPSSMgr *vv = newVPSSMgr(vp_ptr, phaseNode_ptr, spData_nodes);
return vv;
}
// 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*> spData_nodes) {
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(spData_nodes);
}
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;
}
// If it comes back as general, then there may be some unknown
// parameterizations to the SpeciesThermo factory routine.
bool haveSomeUnknowns = true;
GeneralSpeciesThermo *ttmp = dynamic_cast<GeneralSpeciesThermo *>(spth);
if (ttmp == 0) {
haveSomeUnknowns = false;
}
// 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 n = static_cast<int>(spData_nodes.size());
int inasa = 0, ishomate = 0, isimple = 0, iwater = 0, itpx = 0, iother = 0;
int ihptx = 0;
for (int j = 0; j < n; j++) {
try {
getVPSSMgrTypes(spData_nodes[j], inasa, ishomate, isimple, iwater,
itpx, ihptx, iother);
} catch (UnknownSpeciesThermoModel) {
iother = 1;
popError();
}
}
if (iwater == 1) {
if (ihptx == 0) {
vpss = new VPSSMgr_Water_ConstVol(vp_ptr, spth);
} else {
vpss = new VPSSMgr_Water_HKFT(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);
break;
case cVPSSMGR_CONSTVOL:
return new VPSSMgr_ConstVol(vp_ptr, &spthermoRef);
break;
case cVPSSMGR_PUREFLUID:
throw CanteraError("VPSSMgrFactory::newVPSSMgr",
"unimplemented");
case cVPSSMGR_WATER_CONSTVOL:
return new VPSSMgr_Water_ConstVol(vp_ptr, &spthermoRef);
break;
case cVPSSMGR_WATER_HKFT:
return new VPSSMgr_Water_HKFT(vp_ptr, &spthermoRef);
break;
case cVPSSMGR_GENERAL:
return new VPSSMgr_General(vp_ptr, &spthermoRef);
break;
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,
XML_Node* spData_node,
VPSSMgrFactory* f) {
if (f == 0) {
f = VPSSMgrFactory::factory();
}
VPSSMgr* vpsssptherm = f->newVPSSMgr(tp_ptr, phaseNode_ptr, spData_node);
return vpsssptherm;
}
VPSSMgr* newVPSSMgr(VPStandardStateTP *tp_ptr,
XML_Node* phaseNode_ptr,
std::vector<XML_Node*> spData_nodes,
VPSSMgrFactory* f) {
if (f == 0) {
f = VPSSMgrFactory::factory();
}
VPSSMgr* vpsssptherm = f->newVPSSMgr(tp_ptr, phaseNode_ptr, spData_nodes);
return vpsssptherm;
}
}