Cantera 2.6.0
Modules | Classes | Functions
Thermodynamic Properties

These classes are used to compute the thermodynamic properties of phases of matter. More...

Collaboration diagram for Thermodynamic Properties:


 Species Standard-State Thermodynamic Properties
 In this module we describe Cantera's treatment of pressure dependent standard states (PDSS) objects.
 Species Reference-State Thermodynamic Properties
 To compute the thermodynamic properties of multicomponent solutions, it is necessary to know something about the thermodynamic properties of the individual species present in the solution.


class  BinarySolutionTabulatedThermo
 Overloads the virtual methods of class IdealSolidSolnPhase to implement tabulated standard state thermodynamics for one species in a binary solution. More...
class  DebyeHuckel
 Class DebyeHuckel represents a dilute liquid electrolyte phase which obeys the Debye Huckel formulation for nonideality. More...
class  EdgePhase
 A thermodynamic phase representing a one dimensional edge between two surfaces. More...
class  HMWSoln
 Class HMWSoln represents a dilute or concentrated liquid electrolyte phase which obeys the Pitzer formulation for nonideality. More...
class  IdealGasPhase
 Class IdealGasPhase represents low-density gases that obey the ideal gas equation of state. More...
class  IdealMolalSoln
 This phase is based upon the mixing-rule assumption that all molality-based activity coefficients are equal to one. More...
class  IdealSolidSolnPhase
 Class IdealSolidSolnPhase represents a condensed phase ideal solution compound. More...
class  IdealSolnGasVPSS
 An ideal solution approximation of a phase. More...
class  LatticePhase
 A simple thermodynamic model for a bulk phase, assuming a lattice of solid atoms. More...
class  MargulesVPSSTP
 MargulesVPSSTP is a derived class of GibbsExcessVPSSTP that employs the Margules approximation for the excess Gibbs free energy. More...
class  MaskellSolidSolnPhase
 Class MaskellSolidSolnPhase represents a condensed phase non-ideal solution with 2 species following the thermodynamic model described in Maskell, Shaw, and Tye, Manganese Dioxide Electrode – IX, Electrochimica Acta 28(2) pp 231-235, 1983. More...
class  MetalPhase
 Class MetalPhase represents electrons in a metal. More...
class  MixtureFugacityTP
 This is a filter class for ThermoPhase that implements some preparatory steps for efficiently handling mixture of gases that whose standard states are defined as ideal gases, but which describe also non-ideal solutions. More...
class  PengRobinson
 Implementation of a multi-species Peng-Robinson equation of state. More...
class  PureFluidPhase
 This phase object consists of a single component that can be a gas, a liquid, a mixed gas-liquid fluid, or a fluid beyond its critical point. More...
class  RedlichKisterVPSSTP
 RedlichKisterVPSSTP is a derived class of GibbsExcessVPSSTP that employs the Redlich-Kister approximation for the excess Gibbs free energy. More...
class  RedlichKwongMFTP
 Implementation of a multi-species Redlich-Kwong equation of state. More...
class  SingleSpeciesTP
 The SingleSpeciesTP class is a filter class for ThermoPhase. More...
class  StoichSubstance
 Class StoichSubstance represents a stoichiometric (fixed composition) incompressible substance. More...
class  SurfPhase
 A simple thermodynamic model for a surface phase, assuming an ideal solution model. More...
class  ThermoPhase
 Base class for a phase with thermodynamic properties. More...
class  VPStandardStateTP
 This is a filter class for ThermoPhase that implements some preparatory steps for efficiently handling a variable pressure standard state for species. More...
class  WaterPropsIAPWS
 Class for calculating the equation of state of water. More...
class  WaterSSTP
 Class for single-component water. More...


void importPhase (XML_Node &phase, ThermoPhase *th)
 Import a phase information into an empty ThermoPhase object. More...

Detailed Description

These classes are used to compute the thermodynamic properties of phases of matter.

The main base class for describing thermodynamic properties of phases within Cantera is called ThermoPhase. ThermoPhase is a large class that describes the interface within Cantera to Thermodynamic functions for a phase.

The calculation of thermodynamic functions within ThermoPhase is broken down roughly into two or more steps. First, the standard state properties of all of the species are calculated at the current temperature and at either the current pressure or at a reference pressure. If the calculation is carried out at a reference pressure instead of at the current pressure the calculation is called a "reference state properties" calculation, just to make the distinction (even though it may be considered to be a fixed-pressure standard-state calculation). The next step is to adjust the reference state calculation to the current pressure. The thermodynamic functions then are considered to be at the standard state of each species. Lastly the mixing contributions are added to arrive at the thermodynamic functions for the solution.

The ThermoPhase class provides interfaces to thermodynamic properties calculated for the reference state of each species, the standard state values for each species, the thermodynamic functions for solution values, both on a per mole of solution basis (such as enthalpy_mole()), on a per kg of solution basis, and on a partial molar basis for each species (such as getPartialMolarEnthalpies(double *hbar)). At each level, functions for the enthalpy, entropy, Gibbs free energy, internal energy, and volume are provided. So, 5 levels (reference state, standard state, partial molar, per mole of solution, and per mass of solution) and 5 functions multiplied together makes 25 possible functions. That's why ThermoPhase is such a large class.

Categorizing the Different ThermoPhase Objects

ThermoPhase objects may be cataloged into four general bins.

The first type are those whose underlying species have a reference state associated with them. The reference state describes the thermodynamic functions for a species at a single reference pressure, \(p_0\). The thermodynamic functions are specified via derived objects of the SpeciesThermoInterpType object class, and usually consist of polynomials in temperature such as the NASA polynomial or the SHOMATE polynomial. Calculators for these reference states, which manage the calculation for all of the species in a phase, are all derived from the virtual base class SimpleThermo. Calculators are needed because the actual calculation of the reference state thermodynamics has been shown to be relatively expensive. A great deal of work has gone into devising efficient schemes for calculating the thermodynamic polynomials of a set of species in a phase, in particular gas species in ideal gas phases whose reference state thermodynamics is specified by NASA polynomials.

The reference state thermodynamics combined with the mixing rules and an assumption about the pressure dependence yields the thermodynamic functions for the phase. Expressions involving the specification of the fugacities of species would fall into this category of ThermoPhase objects. Note, however, that at this time, we do not have any nontrivial examples of these types of phases. In general, the independent variables that completely describe the state of the system for this class are temperature, the phase density, and \( N - 1 \) species mole or mass fractions. Additionally, if the phase involves charged species, the phase electric potential is an added independent variable. Examples of the first class of ThermoPhase functions, which includes the IdealGasPhase object, the most commonly used object with Cantera, are given below.

The second class of objects are actually all derivatives of the VPStandardState class listed above. These classes assume that there exists a standard state for each species in the phase, where the Thermodynamic functions are specified as a function of temperature and pressure. Standard state objects for each species are all derived from the PDSS virtual base class. In turn, these standard states may employ reference state calculation to aid in their calculations. However, there are some PDSS objects which do not employ reference state calculations. An example of this is real equation of state for liquid water used within the calculation of brine thermodynamics. In general, the independent variables that completely describe the state of the system for this class are temperature, the phase pressure, and N - 1 species mole or mass fractions or molalities. The standard state thermodynamics combined with the mixing rules yields the thermodynamic functions for the phase. Mixing rules are given in terms of specifying the molar-base activity coefficients or activities. Lists of phases which belong to this group are given below

Note, the ideal gas and ideal solution approximations are lumped together in the class IdealSolnGasVPSS, because at this level they look alike having the same mixing rules with respect to the specification of the excess thermodynamic properties.

The third class of objects are actually all derivatives of the MolalityVPSSTP object. They assume that the standard states are temperature and pressure dependent. But, they also assume that the standard states are molality-based. In other words they assume that the standard state of the solute species are in a pseudo state of 1 molality but at infinite dilution. A solvent must be specified in these calculations. The solvent is assumed to be species zero, and its standard state is the pure solvent state. Lists of phases which belong to this group are:

