Folded class Elements into class Phase
This commit is contained in:
parent
7e39e91b5b
commit
c440373aba
4 changed files with 256 additions and 932 deletions
|
|
@ -1,26 +1,18 @@
|
|||
/**
|
||||
* @file Elements.h
|
||||
* Header file for class, Elements, which contains the elements that
|
||||
* make up species (see \ref phases and \link Cantera::Elements Elements\endlink).
|
||||
*
|
||||
* This file contains the declarations for the elements class.
|
||||
* Contains the LookupWtElements function and the definitions of element
|
||||
* constraint types.
|
||||
*/
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
#ifndef CT_ELEMENTS_H
|
||||
#define CT_ELEMENTS_H
|
||||
|
||||
#undef USE_DGG_CODE
|
||||
|
||||
#include "cantera/base/ct_defs.h"
|
||||
|
||||
|
||||
namespace Cantera
|
||||
{
|
||||
|
||||
class XML_Node;
|
||||
class ElementRangeError;
|
||||
|
||||
/*!
|
||||
* @name Types of Element Constraint Equations
|
||||
*
|
||||
|
|
@ -87,330 +79,21 @@ class ElementRangeError;
|
|||
#define CT_ELEM_TYPE_OTHERCONSTRAINT 6
|
||||
//@}
|
||||
|
||||
|
||||
//! Positive number indicating we don't know the gibbs free energy
|
||||
//! of the element in its most stable state at 298.15 K and 1 bar.
|
||||
//! Number indicating we don't know the entropy of the element in its most
|
||||
//! stable state at 298.15 K and 1 bar.
|
||||
#define ENTROPY298_UNKNOWN -123456789.
|
||||
|
||||
//! Object containing the elements that make up species in a phase.
|
||||
/*!
|
||||
* Class %Elements manages the elements that are part of a
|
||||
* chemistry specification. This class may support calculations
|
||||
* employing Multiple phases. In this case, a single Elements object may
|
||||
* be shared by more than one Constituents class. Reactions between
|
||||
* the phases may then be described using stoichiometry base on the
|
||||
* same Elements class object.
|
||||
*
|
||||
* The member functions return information about the elements described
|
||||
* in a particular instantiation of the class.
|
||||
*
|
||||
* @ingroup phases
|
||||
*/
|
||||
class Elements
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Default constructor for the elements class
|
||||
Elements();
|
||||
|
||||
//! Default destructor for the elements class
|
||||
~Elements();
|
||||
|
||||
|
||||
//! copy constructor
|
||||
/*!
|
||||
* This copy constructor just calls the assignment operator for this
|
||||
* class. It sets the number of subscribers to zer0.
|
||||
*
|
||||
* @param right Reference to the object to be copied.
|
||||
*/
|
||||
Elements(const Elements& right);
|
||||
|
||||
//! Assigntment operator
|
||||
/*!
|
||||
* This is the assignment operator for the Elements class.
|
||||
* Right now we pretty much do a straight uncomplicated
|
||||
* assignment. However, subscribers are not mucked with, as they
|
||||
* have to do with the address of the object to be subscribed to
|
||||
*
|
||||
* @param right Reference to the object to be copied.
|
||||
*/
|
||||
Elements& operator=(const Elements& right);
|
||||
|
||||
|
||||
//! Static function to look up an atomic weight
|
||||
/*!
|
||||
* This static function looks up the argument string in the
|
||||
* database above and returns the associated molecular weight.
|
||||
* The data are from the periodic table.
|
||||
*
|
||||
* Note: The idea behind this function is to provide a unified
|
||||
* source for the element atomic weights. This helps to
|
||||
* ensure that mass is conserved.
|
||||
*
|
||||
* @param ename String, Only the first 3 characters are significant
|
||||
*
|
||||
* @return
|
||||
* Return value contains the atomic weight of the element
|
||||
* If a match for the string is not found, a value of -1.0 is
|
||||
* returned.
|
||||
*
|
||||
* @exception CanteraError
|
||||
* If a match is not found, a CanteraError is thrown as well
|
||||
*/
|
||||
static double LookupWtElements(const std::string& ename);
|
||||
|
||||
/// Atomic weight of element m.
|
||||
/*!
|
||||
* @param m element index
|
||||
*/
|
||||
doublereal atomicWeight(size_t m) const {
|
||||
return m_atomicWeights[m];
|
||||
}
|
||||
|
||||
/// Atomic number of element m.
|
||||
/*!
|
||||
* @param m element index
|
||||
*/
|
||||
int atomicNumber(size_t m) const {
|
||||
return m_atomicNumbers[m];
|
||||
}
|
||||
|
||||
//! Entropy at 298.15 K and 1 bar of stable state
|
||||
//! of the element
|
||||
/*!
|
||||
* units J kmol-1 K-1
|
||||
*
|
||||
* @param m Element index
|
||||
*/
|
||||
doublereal entropyElement298(size_t m) const;
|
||||
|
||||
//! Return the element constraint type
|
||||
/*!
|
||||
* Possible types include:
|
||||
*
|
||||
* CT_ELEM_TYPE_ABSPOS 0
|
||||
* CT_ELEM_TYPE_ELECTRONCHARGE 1
|
||||
* CT_ELEM_TYPE_CHARGENEUTRALITY 2
|
||||
* CT_ELEM_TYPE_LATTICERATIO 3
|
||||
* CT_ELEM_TYPE_KINETICFROZEN 4
|
||||
* CT_ELEM_TYPE_SURFACECONSTRAINT 5
|
||||
* CT_ELEM_TYPE_OTHERCONSTRAINT 6
|
||||
*
|
||||
* The default is CT_ELEM_TYPE_ABSPOS
|
||||
*
|
||||
* @param m Element index
|
||||
*
|
||||
* @return Returns the element type
|
||||
*/
|
||||
int elementType(size_t m) const;
|
||||
|
||||
//! Change the element type of the mth constraint
|
||||
/*!
|
||||
* Reassigns an element type
|
||||
*
|
||||
* @param m Element index
|
||||
* @param elem_type New elem type to be assigned
|
||||
*
|
||||
* @return Returns the old element type
|
||||
*/
|
||||
int changeElementType(int m, int elem_type);
|
||||
|
||||
/// vector of element atomic weights
|
||||
const vector_fp& atomicWeights() const {
|
||||
return m_atomicWeights;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inline function that returns the number of elements in the object.
|
||||
*
|
||||
* @return
|
||||
* \c int: The number of elements in the object.
|
||||
*/
|
||||
size_t nElements() const {
|
||||
return m_mm;
|
||||
}
|
||||
|
||||
//! Function that returns the index of an element.
|
||||
/*!
|
||||
* 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.
|
||||
*
|
||||
* @param name String containing the index.
|
||||
*/
|
||||
size_t elementIndex(std::string name) const;
|
||||
|
||||
//! Name of the element with index \c m.
|
||||
/*!
|
||||
* @param m Element index. If m < 0 or m >= nElements() an exception is thrown.
|
||||
*/
|
||||
std::string elementName(size_t m) const;
|
||||
|
||||
//! Returns a string vector containing the element names
|
||||
/*!
|
||||
* Returns a read-only reference to the vector of element names.
|
||||
* @return <tt> const vector<string>& </tt>: The vector contains
|
||||
* the element names in their indexed order.
|
||||
*/
|
||||
const std::vector<std::string>& elementNames() const {
|
||||
return m_elementNames;
|
||||
}
|
||||
|
||||
//! Add an element to the current set of elements in the current object.
|
||||
/*!
|
||||
* The default weight is a special value, which will cause the
|
||||
* routine to look up the actual weight via a string lookup.
|
||||
*
|
||||
* There are two interfaces to this routine. The XML interface
|
||||
* looks up the required parameters for the regular interface
|
||||
* and then calls the base routine.
|
||||
*
|
||||
* @param symbol string symbol for the element.
|
||||
* @param weight Atomic weight of the element. If no argument
|
||||
* is provided, a lookup is attempted.
|
||||
*/
|
||||
void addElement(const std::string& symbol,
|
||||
doublereal weight = -12345.0);
|
||||
|
||||
//! Add an element to the current set of elements in the current object.
|
||||
/*!
|
||||
* @param e Reference to the XML_Node containing the element information
|
||||
* The node name is the element symbol and the atomWt attribute
|
||||
* is used as the atomic weight.
|
||||
*/
|
||||
void addElement(const XML_Node& e);
|
||||
|
||||
//! Add an element only if the element hasn't been added before.
|
||||
/*!
|
||||
* This is accomplished via a string match on symbol.
|
||||
*
|
||||
* @param symbol string symbol for the element.
|
||||
* @param weight Atomic weight of the element. If no argument
|
||||
* is provided, a lookup is attempted.
|
||||
* @param atomicNumber defaults to 0
|
||||
* @param entropy298 Value of the entropy at 298 and 1 bar of the
|
||||
* element in its most stable form.
|
||||
* The default is to specify an ENTROPY298_UNKNOWN value,
|
||||
* which will cause a throw error if it's ever
|
||||
* needed.
|
||||
* @param elem_type New elem type to be assigned.
|
||||
* The default is a regular element, CT_ELEM_TYPE_ABSPOS
|
||||
*/
|
||||
void addUniqueElement(const std::string& symbol,
|
||||
doublereal weight = -12345.0, int atomicNumber = 0,
|
||||
doublereal entropy298 = ENTROPY298_UNKNOWN, int elem_type = CT_ELEM_TYPE_ABSPOS);
|
||||
|
||||
//! Add an element to the current set of elements in the current object.
|
||||
/*!
|
||||
* @param e Reference to the XML_Node containing the element information
|
||||
* The node name is the element symbol and the atomWt attribute
|
||||
* is used as the atomic weight.
|
||||
*/
|
||||
void addUniqueElement(const XML_Node& e);
|
||||
|
||||
//! Add multiple elements from a XML_Node phase description
|
||||
/*!
|
||||
* @param phase XML_Node reference to a phase
|
||||
*/
|
||||
void addElementsFromXML(const XML_Node& phase);
|
||||
|
||||
//! Prohibit addition of more elements, and prepare to add species.
|
||||
void freezeElements();
|
||||
|
||||
//! True if freezeElements has been called.
|
||||
bool elementsFrozen() const;
|
||||
|
||||
/// Remove all elements
|
||||
void clear();
|
||||
|
||||
/// True if both elements and species have been frozen
|
||||
bool ready() const;
|
||||
|
||||
|
||||
//! subscribe to this object
|
||||
/*!
|
||||
* Increment by one the number of subscriptions to this object.
|
||||
*/
|
||||
void subscribe();
|
||||
|
||||
//! unsubscribe to this object
|
||||
/*!
|
||||
* decrement by one the number of subscriptions to this object.
|
||||
*/
|
||||
int unsubscribe();
|
||||
|
||||
//! report the number of subscriptions
|
||||
int reportSubscriptions() const;
|
||||
|
||||
protected:
|
||||
|
||||
/******************************************************************/
|
||||
/* Description of DATA in the Object */
|
||||
/******************************************************************/
|
||||
|
||||
//! Number of elements.
|
||||
size_t m_mm;
|
||||
|
||||
/* m_elementsFrozen: */
|
||||
/** boolean indicating completion of object
|
||||
*
|
||||
* If this is true, then no elements may be added to the
|
||||
* object.
|
||||
*/
|
||||
bool m_elementsFrozen;
|
||||
|
||||
/**
|
||||
* Vector of element atomic weights:
|
||||
*
|
||||
* units = kg / kmol
|
||||
*/
|
||||
vector_fp m_atomicWeights;
|
||||
|
||||
/**
|
||||
* Vector of element atomic numbers:
|
||||
*
|
||||
*/
|
||||
vector_int m_atomicNumbers;
|
||||
|
||||
/** Vector of strings containing the names of the elements
|
||||
*
|
||||
* Note, a string search is the primary way to identify elements.
|
||||
*/
|
||||
std::vector<std::string> m_elementNames;
|
||||
|
||||
//! Entropy at 298.15 K and 1 bar of stable state
|
||||
/*!
|
||||
* units J kmol-1
|
||||
*/
|
||||
vector_fp m_entropy298;
|
||||
|
||||
//! Vector of element types
|
||||
vector_int m_elem_type;
|
||||
|
||||
/**
|
||||
* Number of Constituents Objects that use this object
|
||||
*
|
||||
* Number of Constituents Objects that require this Elements object
|
||||
* to complete its definition.
|
||||
* The destructor checks to see that this is equal to zero.
|
||||
* when the element object is released.
|
||||
*/
|
||||
int numSubscribers;
|
||||
|
||||
/********* GLOBAL STATIC SECTION *************/
|
||||
|
||||
public:
|
||||
/** Vector of pointers to Elements Objects
|
||||
*
|
||||
*/
|
||||
static std::vector<Elements*> Global_Elements_List;
|
||||
|
||||
friend class Phase;
|
||||
};
|
||||
//! Function to look up an atomic weight
|
||||
//! This function looks up the argument string in the database above and
|
||||
//! returns the associated molecular weight.
|
||||
//! The data are from the periodic table.
|
||||
//!
|
||||
//! Note: The idea behind this function is to provide a unified source for the
|
||||
//! element atomic weights. This helps to ensure that mass is conserved.
|
||||
//! @param ename String, Only the first 3 characters are significant
|
||||
//! @return The atomic weight of the element
|
||||
//! @exception CanteraError If a match is not found, throws a CanteraError
|
||||
double LookupWtElements(const std::string& ename);
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,20 @@ namespace Cantera
|
|||
{
|
||||
class SpeciesThermo;
|
||||
|
||||
//! Exception class to indicate a fixed set of elements.
|
||||
/*!
|
||||
* This class is used to warn the user when the number of elements
|
||||
* are changed after at least one species is defined.
|
||||
*/
|
||||
class ElementsFrozen : public CanteraError
|
||||
{
|
||||
public:
|
||||
//! Constructor for class
|
||||
//! @param func Function where the error occurred.
|
||||
ElementsFrozen(std::string func)
|
||||
: CanteraError(func, "Elements cannot be added after species.") {}
|
||||
};
|
||||
|
||||
//! Base class for phases of matter
|
||||
/*!
|
||||
* Class Phase manages the species and elements in a phase, as well as the
|
||||
|
|
@ -149,8 +163,30 @@ public:
|
|||
//! @param m Element index
|
||||
int atomicNumber(size_t m) const;
|
||||
|
||||
//! Return the element constraint type
|
||||
//! Possible types include:
|
||||
//!
|
||||
//! CT_ELEM_TYPE_TURNEDOFF -1
|
||||
//! CT_ELEM_TYPE_ABSPOS 0
|
||||
//! CT_ELEM_TYPE_ELECTRONCHARGE 1
|
||||
//! CT_ELEM_TYPE_CHARGENEUTRALITY 2
|
||||
//! CT_ELEM_TYPE_LATTICERATIO 3
|
||||
//! CT_ELEM_TYPE_KINETICFROZEN 4
|
||||
//! CT_ELEM_TYPE_SURFACECONSTRAINT 5
|
||||
//! CT_ELEM_TYPE_OTHERCONSTRAINT 6
|
||||
//!
|
||||
//! The default is CT_ELEM_TYPE_ABSPOS.
|
||||
//! @param m Element index
|
||||
//! @return Returns the element type
|
||||
int elementType(size_t m) const;
|
||||
|
||||
//! Change the element type of the mth constraint
|
||||
//! Reassigns an element type.
|
||||
//! @param m Element index
|
||||
//! @param elem_type New elem type to be assigned
|
||||
//! @return Returns the old element type
|
||||
int changeElementType(int m, int elem_type);
|
||||
|
||||
//! Return a read-only reference to the vector of atomic weights.
|
||||
const vector_fp& atomicWeights() const;
|
||||
|
||||
|
|
@ -547,7 +583,7 @@ public:
|
|||
//! Add an element.
|
||||
//! @param symbol Atomic symbol std::string.
|
||||
//! @param weight Atomic mass in amu.
|
||||
void addElement(const std::string& symbol, doublereal weight);
|
||||
void addElement(const std::string& symbol, doublereal weight=-12345.0);
|
||||
|
||||
//! Add an element from an XML specification.
|
||||
//! @param e Reference to the XML_Node where the element is described.
|
||||
|
|
@ -565,7 +601,7 @@ public:
|
|||
//! error.
|
||||
//! @param elem_type Specifies the type of the element constraint
|
||||
//! equation. This defaults to CT_ELEM_TYPE_ABSPOS, i.e., an element.
|
||||
void addUniqueElement(const std::string& symbol, doublereal weight,
|
||||
void addUniqueElement(const std::string& symbol, doublereal weight=-12345.0,
|
||||
int atomicNumber = 0,
|
||||
doublereal entropy298 = ENTROPY298_UNKNOWN,
|
||||
int elem_type = CT_ELEM_TYPE_ABSPOS);
|
||||
|
|
@ -629,9 +665,6 @@ public:
|
|||
|
||||
virtual bool ready() const;
|
||||
|
||||
//! Remove all elements and species
|
||||
void clear();
|
||||
|
||||
//! Return the State Mole Fraction Number
|
||||
DEPRECATED(int stateMFNumber() const) {
|
||||
return m_stateNum;
|
||||
|
|
@ -717,12 +750,21 @@ private:
|
|||
//! of the the phase, this is true.
|
||||
bool m_speciesFrozen;
|
||||
|
||||
//! Pointer to the element object corresponding to this phase. Normally,
|
||||
//! this will be the default Element object common to all phases.
|
||||
Elements* m_Elements;
|
||||
//! If this is true, then no elements may be added to the object.
|
||||
bool m_elementsFrozen;
|
||||
|
||||
//! Vector of the species names
|
||||
std::vector<std::string> m_speciesNames;
|
||||
|
||||
size_t m_mm; //!< Number of elements.
|
||||
vector_fp m_atomicWeights; //!< element atomic weights (kg kmol-1)
|
||||
vector_int m_atomicNumbers; //!< element atomic numbers
|
||||
std::vector<std::string> m_elementNames; //!< element names
|
||||
vector_int m_elem_type; //!< Vector of element types
|
||||
|
||||
//! Entropy at 298.15 K and 1 bar of stable state pure elements (J kmol-1)
|
||||
vector_fp m_entropy298;
|
||||
|
||||
};
|
||||
|
||||
//! typedef for the base Phase class
|
||||
|
|
|
|||
|
|
@ -9,27 +9,16 @@
|
|||
// Copyright 2003 California Institute of Technology
|
||||
|
||||
#include "cantera/thermo/Elements.h"
|
||||
#include "cantera/base/xml.h"
|
||||
#include "cantera/base/ctml.h"
|
||||
#include "cantera/base/ctexceptions.h"
|
||||
#include "cantera/base/stringUtils.h"
|
||||
|
||||
using namespace ctml;
|
||||
using namespace std;
|
||||
|
||||
#ifdef USE_DGG_CODE
|
||||
#include <map>
|
||||
#endif
|
||||
#include <cstdlib>
|
||||
|
||||
namespace Cantera
|
||||
{
|
||||
|
||||
|
||||
/* awData structure */
|
||||
/**
|
||||
* Database for atomic molecular weights
|
||||
*
|
||||
/*! Database for atomic molecular weights
|
||||
* Values are taken from the 1989 Standard Atomic Weights, CRC
|
||||
*
|
||||
* awTable[] is a static function with scope limited to this file.
|
||||
|
|
@ -38,13 +27,11 @@ namespace Cantera
|
|||
*
|
||||
* units = kg / kg-mol (or equivalently gm / gm-mol)
|
||||
*
|
||||
* (note: this structure was picked because it's simple, compact,
|
||||
* and extensible).
|
||||
*
|
||||
* This structure was picked because it's simple, compact, and extensible.
|
||||
*/
|
||||
struct awData {
|
||||
char name[4]; ///< Null Terminated name, First letter capitalized
|
||||
double atomicWeight; ///< atomic weight in kg / kg-mol
|
||||
char name[4]; //!< Null Terminated name, First letter capitalized
|
||||
double atomicWeight; //!< atomic weight in kg / kg-mol
|
||||
};
|
||||
|
||||
/*!
|
||||
|
|
@ -152,28 +139,7 @@ static struct awData aWTable[] = {
|
|||
{"Pu", 244.0482 }
|
||||
};
|
||||
|
||||
|
||||
// Static function to look up an atomic weight
|
||||
/*
|
||||
* This static function looks up the argument string in the
|
||||
* database above and returns the associated molecular weight.
|
||||
* The data are from the periodic table.
|
||||
*
|
||||
* Note: The idea behind this function is to provide a unified
|
||||
* source for the element atomic weights. This helps to
|
||||
* ensure that mass is conserved.
|
||||
*
|
||||
* @param s String, Only the first 3 characters are significant
|
||||
*
|
||||
* @return
|
||||
* Return value contains the atomic weight of the element
|
||||
* If a match for the string is not found, a value of -1.0 is
|
||||
* returned.
|
||||
*
|
||||
* @exception CanteraError
|
||||
* If a match is not found, a CanteraError is thrown as well
|
||||
*/
|
||||
doublereal Elements::LookupWtElements(const std::string& ename)
|
||||
doublereal LookupWtElements(const std::string& ename)
|
||||
{
|
||||
int num = sizeof(aWTable) / sizeof(struct awData);
|
||||
string s3 = ename.substr(0,3);
|
||||
|
|
@ -186,486 +152,4 @@ doublereal Elements::LookupWtElements(const std::string& ename)
|
|||
return -1.0;
|
||||
}
|
||||
|
||||
|
||||
//! Exception class to indicate a fixed set of elements.
|
||||
/*!
|
||||
* This class is used to warn the user when the number of elements
|
||||
* are changed after at least one species is defined.
|
||||
*/
|
||||
class ElementsFrozen : public CanteraError
|
||||
{
|
||||
public:
|
||||
//! Constructor for class
|
||||
/*!
|
||||
* @param func Function where the error occurred.
|
||||
*/
|
||||
ElementsFrozen(string func)
|
||||
: CanteraError(func,
|
||||
"elements cannot be added after species.") {}
|
||||
};
|
||||
|
||||
/*
|
||||
* Elements Class Constructor
|
||||
* We initialize all internal variables to zero here.
|
||||
*/
|
||||
Elements::Elements() :
|
||||
m_mm(0),
|
||||
m_elementsFrozen(false),
|
||||
m_elem_type(0),
|
||||
numSubscribers(0)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Elements Class Destructor
|
||||
* If the number of subscribers is not zero, through an error.
|
||||
* A logic problem has occurred.
|
||||
*
|
||||
* @exception CanteraError
|
||||
*/
|
||||
Elements::~Elements()
|
||||
{
|
||||
if (numSubscribers != 0) {
|
||||
throw CanteraError("~Elements", "numSubscribers not zero");
|
||||
}
|
||||
}
|
||||
|
||||
Elements::Elements(const Elements& right) :
|
||||
m_mm(0),
|
||||
m_elementsFrozen(false),
|
||||
numSubscribers(0)
|
||||
{
|
||||
*this = operator=(right);
|
||||
}
|
||||
|
||||
Elements& Elements::operator=(const Elements& right)
|
||||
{
|
||||
if (&right == this) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
m_mm = right.m_mm;
|
||||
m_elementsFrozen = right.m_elementsFrozen;
|
||||
m_atomicWeights = right.m_atomicWeights;
|
||||
m_atomicNumbers = right.m_atomicNumbers;
|
||||
m_elementNames = right.m_elementNames;
|
||||
m_entropy298 = right.m_entropy298;
|
||||
m_elem_type = right.m_elem_type;
|
||||
numSubscribers = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* freezeElements():
|
||||
*
|
||||
* Set the freeze flag. This is a prerequesite to other
|
||||
* activivities, i.e., this is done before species are defined.
|
||||
*/
|
||||
void Elements::freezeElements()
|
||||
{
|
||||
m_elementsFrozen = true;
|
||||
}
|
||||
|
||||
#ifdef INCL_DEPRECATED_METHODS
|
||||
/*
|
||||
*
|
||||
* Returns an ElementData struct that contains the parameters
|
||||
* for element index m.
|
||||
*/
|
||||
ElementData Elements::element(int m) const
|
||||
{
|
||||
ElementData e;
|
||||
e.name = m_elementNames[m];
|
||||
e.atomicWeight = m_atomicWeights[m];
|
||||
return e;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifdef USE_DGG_CODE
|
||||
size_t Elements::elementIndex(std::string name) const
|
||||
{
|
||||
map<string, int>::const_iterator it;
|
||||
it = m_definedElements.find(name);
|
||||
if (it != m_definedElements.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
size_t Elements::elementIndex(std::string name) const
|
||||
{
|
||||
for (size_t i = 0; i < m_mm; i++) {
|
||||
if (m_elementNames[i] == name) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*
|
||||
* Name of the element with index \c m. @param m Element
|
||||
* index. If m < 0 or m >= nElements() an exception is thrown.
|
||||
*/
|
||||
string Elements::elementName(size_t m) const
|
||||
{
|
||||
if (m >= nElements()) {
|
||||
throw IndexError("Elements::elementName", "m_elementNames",
|
||||
m, nElements());
|
||||
}
|
||||
return m_elementNames[m];
|
||||
}
|
||||
|
||||
|
||||
doublereal Elements::entropyElement298(size_t m) const
|
||||
{
|
||||
AssertThrowMsg(m_entropy298[m] != ENTROPY298_UNKNOWN,
|
||||
"Elements::entropy298",
|
||||
"Entropy at 298 K of element is unknown");
|
||||
AssertTrace(m < m_mm);
|
||||
return (m_entropy298[m]);
|
||||
}
|
||||
//====================================================================================================================
|
||||
//! Return the element constraint type
|
||||
/*!
|
||||
* Possible types include:
|
||||
*
|
||||
* CT_ELEM_TYPE_TURNEDOFF -1
|
||||
* CT_ELEM_TYPE_ABSPOS 0
|
||||
* CT_ELEM_TYPE_ELECTRONCHARGE 1
|
||||
* CT_ELEM_TYPE_CHARGENEUTRALITY 2
|
||||
* CT_ELEM_TYPE_LATTICERATIO 3
|
||||
* CT_ELEM_TYPE_KINETICFROZEN 4
|
||||
* CT_ELEM_TYPE_SURFACECONSTRAINT 5
|
||||
* CT_ELEM_TYPE_OTHERCONSTRAINT 6
|
||||
*
|
||||
* The default is CT_ELEM_TYPE_ABSPOS
|
||||
*/
|
||||
int Elements::elementType(size_t m) const
|
||||
{
|
||||
return m_elem_type[m];
|
||||
}
|
||||
//====================================================================================================================
|
||||
// Change the element type of the mth constraint
|
||||
/*
|
||||
* Reassigns an element type
|
||||
*
|
||||
* @param m Element index
|
||||
* @param elem_type New elem type to be assigned
|
||||
*
|
||||
* @return Returns the old element type
|
||||
*/
|
||||
int Elements::changeElementType(int m, int elem_type)
|
||||
{
|
||||
int old = m_elem_type[m];
|
||||
m_elem_type[m] = elem_type;
|
||||
return old;
|
||||
}
|
||||
//====================================================================================================================
|
||||
/*
|
||||
*
|
||||
* Add an element to the current set of elements in the current object.
|
||||
* @param symbol symbol string
|
||||
* @param weight atomic weight in kg/kmol.
|
||||
*
|
||||
* The default weight is a special value, which will cause the
|
||||
* routine to look up the actual weight via a string lookup.
|
||||
*
|
||||
* There are two interfaces to this routine. The XML interface
|
||||
* looks up the required parameters for the regular interface
|
||||
* and then calls the base routine.
|
||||
*/
|
||||
void Elements::
|
||||
addElement(const std::string& symbol, doublereal weight)
|
||||
{
|
||||
if (weight == -12345.0) {
|
||||
weight = LookupWtElements(symbol);
|
||||
if (weight < 0.0) {
|
||||
throw ElementsFrozen("addElement");
|
||||
}
|
||||
}
|
||||
if (m_elementsFrozen) {
|
||||
throw ElementsFrozen("addElement");
|
||||
return;
|
||||
}
|
||||
m_atomicWeights.push_back(weight);
|
||||
m_elementNames.push_back(symbol);
|
||||
#ifdef USE_DGG_CODE
|
||||
m_definedElements[symbol] = nElements() + 1;
|
||||
#endif
|
||||
if (symbol == "E") {
|
||||
m_elem_type.push_back(CT_ELEM_TYPE_ELECTRONCHARGE);
|
||||
} else {
|
||||
m_elem_type.push_back(CT_ELEM_TYPE_ABSPOS);
|
||||
}
|
||||
|
||||
m_mm++;
|
||||
}
|
||||
//===========================================================================================================
|
||||
void Elements::
|
||||
addElement(const XML_Node& e)
|
||||
{
|
||||
doublereal weight = atof(e["atomicWt"].c_str());
|
||||
string symbol = e["name"];
|
||||
addElement(symbol, weight);
|
||||
}
|
||||
//===========================================================================================================
|
||||
/*
|
||||
* addUniqueElement():
|
||||
*
|
||||
* Add a unique element to the set. This routine will not allow
|
||||
* duplicate elements to be input.
|
||||
*
|
||||
* @param symbol symbol string
|
||||
* @param weight atomic weight in kg/kmol.
|
||||
*
|
||||
*
|
||||
* The default weight is a special value, which will cause the
|
||||
* routine to look up the actual weight via a string lookup.
|
||||
*/
|
||||
#ifdef USE_DGG_CODE
|
||||
void Elements::
|
||||
addUniqueElement(const std::string& symbol, doublereal weight, int atomicNumber,
|
||||
doublereal entropy298, int elem_type)
|
||||
{
|
||||
if (m_elementsFrozen) {
|
||||
throw ElementsFrozen("addElement");
|
||||
}
|
||||
|
||||
if (weight == -12345.0) {
|
||||
weight = LookupWtElements(symbol);
|
||||
}
|
||||
|
||||
/*
|
||||
* First decide if this element has been previously added.
|
||||
* If it unique, add it to the list.
|
||||
*/
|
||||
|
||||
int i = m_definedElements[symbol] - 1;
|
||||
if (i < 0) {
|
||||
m_atomicWeights.push_back(weight);
|
||||
m_elementNames.push_back(symbol);
|
||||
m_atomicNumbers.push_back(atomicNumber);
|
||||
m_entropy298.push_back(entropy298);
|
||||
if (symbol == "E") {
|
||||
m_elem_type.push_back(CT_ELEM_TYPE_ELECTRONCHARGE);
|
||||
} else {
|
||||
m_elem_type.push_back(elem_type);
|
||||
}
|
||||
m_mm++;
|
||||
} else {
|
||||
if (m_atomicWeights[i] != weight) {
|
||||
throw CanteraError("AddUniqueElement",
|
||||
"Duplicate Elements (" + symbol + ") have different weights");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
void Elements::
|
||||
addUniqueElement(const std::string& symbol,
|
||||
doublereal weight, int atomicNumber, doublereal entropy298,
|
||||
int elem_type)
|
||||
{
|
||||
if (weight == -12345.0) {
|
||||
weight = LookupWtElements(symbol);
|
||||
if (weight < 0.0) {
|
||||
throw ElementsFrozen("addElement");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* First decide if this element has been previously added
|
||||
* by conducting a string search. If it unique, add it to
|
||||
* the list.
|
||||
*/
|
||||
int ifound = 0;
|
||||
int i = 0;
|
||||
for (vector<string>::const_iterator it = m_elementNames.begin();
|
||||
it < m_elementNames.end(); ++it, ++i) {
|
||||
if (*it == symbol) {
|
||||
ifound = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ifound) {
|
||||
if (m_elementsFrozen) {
|
||||
throw ElementsFrozen("addElement");
|
||||
return;
|
||||
}
|
||||
m_atomicWeights.push_back(weight);
|
||||
m_elementNames.push_back(symbol);
|
||||
m_atomicNumbers.push_back(atomicNumber);
|
||||
m_entropy298.push_back(entropy298);
|
||||
if (symbol == "E") {
|
||||
m_elem_type.push_back(CT_ELEM_TYPE_ELECTRONCHARGE);
|
||||
} else {
|
||||
m_elem_type.push_back(elem_type);
|
||||
}
|
||||
m_mm++;
|
||||
} else {
|
||||
if (m_atomicWeights[i] != weight) {
|
||||
throw CanteraError("AddUniqueElement",
|
||||
"Duplicate Elements (" + symbol + ") have different weights");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* @todo call addUniqueElement(symbol, weight) instead of
|
||||
* addElement.
|
||||
*/
|
||||
void Elements::
|
||||
addUniqueElement(const XML_Node& e)
|
||||
{
|
||||
doublereal weight = 0.0;
|
||||
if (e.hasAttrib("atomicWt")) {
|
||||
weight = atof(stripws(e["atomicWt"]).c_str());
|
||||
}
|
||||
int anum = 0;
|
||||
if (e.hasAttrib("atomicNumber")) {
|
||||
anum = atoi(stripws(e["atomicNumber"]).c_str());
|
||||
}
|
||||
string symbol = e["name"];
|
||||
doublereal entropy298 = ENTROPY298_UNKNOWN;
|
||||
if (e.hasChild("entropy298")) {
|
||||
XML_Node& e298Node = e.child("entropy298");
|
||||
if (e298Node.hasAttrib("value")) {
|
||||
entropy298 = atofCheck(stripws(e298Node["value"]).c_str());
|
||||
}
|
||||
}
|
||||
if (weight != 0.0) {
|
||||
addUniqueElement(symbol, weight, anum, entropy298);
|
||||
} else {
|
||||
addUniqueElement(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// True if freezeElements has been called.
|
||||
bool Elements::elementsFrozen() const
|
||||
{
|
||||
return m_elementsFrozen;
|
||||
}
|
||||
|
||||
/*
|
||||
* clear()
|
||||
*
|
||||
* Remove all elements from the structure.
|
||||
*/
|
||||
void Elements::clear()
|
||||
{
|
||||
m_mm = 0;
|
||||
m_atomicWeights.resize(0);
|
||||
m_elementNames.resize(0);
|
||||
m_entropy298.resize(0);
|
||||
m_elem_type.resize(0);
|
||||
m_elementsFrozen = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* ready():
|
||||
*
|
||||
* True if the elements have been frozen
|
||||
*/
|
||||
bool Elements::ready() const
|
||||
{
|
||||
return (m_elementsFrozen);
|
||||
}
|
||||
|
||||
|
||||
void Elements::addElementsFromXML(const XML_Node& phase)
|
||||
{
|
||||
|
||||
// get the declared element names
|
||||
if (! phase.hasChild("elementArray")) {
|
||||
throw CanteraError("Elements::addElementsFromXML",
|
||||
"phase xml node doesn't have \"elementArray\" XML Node");
|
||||
}
|
||||
XML_Node& elements = phase.child("elementArray");
|
||||
vector<string> enames;
|
||||
getStringArray(elements, enames);
|
||||
|
||||
// // element database defaults to elements.xml
|
||||
string element_database = "elements.xml";
|
||||
if (elements.hasAttrib("datasrc")) {
|
||||
element_database = elements["datasrc"];
|
||||
}
|
||||
|
||||
XML_Node* doc = get_XML_File(element_database);
|
||||
XML_Node* dbe = &doc->child("ctml/elementData");
|
||||
|
||||
XML_Node& root = phase.root();
|
||||
XML_Node* local_db = 0;
|
||||
if (root.hasChild("ctml")) {
|
||||
if (root.child("ctml").hasChild("elementData")) {
|
||||
local_db = &root.child("ctml/elementData");
|
||||
}
|
||||
}
|
||||
|
||||
int nel = static_cast<int>(enames.size());
|
||||
int i;
|
||||
string enm;
|
||||
XML_Node* e = 0;
|
||||
for (i = 0; i < nel; i++) {
|
||||
e = 0;
|
||||
if (local_db) {
|
||||
//writelog("looking in local database.");
|
||||
e = local_db->findByAttr("name",enames[i]);
|
||||
//if (!e) writelog(enames[i]+" not found.");
|
||||
}
|
||||
if (!e) {
|
||||
e = dbe->findByAttr("name",enames[i]);
|
||||
}
|
||||
if (e) {
|
||||
addUniqueElement(*e);
|
||||
} else {
|
||||
throw CanteraError("addElementsFromXML","no data for element "
|
||||
+enames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* subscribe(), unsubscribe(), and reportSubscriptions():
|
||||
*
|
||||
* Handles setting and reporting the number of subscriptions to this
|
||||
* object.
|
||||
*/
|
||||
void Elements::subscribe()
|
||||
{
|
||||
++numSubscribers;
|
||||
}
|
||||
int Elements::unsubscribe()
|
||||
{
|
||||
--numSubscribers;
|
||||
return numSubscribers;
|
||||
}
|
||||
int Elements::reportSubscriptions() const
|
||||
{
|
||||
return numSubscribers;
|
||||
}
|
||||
|
||||
/********************* GLOBAL STATIC SECTION **************************/
|
||||
/*
|
||||
* We keep track of a vector of pointers to element objects.
|
||||
* Initially there are no Elements objects. Whenever one is created,
|
||||
* the pointer to that object is added onto this list.
|
||||
*/
|
||||
vector<Elements*> Elements::Global_Elements_List;
|
||||
/***********************************************************************/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,10 +25,11 @@ Phase::Phase() :
|
|||
m_dens(0.001),
|
||||
m_mmw(0.0),
|
||||
m_stateNum(-1),
|
||||
m_speciesFrozen(false) ,
|
||||
m_Elements(new Elements())
|
||||
m_speciesFrozen(false),
|
||||
m_elementsFrozen(false),
|
||||
m_mm(0),
|
||||
m_elem_type(0)
|
||||
{
|
||||
m_Elements->subscribe();
|
||||
}
|
||||
|
||||
Phase::Phase(const Phase& right) :
|
||||
|
|
@ -42,7 +43,9 @@ Phase::Phase(const Phase& right) :
|
|||
m_mmw(0.0),
|
||||
m_stateNum(-1),
|
||||
m_speciesFrozen(false) ,
|
||||
m_Elements(0)
|
||||
m_elementsFrozen(false),
|
||||
m_mm(0),
|
||||
m_elem_type(0)
|
||||
{
|
||||
// Use the assignment operator to do the actual copying
|
||||
*this = operator=(right);
|
||||
|
|
@ -66,30 +69,20 @@ Phase& Phase::operator=(const Phase& right)
|
|||
m_molwts = right.m_molwts;
|
||||
m_rmolwts = right.m_rmolwts;
|
||||
m_stateNum = -1;
|
||||
|
||||
m_speciesFrozen = right.m_speciesFrozen;
|
||||
if (m_Elements) {
|
||||
int nleft = m_Elements->unsubscribe();
|
||||
if (nleft <= 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;
|
||||
}
|
||||
}
|
||||
m_Elements = right.m_Elements;
|
||||
if (m_Elements) {
|
||||
m_Elements->subscribe();
|
||||
}
|
||||
m_speciesNames = right.m_speciesNames;
|
||||
m_speciesComp = right.m_speciesComp;
|
||||
m_speciesCharge = right.m_speciesCharge;
|
||||
m_speciesSize = right.m_speciesSize;
|
||||
|
||||
m_mm = right.m_mm;
|
||||
m_elementsFrozen = right.m_elementsFrozen;
|
||||
m_atomicWeights = right.m_atomicWeights;
|
||||
m_atomicNumbers = right.m_atomicNumbers;
|
||||
m_elementNames = right.m_elementNames;
|
||||
m_entropy298 = right.m_entropy298;
|
||||
m_elem_type = right.m_elem_type;
|
||||
/*
|
||||
* This is a little complicated. -> Because we delete m_xml
|
||||
* in the destructor, we own m_xml completely, and we need
|
||||
|
|
@ -117,24 +110,6 @@ Phase::~Phase()
|
|||
delete m_xml;
|
||||
m_xml = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Phase::stateMFChangeCalc(bool forcerChange)
|
||||
|
|
@ -174,52 +149,71 @@ void Phase::setName(std::string nm)
|
|||
|
||||
size_t Phase::nElements() const
|
||||
{
|
||||
return m_Elements->nElements();
|
||||
return m_mm;
|
||||
}
|
||||
|
||||
string Phase::elementName(size_t m) const
|
||||
{
|
||||
return m_Elements->elementName(m);
|
||||
if (m >= nElements()) {
|
||||
throw IndexError("Elements::elementName", "m_elementNames",
|
||||
m, nElements());
|
||||
}
|
||||
return m_elementNames[m];
|
||||
}
|
||||
|
||||
size_t Phase::elementIndex(std::string name) const
|
||||
{
|
||||
return m_Elements->elementIndex(name);
|
||||
for (size_t i = 0; i < m_mm; i++) {
|
||||
if (m_elementNames[i] == name) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
const vector<string>& Phase::elementNames() const
|
||||
{
|
||||
return m_Elements->elementNames();
|
||||
return m_elementNames;
|
||||
}
|
||||
|
||||
doublereal Phase::atomicWeight(size_t m) const
|
||||
{
|
||||
return m_Elements->atomicWeight(m);
|
||||
return m_atomicWeights[m];
|
||||
}
|
||||
|
||||
doublereal Phase::entropyElement298(size_t m) const
|
||||
{
|
||||
return m_Elements->entropyElement298(m);
|
||||
AssertThrowMsg(m_entropy298[m] != ENTROPY298_UNKNOWN,
|
||||
"Elements::entropy298",
|
||||
"Entropy at 298 K of element is unknown");
|
||||
AssertTrace(m < m_mm);
|
||||
return (m_entropy298[m]);
|
||||
}
|
||||
|
||||
const vector_fp& Phase::atomicWeights() const
|
||||
{
|
||||
return m_Elements->atomicWeights();
|
||||
return m_atomicWeights;
|
||||
}
|
||||
|
||||
int Phase::atomicNumber(size_t m) const
|
||||
{
|
||||
return m_Elements->atomicNumber(m);
|
||||
return m_atomicNumbers[m];
|
||||
}
|
||||
|
||||
int Phase::elementType(size_t m) const
|
||||
{
|
||||
return m_Elements->elementType(m);
|
||||
return m_elem_type[m];
|
||||
}
|
||||
|
||||
int Phase::changeElementType(int m, int elem_type)
|
||||
{
|
||||
int old = m_elem_type[m];
|
||||
m_elem_type[m] = elem_type;
|
||||
return old;
|
||||
}
|
||||
|
||||
doublereal Phase::nAtoms(size_t k, size_t m) const
|
||||
{
|
||||
const size_t m_mm = m_Elements->nElements();
|
||||
if (m >= m_mm) {
|
||||
throw IndexError("Phase::nAtoms", "", m, nElements());
|
||||
}
|
||||
|
|
@ -231,7 +225,6 @@ doublereal Phase::nAtoms(size_t k, size_t m) const
|
|||
|
||||
void Phase::getAtoms(size_t k, double* atomArray) const
|
||||
{
|
||||
const size_t m_mm = m_Elements->nElements();
|
||||
for (size_t m = 0; m < m_mm; m++) {
|
||||
atomArray[m] = (double) m_speciesComp[m_mm * k + m];
|
||||
}
|
||||
|
|
@ -655,40 +648,165 @@ doublereal Phase::sum_xlogQ(doublereal* Q) const
|
|||
|
||||
void Phase::addElement(const std::string& symbol, doublereal weight)
|
||||
{
|
||||
m_Elements->addElement(symbol, weight);
|
||||
if (weight == -12345.0) {
|
||||
weight = LookupWtElements(symbol);
|
||||
if (weight < 0.0) {
|
||||
throw ElementsFrozen("addElement");
|
||||
}
|
||||
}
|
||||
if (m_elementsFrozen) {
|
||||
throw ElementsFrozen("addElement");
|
||||
return;
|
||||
}
|
||||
m_atomicWeights.push_back(weight);
|
||||
m_elementNames.push_back(symbol);
|
||||
if (symbol == "E") {
|
||||
m_elem_type.push_back(CT_ELEM_TYPE_ELECTRONCHARGE);
|
||||
} else {
|
||||
m_elem_type.push_back(CT_ELEM_TYPE_ABSPOS);
|
||||
}
|
||||
|
||||
m_mm++;
|
||||
}
|
||||
|
||||
void Phase::addElement(const XML_Node& e)
|
||||
{
|
||||
m_Elements->addElement(e);
|
||||
doublereal weight = atof(e["atomicWt"].c_str());
|
||||
string symbol = e["name"];
|
||||
addElement(symbol, weight);
|
||||
}
|
||||
|
||||
void Phase::addUniqueElement(const std::string& symbol, doublereal weight,
|
||||
int atomicNumber, doublereal entropy298,
|
||||
int elem_type)
|
||||
{
|
||||
m_Elements->addUniqueElement(symbol, weight, atomicNumber,
|
||||
entropy298, elem_type);
|
||||
if (weight == -12345.0) {
|
||||
weight = LookupWtElements(symbol);
|
||||
if (weight < 0.0) {
|
||||
throw ElementsFrozen("addElement");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* First decide if this element has been previously added
|
||||
* by conducting a string search. If it unique, add it to
|
||||
* the list.
|
||||
*/
|
||||
int ifound = 0;
|
||||
int i = 0;
|
||||
for (vector<string>::const_iterator it = m_elementNames.begin();
|
||||
it < m_elementNames.end(); ++it, ++i) {
|
||||
if (*it == symbol) {
|
||||
ifound = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ifound) {
|
||||
if (m_elementsFrozen) {
|
||||
throw ElementsFrozen("addElement");
|
||||
return;
|
||||
}
|
||||
m_atomicWeights.push_back(weight);
|
||||
m_elementNames.push_back(symbol);
|
||||
m_atomicNumbers.push_back(atomicNumber);
|
||||
m_entropy298.push_back(entropy298);
|
||||
if (symbol == "E") {
|
||||
m_elem_type.push_back(CT_ELEM_TYPE_ELECTRONCHARGE);
|
||||
} else {
|
||||
m_elem_type.push_back(elem_type);
|
||||
}
|
||||
m_mm++;
|
||||
} else {
|
||||
if (m_atomicWeights[i] != weight) {
|
||||
throw CanteraError("AddUniqueElement",
|
||||
"Duplicate Elements (" + symbol + ") have different weights");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Phase::addUniqueElement(const XML_Node& e)
|
||||
{
|
||||
m_Elements->addUniqueElement(e);
|
||||
doublereal weight = 0.0;
|
||||
if (e.hasAttrib("atomicWt")) {
|
||||
weight = atof(stripws(e["atomicWt"]).c_str());
|
||||
}
|
||||
int anum = 0;
|
||||
if (e.hasAttrib("atomicNumber")) {
|
||||
anum = atoi(stripws(e["atomicNumber"]).c_str());
|
||||
}
|
||||
string symbol = e["name"];
|
||||
doublereal entropy298 = ENTROPY298_UNKNOWN;
|
||||
if (e.hasChild("entropy298")) {
|
||||
XML_Node& e298Node = e.child("entropy298");
|
||||
if (e298Node.hasAttrib("value")) {
|
||||
entropy298 = atofCheck(stripws(e298Node["value"]).c_str());
|
||||
}
|
||||
}
|
||||
if (weight != 0.0) {
|
||||
addUniqueElement(symbol, weight, anum, entropy298);
|
||||
} else {
|
||||
addUniqueElement(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
void Phase::addElementsFromXML(const XML_Node& phase)
|
||||
{
|
||||
m_Elements->addElementsFromXML(phase);
|
||||
// get the declared element names
|
||||
if (! phase.hasChild("elementArray")) {
|
||||
throw CanteraError("Elements::addElementsFromXML",
|
||||
"phase xml node doesn't have \"elementArray\" XML Node");
|
||||
}
|
||||
XML_Node& elements = phase.child("elementArray");
|
||||
vector<string> enames;
|
||||
ctml::getStringArray(elements, enames);
|
||||
|
||||
// // element database defaults to elements.xml
|
||||
string element_database = "elements.xml";
|
||||
if (elements.hasAttrib("datasrc")) {
|
||||
element_database = elements["datasrc"];
|
||||
}
|
||||
|
||||
XML_Node* doc = get_XML_File(element_database);
|
||||
XML_Node* dbe = &doc->child("ctml/elementData");
|
||||
|
||||
XML_Node& root = phase.root();
|
||||
XML_Node* local_db = 0;
|
||||
if (root.hasChild("ctml")) {
|
||||
if (root.child("ctml").hasChild("elementData")) {
|
||||
local_db = &root.child("ctml/elementData");
|
||||
}
|
||||
}
|
||||
|
||||
int nel = static_cast<int>(enames.size());
|
||||
int i;
|
||||
string enm;
|
||||
XML_Node* e = 0;
|
||||
for (i = 0; i < nel; i++) {
|
||||
e = 0;
|
||||
if (local_db) {
|
||||
//writelog("looking in local database.");
|
||||
e = local_db->findByAttr("name",enames[i]);
|
||||
//if (!e) writelog(enames[i]+" not found.");
|
||||
}
|
||||
if (!e) {
|
||||
e = dbe->findByAttr("name",enames[i]);
|
||||
}
|
||||
if (e) {
|
||||
addUniqueElement(*e);
|
||||
} else {
|
||||
throw CanteraError("addElementsFromXML","no data for element "
|
||||
+enames[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Phase::freezeElements()
|
||||
{
|
||||
m_Elements->freezeElements();
|
||||
m_elementsFrozen = true;
|
||||
}
|
||||
|
||||
bool Phase::elementsFrozen()
|
||||
{
|
||||
return m_Elements->elementsFrozen();
|
||||
return m_elementsFrozen;
|
||||
}
|
||||
|
||||
size_t Phase::addUniqueElementAfterFreeze(const std::string& symbol,
|
||||
|
|
@ -700,10 +818,9 @@ size_t Phase::addUniqueElementAfterFreeze(const std::string& symbol,
|
|||
return ii;
|
||||
}
|
||||
// Check to see that the element isn't really in the list
|
||||
m_Elements->m_elementsFrozen = false;
|
||||
m_elementsFrozen = false;
|
||||
addUniqueElement(symbol, weight, atomicNumber, entropy298, elem_type);
|
||||
m_Elements->m_elementsFrozen = true;
|
||||
size_t m_mm = m_Elements->nElements();
|
||||
m_elementsFrozen = true;
|
||||
ii = elementIndex(symbol);
|
||||
if (ii != m_mm-1) {
|
||||
throw CanteraError("Phase::addElementAfterFreeze()", "confused");
|
||||
|
|
@ -725,11 +842,11 @@ size_t Phase::addUniqueElementAfterFreeze(const std::string& symbol,
|
|||
void Phase::addSpecies(const std::string& name, const doublereal* comp,
|
||||
doublereal charge, doublereal size)
|
||||
{
|
||||
m_Elements->freezeElements();
|
||||
freezeElements();
|
||||
m_speciesNames.push_back(name);
|
||||
m_speciesCharge.push_back(charge);
|
||||
m_speciesSize.push_back(size);
|
||||
size_t ne = m_Elements->nElements();
|
||||
size_t ne = nElements();
|
||||
// Create a changeable copy of the element composition. We now change
|
||||
// the charge potentially
|
||||
vector_fp compNew(ne);
|
||||
|
|
@ -737,9 +854,9 @@ void Phase::addSpecies(const std::string& name, const doublereal* comp,
|
|||
compNew[m] = comp[m];
|
||||
}
|
||||
double wt = 0.0;
|
||||
const vector_fp& aw = m_Elements->atomicWeights();
|
||||
const vector_fp& aw = atomicWeights();
|
||||
if (charge != 0.0) {
|
||||
size_t eindex = m_Elements->elementIndex("E");
|
||||
size_t eindex = elementIndex("E");
|
||||
if (eindex != npos) {
|
||||
doublereal ecomp = compNew[eindex];
|
||||
if (fabs(charge + ecomp) > 0.001) {
|
||||
|
|
@ -756,8 +873,8 @@ void Phase::addSpecies(const std::string& name, const doublereal* comp,
|
|||
} else {
|
||||
addUniqueElementAfterFreeze("E", 0.000545, 0, 0.0,
|
||||
CT_ELEM_TYPE_ELECTRONCHARGE);
|
||||
ne = m_Elements->nElements();
|
||||
eindex = m_Elements->elementIndex("E");
|
||||
ne = nElements();
|
||||
eindex = elementIndex("E");
|
||||
compNew.resize(ne);
|
||||
compNew[ne - 1] = - charge;
|
||||
}
|
||||
|
|
@ -779,7 +896,6 @@ void Phase::addUniqueSpecies(const std::string& name, const doublereal* comp,
|
|||
// 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.
|
||||
size_t m_mm = m_Elements->nElements();
|
||||
for (size_t i = 0; i < m_mm; i++) {
|
||||
if (comp[i] != m_speciesComp[m_kk * m_mm + i]) {
|
||||
throw CanteraError("addUniqueSpecies",
|
||||
|
|
@ -809,7 +925,6 @@ void Phase::freezeSpecies()
|
|||
m_speciesFrozen = true;
|
||||
init(molecularWeights());
|
||||
size_t kk = nSpecies();
|
||||
size_t nv = kk + 2;
|
||||
m_kk = nSpecies();
|
||||
}
|
||||
|
||||
|
|
@ -848,7 +963,7 @@ void Phase::init(const vector_fp& mw)
|
|||
|
||||
bool Phase::ready() const
|
||||
{
|
||||
return (m_kk > 0 && m_Elements->elementsFrozen() && m_speciesFrozen);
|
||||
return (m_kk > 0 && m_elementsFrozen && m_speciesFrozen);
|
||||
}
|
||||
|
||||
} // namespace Cantera
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue