cantera/Cantera/src/Constituents.cpp
2005-06-18 16:58:39 +00:00

524 lines
15 KiB
C++
Executable file

/**
* @file Constituents.cpp
* Implementation file for class Constituents
*/
/* $Author$
* $Date$
* $Revision$
*
*/
// Copyright 2001 California Institute of Technology
#ifdef WIN32
#pragma warning(disable:4786)
#endif
#include "Constituents.h"
#include "Elements.h"
using namespace std;
namespace Cantera {
//class ElementsFrozen : public CanteraError {
//public:
// ElementsFrozen(string func)
// : CanteraError(func,
// "elements cannot be added after species.") {}
//};
/********************************************************************
*
* Constituents():
*
* Constructor sets all base variable types to zero. Also, it
* sets the pointer to the Elements object for this object to the
* default value of BaseElements. If the BaseElements Elements
* object doesn't exist, it creates it.
*
* Input
* --------
* ptr_Elements: If the Constituents object requires a different
* Elements object than the default one, input
* address here. This argument defaults to null,
* in which case the default Elements Object is
* chosen.
*/
/*
* DGG: I have reversed the role of ptr_Elements. In this version,
* the default is that a new Elements object is created, so this
* Constituents object is independent of any other object. But if
* ptr_Elements is supplied, it will be used. This way, a class
* implementing a multi-phase mixture is responsible for
* maintaining the global elements list for the mixture, and no
* static global element list is required.
*/
Constituents::Constituents(Elements* ptr_Elements) :
m_kk(0),
m_speciesFrozen(false) ,
m_Elements(ptr_Elements)
{
/*
* Check to see that m_Elements is non-null.
*/
if (!m_Elements) {
m_Elements = new Elements();
}
// /*
// * Check to see if the default Elements Object has been
// * created. If it hasn't, create it.
// */
// if (Elements::Global_Elements_List.size() == 0) {
// Elements::Global_Elements_List.push_back(new Elements());
// }
// /*
// * Assign the default Elements object as the
// * Constituents's Elements object
// */
// m_Elements = Elements::Global_Elements_List[0];
// }
/*
* Register subscription to Elements object whether or not we
* created it here.
*/
m_Elements->subscribe();
}
/********************************************************************
*
* ~Constituents():
*
* Destructor For Constituents class.
*
* When the Elements subscription list hits zero, we delete the
* Elements object from here.
*/
Constituents::~Constituents()
{
int ileft = m_Elements->unsubscribe();
/*
* Here we may delete Elements Objects or not. Right now, we
* will delete them. We also delete the global pointer entry
* to keep everything consistent.
*/
if (ileft <= 0) {
vector<Elements *>::iterator it;
for (it = Elements::Global_Elements_List.begin();
it != Elements::Global_Elements_List.end(); ++it) {
if (*it == m_Elements) {
Elements::Global_Elements_List.erase(it);
break;
}
}
delete m_Elements;
}
}
int Constituents::nElements() const { return m_Elements->nElements(); }
/********************************************************************
*
* atomicWeight
*
* Return the Atomic weight of element m.
* units = Kg / Kmol
*/
doublereal Constituents::atomicWeight(int m) const {
return m_Elements->atomicWeight(m);
}
/*******************************************************************
*
* atomicWeights()
*
* returns a reference to the vector of atomic weights pertinent
* to this constituents object
* units = kg / Kmol
*/
const vector_fp& Constituents::atomicWeights() const {
return m_Elements->atomicWeights();
}
/********************************************************************
*
* atomicNumber
*
* Return the atomic number of element m.
*/
int Constituents::atomicNumber(int m) const {
return m_Elements->atomicNumber(m);
}
#ifdef INCL_DEPRECATED_METHODS
/********************************************************************
* element():
*
* Returns an ElementData struct that contains the parameters for
* element m.
*
* -> Passthrough to the Element lvl.
*/
ElementData Constituents::element(int m) const {
return (m_Elements->element(m));
}
#endif
/*******************************************************************
*
* addElement():
*
* Add an element to the set.
* @param symbol symbol string
* Optional:
* @param weight atomic weight in kg/mol.
*
*
* If weight is not given, then a lookup is performed in the
* element object
*
* -> Passthrough to the Element lvl.
*/
void Constituents::
addElement(const string& symbol, doublereal weight)
{
m_Elements->addElement(symbol, weight);
}
void Constituents::
addElement(const XML_Node& e)
{
m_Elements->addElement(e);
}
/*******************************************************************
*
* addUniqueElement():
*
* Add a unique element to the set. A check on the symbol is made
* If the symbol is already an element, then a new element is
* not created.
*
* @param symbol symbol string
* Optional:
* @param weight atomic weight in kg/mol.
*
* If weight is not given, then a lookup is performed in the
* element object
*
* -> Passthrough to the Element lvl.
*/
void Constituents::
addUniqueElement(const string& symbol, doublereal weight)
{
m_Elements->addUniqueElement(symbol, weight);
}
void Constituents::
addUniqueElement(const XML_Node& e)
{
m_Elements->addUniqueElement(e);
}
void Constituents::addElementsFromXML(const XML_Node& phase) {
m_Elements->addElementsFromXML(phase);
}
/*******************************************************************
*
* freezeElements()
*
* -> Passthrough to the Element lvl.
*/
void Constituents::freezeElements() {
m_Elements->freezeElements();
}
/*******************************************************************
*
* elementsFrozen()
*
* -> Passthrough to the Element lvl.
*/
bool Constituents::elementsFrozen() {
return m_Elements->elementsFrozen();
}
/*******************************************************************
*
* elementIndex():
*
* Index of element named \c name. The index is an integer
* assigned to each element in the order it was added,
* beginning with 0 for the first element. If \c name is not
* the name of an element in the set, then the value -1 is
* returned.
*
*
* -> Passthrough to the Element class.
*/
int Constituents::elementIndex(string name) const {
return (m_Elements->elementIndex(name));
}
/*******************************************************************
*
* elementName():
*
* Name of the element with index \c m. @param m Element
* index. If m < 0 or m >= nElements() an exception is thrown.
*
*
* -> Passthrough to the Element lvl.
*/
string Constituents::elementName(int m) const {
return (m_Elements->elementName(m));
}
/*******************************************************************
*
* elementNames():
*
* Returns a read-only reference to the vector of element names.
* @code
* Constituents c;
* ...
* const vector<string>& enames = c.elementNames();
* int n = enames.size();
* for (int i = 0; i < n; i++) cout << enames[i] << endl;
* @endcode
*
*
* -> Passthrough to the Element lvl.
*/
const vector<string>& Constituents::elementNames() const {
return m_Elements->elementNames();
}
/**********************************************************************
*
* molecularWeight()
*
* Returns the molecular weight of a species given the species index
*
* units = kg / kmol.
*/
doublereal Constituents::molecularWeight(int k) const {
if (k < 0 || k >= nSpecies()) {
throw SpeciesRangeError("Constituents::molecularWeight",
k, nSpecies());
}
return m_weight[k];
}
/**********************************************************************
*
* molecularWeights()
*
* Returns a const reference to the vector of molecular weights
* for all of the species defined in the object.
*
* units = kg / kmol.
*/
const array_fp& Constituents::molecularWeights() const {
return m_weight;
}
/**********************************************************************
*
* charge():
*
* Electrical charge of one species k molecule, divided by
* \f$ e = 1.602 \times 10^{-19}\f$ Coulombs.
*/
doublereal Constituents::charge(int k) const {
return m_speciesCharge[k];
}
/**********************************************************************
*
* addSpecies()
*
* Add a species to a Constituents object. Note, no check is made
* as to whether the species has a unique name.
*
* Input
* ---------
* name = string containing the name
* comp[]
* charge =
* weight = weight of the species. Default = 0.0.
* Note, the weight is a bit redundent and potentially
* harmful. If weight is less than or equal to zero,
* the weight is calculated from the element composition
* and it need not be supplied on the command line.
*/
void Constituents::
addSpecies(const string& name, const doublereal* comp,
doublereal charge, doublereal size) {
m_Elements->freezeElements();
m_speciesNames.push_back(name);
m_speciesCharge.push_back(charge);
m_speciesSize.push_back(size);
double wt = 0.0;
int m_mm = m_Elements->nElements();
const vector_fp &aw = m_Elements->atomicWeights();
for (int m = 0; m < m_mm; m++) {
m_speciesComp.push_back(comp[m]);
wt += comp[m] * aw[m];
}
m_weight.push_back(wt);
m_kk++;
}
/**********************************************************************
*
* addUniqueSpecies():
*
* Add a species to a Constituents object. This routine will
* first check to see if the species is already part of the
* phase. It does this via a string comparison with the
* existing species in the phase.
*/
void Constituents::
addUniqueSpecies(const string& name, const doublereal* comp,
doublereal charge, doublereal size) {
vector<string>::const_iterator it = m_speciesNames.begin();
for (int k = 0; k < m_kk; k++) {
if (*it == name) {
/*
* We have found a match. At this point we could do some
* compatibility checks. However, let's just return for the
* moment without specifying any error.
*/
int m_mm = m_Elements->nElements();
for (int i = 0; i < m_mm; i++) {
if (comp[i] != m_speciesComp[m_kk * m_mm + i]) {
throw CanteraError("addUniqueSpecies",
"Duplicate species have different "
"compositions: " + *it);
}
}
if (charge != m_speciesCharge[m_kk]) {
throw CanteraError("addUniqueSpecies",
"Duplicate species have different "
"charges: " + *it);
}
if (size != m_speciesSize[m_kk]) {
throw CanteraError("addUniqueSpecies",
"Duplicate species have different "
"sizes: " + *it);
}
return;
}
++it;
}
addSpecies(name, comp, charge, size);
}
/*******************************************************************
*
* freezeSpecies()
* Set the boolean indicating that we are no longer allowing
* species to be added to the Constituents class object.
*/
void Constituents::freezeSpecies() {
m_speciesFrozen = true;
}
/**********************************************************************
*
* speciesIndex()
*
* Index of species named \c name. The first species added
* will have index 0, and the last one index nSpecies() - 1.
*
* Note, the [] operator shouldn't be used for map's because it
* creates new entries. Here, we use find() to look up entries.
*
* If name isn't in the list, then a -1 is returned.
*/
int Constituents::speciesIndex(string name) const {
vector<string>::const_iterator it = m_speciesNames.begin();
for (int k = 0; k < m_kk; k++) {
if (*it == name) {
/*
* We have found a match.
*/
return k;
}
++it;
}
return -1;
}
/**********************************************************************
*
* speciesName()
*
* Name of the species with index k
*/
string Constituents::speciesName(int k) const {
if (k < 0 || k >= nSpecies())
throw SpeciesRangeError("Constituents::speciesName",
k, nSpecies());
return m_speciesNames[k];
}
/**********************************************************************
*
* speciesNames()
*
* Return a const reference to the vector of species names
*/
const vector<string>& Constituents::speciesNames() const {
return m_speciesNames;
}
/**********************************************************************
*
* ready():
* True if both elements and species have been frozen
*/
bool Constituents::ready() const {
return (m_Elements->elementsFrozen() && m_speciesFrozen);
}
/**********************************************************************
*
* nAtoms()
*
* Returns the number of atoms of element \c m in species \c k.
*/
doublereal Constituents::nAtoms(int k, int m) const
{
const int m_mm = m_Elements->nElements();
if (m < 0 || m >=m_mm)
throw ElementRangeError("Constituents::nAtoms",m,nElements());
if (k < 0 || k >= nSpecies())
throw SpeciesRangeError("Constituents::nAtoms",k,nSpecies());
return m_speciesComp[m_mm * k + m];
}
/*********************************************************************
*
* getAtoms()
*
* Get a vector containing the atomic composition
* of species k
*/
void Constituents::getAtoms(int k, double *atomArray) const
{
const int m_mm = m_Elements->nElements();
for (int m = 0; m < m_mm; m++) {
atomArray[m] = (double) m_speciesComp[m_mm * k + m];
}
}
}