The fourth class of ThermoPhase objects are stoichiometric phases. Stoichiometric phases are phases which consist of one and only one species. The class SingleSpeciesTP is the base class for these substances. Within the class, the general ThermoPhase interface is dumbed down so that phases consisting of one species may be succinctly described. These phases may have PDSS classes or SimpleThermo calculators associated with them. In general, the independent variables that completely describe the state of the system for this class are temperature and either the phase density or the phase pressure. Lists of classes in this group are given below.

The reader may note that there are duplications in functionality in the above lists. This is true. And, it's used for the internal verification of capabilities within Cantera's unit tests.

Setting the State of the phase

Typically, the way the ThermoPhase object works is that there are a set of functions that set the state of the phase via setting the internal independent variables. Then, there are another set of functions that query the thermodynamic functions evaluated at the current State of the phase. Internally, most of the intermediate work generally occurs at the point where the internal state of the system is set and not at the time when individual thermodynamic functions are queried (though the actual breakdown in work is dependent on the individual derived ThermoPhase object). Therefore, for efficiency, the user should lump together queries of thermodynamic functions after setting the state. Moreover, in setting the state, if the density is the independent variable, the following order should be used:

For classes which inherit from VPStandardStateTP, the above order may be used, or the following order may be used. It's not important.

The following functions are used to set the state:

setState_TPX() Sets the temperature, mole fractions and then the pressure of the phase.
setState_TPY() Set the temperature, mass fractions and then the pressure of the phase.
setState_TPM() Set the temperature, solute molalities, and then the pressure of the phase. Only from ThermoPhase objects which inherit from MolalityVPSSTP
setState_TP() Set the temperature, and then the pressure of the phase. The mole fractions are assumed fixed.
setState_PX() Set the mole fractions and then the pressure of the phase. The temperature is assumed fixed.
setState_PY() Set the mass fractions and then the pressure of the phase. The temperature is assumed fixed.
setState_HP() Set the total specific enthalpy and the pressure of the phase using an iterative process. The mole fractions are assumed fixed
setState_UV() Set the total specific internal energy and the pressure of the phase using an iterative process. The mole fractions are assumed fixed.
setState_SP() Set the total specific internal energy and the pressure of the phase using an iterative process. The mole fractions are assumed fixed.
setState_SV() Set the total specific entropy and the total specific molar volume of the phase using an iterative process. The mole fractions are assumed fixed.
setConcentrations() Set the concentrations of all the species in the phase. Note this implicitly specifies the pressure and density of the phase. The temperature is assumed fixed.
setDensity() Set the total density of the phase. The temperature and mole fractions are assumed fixed. Note this implicitly sets the pressure of the phase.
setTemperature() Set the temperature of the phase. The density and the mole fractions of the phase are fixed.
setToEquilState() Sets the mole fractions of the phase to their equilibrium values assuming fixed temperature and total density.

Some of the functions, like setState_TPX() have multiple forms depending upon the format for how the species compositions are set.

Molar Basis vs. Molality Basis

Mechanical properties

The ThermoPhase object specifies the mechanical equation of state of the phase. Functions which are defined at the ThermoPhase level to give the user more information about the mechanical properties are:

 - ThermoPhase::pressure()
 - ThermoPhase::isothermalCompressibility()
 - ThermoPhase::thermalExpansionCoeff()

Treatment of the Phase Potential and the electrochemical potential of a species

The electrochemical potential of species k in a phase p, \( \zeta_k \), is related to the chemical potential via the following equation,

      \zeta_{k}(T,P) = \mu_{k}(T,P) + z_k \phi_p

where \( \nu_k \) is the charge of species k, and \( \phi_p \) is the electric potential of phase p.

The potential \( \phi_p \) is tracked and internally stored within the base ThermoPhase object. It constitutes a specification of the internal state of the phase; it's the third state variable, the first two being temperature and density (or, pressure, for incompressible equations of state). It may be set with the function, ThermoPhase::setElectricPotential(), and may be queried with the function ThermoPhase::electricPotential().

Note, the overall electrochemical potential of a phase may not be changed by the potential because many phases enforce charge neutrality:

      0 = \sum_k z_k X_k

Whether charge neutrality is necessary for a phase is also specified within the ThermoPhase object, by the function call ThermoPhase::chargeNeutralityNecessary(). Note, that it is not necessary for the IdealGas phase, currently. However, it is necessary for liquid phases such as Cantera::DebyeHuckel and Cantera::HMWSoln for the proper specification of the chemical potentials.

