/** * @defgroup thermoprops Thermodynamic Properties * * * 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 (i.e., enthalpy_mole()), on a per kg of * solution basis, and on a * partial molar basis for each species (i.e., * 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, \f$p_0\f$. 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 \f$ N - 1 \f$ 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. * * - IdealGasPhase in IdealGasPhase.h * - StoichSubstance in StoichSubstance.h * - SurfPhase in SurfPhase.h * - EdgePhase in EdgePhase.h * - LatticePhase in LatticePhase.h * - LatticeSolidPhase in LatticeSolidPhase.h * - ConstDensityThermo in ConstDensityThermo.h * - PureFluidPhase in PureFluidPhase.h * - IdealSolidSolnPhase in IdealSolidSolnPhase.h * - VPStandardStateTP in VPStandardStateTP.h * * 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 * * - IdealSolnGasVPSS in IdealSolnGasVPSS.h * - MolalityVPSSTP in MolalityVPSSTP.h * * 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: * * - DebyeHuckel in DebyeHuckel.h * - IdealMolalSoln in IdealMolalSoln.h * - HMWSoln in HMWSoln.h * * 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. * * - StoichSubstance in StoichSubstance.h * - WaterSSTP in WaterSSTP.h * * 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: * * - Set the temperature * - Set the mole or mass fractions or set the molalities * - set the pressure. * * For classes which inherit from VPStandardStateTP, the above order may * be used, or the following order may be used. It's not important. * * - Set the temperature * - Set the pressure * - Set the mole or mass fractions or set the molalities * * The following functions are used to set the state: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
\link Cantera::ThermoPhase::setState_TPX() setState_TPX()\endlink Sets the temperature, mole fractions and then the pressure * of the phase.
\link Cantera::ThermoPhase::setState_TPY() setState_TPY()\endlink Set the temperature, mass fractions and then the pressure * of the phase.
\link Cantera::MolalityVPSSTP::setState_TPM() setState_TPM()\endlink Set the temperature, solute molalities, and then the * pressure of the phase. Only from %ThermoPhase objects which * inherit from MolalityVPSSTP *
\link Cantera::ThermoPhase::setState_TP() setState_TP()\endlink Set the temperature, and then the pressure * of the phase. The mole fractions are assumed fixed. *
\link Cantera::ThermoPhase::setState_PX() setState_PX()\endlink Set the mole fractions and then the pressure * of the phase. The temperature is assumed fixed. *
\link Cantera::ThermoPhase::setState_PY() setState_PY()\endlink Set the mass fractions and then the pressure * of the phase. The temperature is assumed fixed. *
\link Cantera::ThermoPhase::setState_HP() setState_HP()\endlink Set the total specific enthalpy and the pressure * of the phase using an iterative process. * The mole fractions are assumed fixed *
\link Cantera::ThermoPhase::setState_UV() setState_UV()\endlink Set the total specific internal energy and the pressure * of the phase using an iterative process. * The mole fractions are assumed fixed. *
\link Cantera::ThermoPhase::setState_SP setState_SP()\endlink Set the total specific internal energy and the pressure * of the phase using an iterative process. * The mole fractions are assumed fixed. *
\link Cantera::ThermoPhase::setState_SV setState_SV()\endlink Set the total specific entropy and the total specific * molar volume of the phase using an iterative process. * The mole fractions are assumed fixed. *
\link Cantera::Phase::setConcentrations setConcentrations()\endlink 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. *
\link Cantera::Phase::setDensity setDensity()\endlink Set the total density of the phase. The temperature and * mole fractions are assumed fixed. Note this implicitly * sets the pressure of the phase. *
\link Cantera::Phase::setTemperature() setTemperature()\endlink Set the temperature of the phase. The density and * the mole fractions of the phase are fixed. *
\link Cantera::ThermoPhase::setToEquilState() setToEquilState()\endlink 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, \f$ \zeta_k \f$, * is related to the chemical potential via * the following equation, * * \f[ * \zeta_{k}(T,P) = \mu_{k}(T,P) + z_k \phi_p * \f] * * where \f$ \nu_k \f$ is the charge of species k, and \f$ \phi_p \f$ is * the electric potential of phase p. * * The potential \f$ \phi_p \f$ 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: * * \f[ * 0 = \sum_k z_k X_k * \f] * * 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 \f$ \zeta_k \f$ 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 \f$a_k\f$ and activity coefficient \f$ \gamma_k \f$ of a * species in solution is related to the chemical potential by * * \f[ * \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 * \f] * * The quantity \f$\mu_k^0(T,P)\f$ 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: * * \f[ * \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}) * \f] * * And, the solvent employs the following convention * \f[ * \mu_o = \mu^o_o(T,P) + RT ln(a_o) * \f] * * where \f$ a_o \f$ is often redefined in terms of the osmotic coefficient \f$ \phi \f$. * * \f[ * \phi = \frac{- ln(a_o)}{\tilde{M}_o \sum_{i \ne o} m_i} * \f] * * %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, i.e., 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, \f$ C^a_k \f$. 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, \f$ C^a_k \f$, are * related to the activity for species, k, \f$ a_k \f$, * via the following expression: * * \f[ * a_k = C^a_k / C^0_k * \f] * * \f$ C^0_k \f$ 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 * * \f[ * C^0_k = P/ R T * \f] * * In many solid phase kinetics problems, * * \f[ * C^0_k = 1.0 , * \f] * * 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, i.e., * 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, i.e., 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 newPhase(std::string file, std::string id) Description for how to * read ThermoPhases from XML files. * @see newPhase(XML_Node &phase) How to call the Factory routine to create * and initialize %ThermoPhase objects. * @ingroup phases */