This equation, when applied to the \( \zeta_k \) equation described above, results in a zero net change in the effective Gibbs free energy of the phase. However, specific charged species in the phase may increase or decrease their electrochemical potentials, which will have an effect on interfacial reactions involving charged species, when there is a potential drop between phases. This effect is used within the Cantera::InterfaceKinetics and Cantera::EdgeKinetics kinetics objects classes.

Other internal state variables, that track the treatment of other potential energy contributions, by adding contributions to the chemical potential to create an effective chemical potential, may be added at a later time.

Specification of Activities and Activity Conventions

The activity \(a_k\) and activity coefficient \( \gamma_k \) of a species in solution is related to the chemical potential by

\[ \mu_k = \mu_k^0(T,P) + \hat R T \log a_k.= \mu_k^0(T,P) + \hat R T \log x_k \gamma_k \]

The quantity \(\mu_k^0(T,P)\) is the standard chemical potential at unit activity, which depends on the temperature and pressure, but not on the composition. The activity is dimensionless. Within liquid electrolytes it's common to use a molality convention, where solute species employ the molality-based activity coefficients:

\[ \mu_k = \mu_k^\triangle(T,P) + R T ln(a_k^{\triangle}) = \mu_k^\triangle(T,P) + R T ln(\gamma_k^{\triangle} \frac{m_k}{m^\triangle}) \]

And, the solvent employs the following convention

\[ \mu_o = \mu^o_o(T,P) + RT ln(a_o) \]

where \( a_o \) is often redefined in terms of the osmotic coefficient \( \phi \).

\[ \phi = \frac{- ln(a_o)}{\tilde{M}_o \sum_{i \ne o} m_i} \]

ThermoPhase classes which employ the molality based convention are all derived from the MolalityVPSSTP class. See the class description for further information on its capabilities.

The activity convention used by a ThermoPhase object may be queried via the ThermoPhase::activityConvention() function. A zero means molar based, while a one means molality based.

The function ThermoPhase::getActivities() returns a vector of activities. Whether these are molar-based or molality-based depends on the value of activityConvention().

The function getActivityCoefficients() always returns molar-based activity coefficients regardless of the activity convention used. The function MolalityVPSSTP::getMolalityActivityCoefficients() returns molality based activity coefficients for those ThermoPhase objects derived from the MolalityVPSSTP class. The function MolalityVPSSTP::osmoticCoefficient() returns the osmotic coefficient.

Activity Concentrations: Relationship of ThermoPhase to Kinetics Expressions

Cantera can handle both thermodynamics and kinetics mechanisms. Reversible kinetics mechanisms within Cantera must be compatible with thermodynamics in the sense that at equilibrium, or at infinite times, the concentrations of species must conform to thermodynamics. This means that for every valid reversible kinetics reaction in a mechanism, it must be reducible to an expression involving the ratio of the product activity to the reactant activities being equal to the exponential of the dimensionless standard state gibbs free energies of reaction. Irreversible kinetics reactions do not have this requirement; however, their usage can yield unexpected and inconsistent results in many situations. The actual units used in a kinetics expression depend on the context or the relative field of study. For example, in gas phase kinetics, species in kinetics expressions are expressed in terms of concentrations, for example, gmol cm-3. In solid phase studies, however, kinetics is usually expressed in terms of unitless activities, which most often equate to solid phase mole fractions. In order to accommodate variability here, Cantera has come up with the idea of activity concentrations, \( C^a_k \). Activity concentrations are the expressions used directly in kinetics expressions. These activity (or generalized) concentrations are used by kinetics manager classes to compute the forward and reverse rates of elementary reactions. Note that they may or may not have units of concentration — they might be partial pressures, mole fractions, or surface coverages, The activity concentrations for species k, \( C^a_k \), are related to the activity for species, k, \( a_k \), via the following expression:

\[ a_k = C^a_k / C^0_k \]

\( C^0_k \) are called standard concentrations. They serve as multiplicative factors between the activities and the generalized concentrations. Standard concentrations may be different for each species. They may depend on both the temperature and the pressure. However, they may not depend on the composition of the phase. For example, for the IdealGasPhase object the standard concentration is defined as

\[ C^0_k = P/ R T \]

In many solid phase kinetics problems,

\[ C^0_k = 1.0 , \]

is employed making the units for activity concentrations in solids unitless.

ThermoPhase member functions dealing with this concept include ThermoPhase::getActivityConcentrations() , which provides a vector of the current activity concentrations. The function, ThermoPhase::standardConcentration(int k=0) returns the standard concentration of the kth species. The function, ThermoPhase::logStandardConc(int k=0), returns the natural log of the kth standard concentration. The function ThermoPhase::getUnitsStandardConc() returns a vector of doubles, specifying the MKS units of the standard concentration of the kth species.

Initialization of ThermoPhase Objects within Cantera

Instantiation of ThermoPhase properties occurs by reading and processing the XML data contained within an ctxml data file. First a call to newPhase(std::string file, std::string id) or newPhase(XML_Node &phase) is made. The arguments serve to specify the XML data structure containing the phase information.

Within newPhase() a determination of what type of ThermoPhase object should be used is made. This is done within the routine ThermoFactory::newThermoPhase(std::string model) or related routines. Once the correct ThermoPhase derived object is selected and instantiated with a bare constructor, the function Cantera::importPhase() is called with the ThermoPhase derived object as one of its arguments.

Within importPhase(), a decision is made as to what type of standard state, that is, either a reference state (just T dependent) or a standard state (both P and T dependent), is to be used to calculate the standard state properties of the species within the phase. If only a reference state is needed then a call to newSpeciesThermoMgr() is made in order pick a manager, that is, a derivative of the SpeciesThermo object, to use.

Once these determinations are made, the ThermoPhase object is ready to start reading in the species information, which includes all of the available standard state information about the species. this is done within the routine installSpecies().

Within installSpecies(), most of the common steps for adding a species are carried out. The element stoichiometry is read and elements are added as needed to the list of elements kept with the ThermoPhase object. The charge of the species is read in. The species is added into the list of species kept within the ThermoPhase object. Lastly, the standard state thermodynamics for the species is read in. For reference states, the routine, SpeciesThermoFactory::installThermoForSpecies(), is used to read in the data. Essentially, this routine is a factory routine for picking the correct subroutine to call to read the XML data from the input file and install the correct SpeciesThermoInterpType object into the SpeciesThermo object.

Within installSpecies(), for standard states, derived PDSS object is created and installed into the VPStandardStateTP list containing all of the PDSS objects for that phase.

Now that all of the species standard states are read in and installed into the ThermoPhase object, control once again is returned to the importPhase() function. Two derived functions are then called. The first one, ThermoPhase::initThermo(), is called. In this routine, all internal arrays within the ThermoPhase object are dimensioned according to the number of elements and species. Then, the function ThermoPhase::initThermoXML() is called. This function is tasked with reading in all of the thermodynamic function information specific to the calculation of the phase information. This includes all of the information about the activity coefficient calculation.

After the ThermoPhase::initThermoXML() is finished, the ThermoPhase routine is ready to receive requests for thermodynamic property information.

There is an alternative way to instantiate ThermoPhase objects that is applicable to a significant proportion of ThermoPhase classes. The phase may be instantiated via a constructor that invokes the XML data structure wherein the phase information is to be read directly. In this case, the call to newPhase() and the call to ThermoFactory::newThermoPhase(std::string model) is not made. However, soon after that, the call to importPhase() is made and thereafter instantiation follows the initialization course described previously in order to avoid as much duplicate code as possible. This alternative way to instantiate ThermoPhase objects has the advantage of working well with hard-coded situations. And, it works well also with situations where new ThermoPhase classes are being developed and haven't yet made their way into the factory routines.

Adding Additional Thermodynamics Models

In general, factory routines throw specific errors when encountering unknown thermodynamics models in XML files. All of the error classes derive from the class, CanteraError.

Many of the important member functions in factory routines are virtual classes. This means that a user may write their own factory classes which inherit from the base Cantera factory classes to provide additional ThermoPhase classes.

See also
newPhase(std::string file, std::string id) Description for how to read ThermoPhases from XML files.
newPhase(XML_Node &phase) How to call the Factory routine to create and initialize ThermoPhase objects.

Standard ThermoPhase objects may be instantiated by calling the main Cantera factory class for ThermoPhase objects; This class is called ThermoFactory.

Function Documentation

◆ importPhase()

void importPhase ( XML_Node phase,
ThermoPhase th 

Import a phase information into an empty ThermoPhase object.

Here we read an XML description of the thermodynamic information for a phase. At the end of this routine, the phase should be ready to be used within applications. This routine contains some key routines that are used as pass back routines so that the phase (and the contents of the XML file) may contain variable parameterizations for the specification of the species standard states, the equation of state, and the specification of other nonidealities. Below, a description is presented of the main algorithm for bringing up a ThermoPhase object, with care to present points where customizations occur.

Before invoking this routine, either the ThermoPhase Factory routines are called or direct constructor routines are called that instantiate an inherited ThermoPhase object. This object is input to this routine, and therefore contains inherited routines that drive the customization of the initialization process.

At the start of the routine, we import descriptions of the elements that make up the species in a phase.

We call setParametersFromXML(eos) to read parameters about the thermo phase before the species are read in.

We call addElementsFromXML() to add elements into the description of the phase.

We create a new species thermo manager. Function 'newSpeciesThermoMgr' looks at the species in the database to see what thermodynamic property parameterizations are used, and selects a class that can handle the parameterizations found.

We import information about the species, including their reference state thermodynamic polynomials. We then freeze the state of the species in the element.

Finally, we call initThermoXML(), a member function of the ThermoPhase object, to "finish" the description. Now that the species are known, additional information may be read in about the thermodynamics of the phase, (for example, virial coefficients, which are binary or ternary interaction parameters between species).

phaseThis object must be the phase node of a complete XML tree description of the phase, including all of the species data. In other words while "phase" must point to an XML phase object, it must have sibling nodes "speciesData" that describe the species in the phase.
thPointer to the ThermoPhase object which will handle the thermodynamics for this phase. We initialize part of the ThermoPhase object here, especially for those objects which are part of the Cantera Kernel.
The XML input format is deprecated and will be removed in Cantera 3.0.

Definition at line 250 of file ThermoFactory.cpp.

References ThermoPhase::addSpecies(), AssertTrace, XML_Node::attrib(), XML_Node::child(), Cantera::cSS_CONVENTION_SLAVE, Cantera::cSS_CONVENTION_VPSS, XML_Node::findByName(), Cantera::formSpeciesXMLNodeList(), Cantera::get_XML_Node(), XML_Node::getChildren(), XML_Node::hasAttrib(), XML_Node::hasChild(), XML_Node::id(), Phase::ignoreUndefinedElements(), ThermoPhase::initThermo(), ThermoPhase::initThermoXML(), Cantera::installElements(), VPStandardStateTP::installPDSS(), Cantera::intValue(), XML_Node::name(), Phase::name(), Cantera::newSpecies(), XML_Node::root(), ThermoPhase::saveSpeciesData(), Phase::setName(), Phase::setNDim(), ThermoPhase::setParametersFromXML(), Phase::setXMLdata(), ThermoPhase::standardStateConvention(), and Phase::throwUndefinedElements().

Referenced by BinarySolutionTabulatedThermo::BinarySolutionTabulatedThermo(), Cantera::buildSolutionFromXML(), IdealGasPhase::IdealGasPhase(), IdealMolalSoln::IdealMolalSoln(), IdealSolidSolnPhase::IdealSolidSolnPhase(), ThermoPhase::initThermoFile(), IonsFromNeutralVPSSTP::IonsFromNeutralVPSSTP(), LatticePhase::LatticePhase(), MargulesVPSSTP::MargulesVPSSTP(), Cantera::newPhase(), RedlichKisterVPSSTP::RedlichKisterVPSSTP(), RedlichKwongMFTP::RedlichKwongMFTP(), StoichSubstance::StoichSubstance(), SurfPhase::SurfPhase(), and WaterSSTP::WaterSSTP().