DebyeHuckel.h

Go to the documentation of this file.
00001 /**
00002  *  @file DebyeHuckel.h
00003  *    Headers for the %DebyeHuckel ThermoPhase object, which models dilute
00004  *    electrolyte solutions
00005  *    (see \ref thermoprops and \link Cantera::DebyeHuckel DebyeHuckel \endlink) .
00006  *
00007  * Class %DebyeHuckel represents a dilute liquid electrolyte phase which
00008  * obeys the Debye Huckel formulation for nonideality.
00009  */
00010 
00011 /*
00012  * Copywrite (2006) Sandia Corporation. Under the terms of 
00013  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
00014  * U.S. Government retains certain rights in this software.
00015  */
00016 
00017 /*
00018  * $Id: DebyeHuckel.h 279 2009-12-05 19:08:43Z hkmoffa $
00019  */
00020 
00021 #ifndef CT_DEBYEHUCKEL_H
00022 #define CT_DEBYEHUCKEL_H
00023 
00024 #include "MolalityVPSSTP.h"
00025 #include "electrolytes.h"
00026 #include "Array.h"
00027 
00028 namespace Cantera {
00029 
00030   /*!
00031    * @name Formats for the Activity Coefficients 
00032    *    
00033    *   These are possible formats for the molality-based activity coefficients.
00034    */
00035   //@{
00036 #define DHFORM_DILUTE_LIMIT  0
00037 #define DHFORM_BDOT_AK       1
00038 #define DHFORM_BDOT_ACOMMON  2
00039 #define DHFORM_BETAIJ        3
00040 #define DHFORM_PITZER_BETAIJ 4
00041   //@}
00042   /*
00043    *  @name  Acceptable ways to calculate the value of A_Debye
00044    */
00045   //@{
00046 #define    A_DEBYE_CONST  0
00047 #define    A_DEBYE_WATER  1
00048   //@}
00049 
00050   class WaterProps;
00051   class PDSS_Water;
00052 
00053   /**
00054    * @ingroup thermoprops
00055    *
00056    * Class %DebyeHuckel represents a dilute liquid electrolyte phase which
00057    * obeys the Debye Huckel formulation for nonideality.
00058    *
00059    * The concentrations of the ionic species are assumed to obey the electroneutrality
00060    * condition. 
00061    *
00062    * <HR>
00063    * <H2> Specification of Species Standard %State Properties </H2>
00064    * <HR>
00065    *
00066    * The standard states are on the unit molality basis. Therefore, in the
00067    * documentation below, the normal \f$ o \f$ superscript is replaced with
00068    * the \f$ \triangle \f$ symbol. The reference state symbol is now
00069    *  \f$ \triangle, ref \f$.
00070    * 
00071    *  
00072    *  It is assumed that the reference state thermodynamics may be
00073    *  obtained by a pointer to a populated species thermodynamic property
00074    *  manager class (see ThermoPhase::m_spthermo). How to relate pressure
00075    *  changes to the reference state thermodynamics is resolved at this level.
00076    *
00077    *  For an incompressible,
00078    * stoichiometric substance, the molar internal energy is
00079    * independent of pressure. Since the thermodynamic properties
00080    * are specified by giving the standard-state enthalpy, the
00081    * term \f$ P_0 \hat v\f$ is subtracted from the specified molar
00082    * enthalpy to compute the molar internal energy. The entropy is
00083    * assumed to be independent of the pressure.
00084    *
00085    * The enthalpy function is given by the following relation.
00086    *
00087    *       \f[
00088    *   \raggedright  h^\triangle_k(T,P) = h^{\triangle,ref}_k(T) 
00089    *         + \tilde v \left( P - P_{ref} \right) 
00090    *       \f]
00091    *
00092    * For an incompressible,
00093    * stoichiometric substance, the molar internal energy is
00094    * independent of pressure. Since the thermodynamic properties
00095    * are specified by giving the standard-state enthalpy, the
00096    * term \f$ P_{ref} \tilde v\f$ is subtracted from the specified reference molar
00097    * enthalpy to compute the molar internal energy.
00098    *
00099    *       \f[
00100    *            u^\triangle_k(T,P) = h^{\triangle,ref}_k(T) - P_{ref} \tilde v
00101    *       \f]
00102    *
00103    * The standard state heat capacity and entropy are independent
00104    * of pressure. The standard state gibbs free energy is obtained
00105    * from the enthalpy and entropy functions.
00106    *
00107    * The vector Constituents::m_speciesSize[] is used to hold the
00108    * base values of species sizes. These are defined as the 
00109    * molar volumes of species at infinite dilution at 300 K and 1 atm
00110    * of water. m_speciesSize are calculated during the initialization of the
00111    * %DebyeHuckel object and are then not touched.
00112    *
00113    * The current model assumes that an incompressible molar volume for
00114    * all solutes. The molar volume for the water solvent, however,
00115    * is obtained from a pure water equation of state, waterSS.
00116    * Therefore, the water standard state varies with both T and P.
00117    * It is an error to request standard state water properties  at a T and P
00118    * where the water phase is not a stable phase, i.e., beyond its
00119    * spinodal curve.
00120    *   
00121    * <HR>
00122    * <H2> Specification of Solution Thermodynamic Properties </H2>
00123    * <HR>
00124    *
00125    * Chemical potentials
00126    * of the solutes,  \f$ \mu_k \f$, and the solvent, \f$ \mu_o \f$, which are based 
00127    * on the molality form, have the following general format:
00128    *
00129    * \f[
00130    *    \mu_k = \mu^{\triangle}_k(T,P) + R T ln(\gamma_k^{\triangle} \frac{m_k}{m^\triangle}) 
00131    * \f]
00132    * \f[
00133    *    \mu_o = \mu^o_o(T,P) + RT ln(a_o) 
00134    * \f]
00135    *
00136    * where \f$ \gamma_k^{\triangle} \f$ is the molality based activity coefficient for species
00137    * \f$k\f$.
00138    * 
00139    * Individual activity coefficients of ions can not be independently measured. Instead,
00140    * only binary pairs forming electroneutral solutions can be measured.
00141  
00142    *
00143    *  <H3> Ionic Strength </H3>
00144    *
00145    *  Most of the parameterizations within the model use the ionic strength 
00146    *  as a key variable. The ionic strength, \f$ I\f$ is defined as follows
00147    *
00148    *  \f[
00149    *    I = \frac{1}{2} \sum_k{m_k  z_k^2}
00150    *  \f]
00151    *
00152    * \f$ m_k \f$ is the molality of the kth species. \f$ z_k \f$ is the charge
00153    * of the kth species. Note, the ionic strength is a defined units quantity.
00154    * The molality has defined units of gmol kg-1, and therefore the ionic
00155    * strength has units of sqrt( gmol kg-1).
00156    *
00157    * In some instances, from some authors, a different 
00158    * formulation is used for the ionic strength in the equations below. The different
00159    * formulation is due to the possibility of the existence of weak acids and how
00160    * association wrt to the weak acid equilibrium relation affects the calculation 
00161    * of the activity coefficients via the assumed value of the ionic strength.
00162    *
00163    * If we are to assume that the association reaction doesn't have an effect
00164    * on the ionic strength, then we will want to consider the associated weak
00165    * acid as in effect being fully dissociated, when we calculate an effective
00166    * value for the ionic strength. We will call this calculated value, the
00167    * stoichiometric ionic strength, \f$ I_s \f$, putting a subscript s to denote
00168    * it from the more straightforward calculation of \f$ I \f$.
00169    *
00170    *  \f[
00171    *    I_s = \frac{1}{2} \sum_k{m_k^s  z_k^2}
00172    *  \f]
00173    *
00174    *  Here, \f$ m_k^s \f$ is the value of the molalities calculated assuming that
00175    *  all weak acid-base pairs are in their fully dissociated states. This calculation may
00176    * be simplified by considering that the weakly associated acid may be made up of two
00177    * charged species, k1 and k2, each with their own charges, obeying the following relationship:
00178    *
00179    *   \f[
00180    *      z_k = z_{k1} +  z_{k2}
00181    *   \f]
00182    *  Then, we may only need to specify one charge value, say, \f$  z_{k1}\f$, 
00183    *  the cation charge number,
00184    *  in order to get both numbers, since we have already specified \f$ z_k \f$ 
00185    *  in the definition of original species.
00186    *  Then, the stoichiometric ionic strength may be calculated via the following formula.
00187    *
00188    *  \f[
00189    *    I_s = \frac{1}{2} \left(\sum_{k,ions}{m_k  z_k^2}+ 
00190    *               \sum_{k,weak_assoc}(m_k  z_{k1}^2 + m_k  z_{k2}^2) \right)
00191    *  \f]
00192    *
00193    *  The specification of which species are weakly associated acids is made in the input 
00194    *  file via the
00195    *  <TT> stoichIsMods </TT> XML block, where the charge for k1 is also specified. 
00196    *  An example is given below:
00197    * 
00198    * @code
00199    *          <stoichIsMods>
00200    *                NaCl(aq):-1.0
00201    *          </stoichIsMods>
00202    * @endcode
00203    *
00204    *  Because we need the concept of a weakly associated acid in order to calculated 
00205    *  \f$ I_s \f$ we need to 
00206    *  catalog all species in the phase. This is done using the following categories:
00207    *
00208    *  -  <B>cEST_solvent</B>    :           Solvent species (neutral)
00209    *  -  <B>cEST_chargedSpecies</B>         Charged species (charged)
00210    *  -  <B>cEST_weakAcidAssociated</B>     Species which can break apart into charged species.
00211    *                                        It may or may not be charged.  These may or 
00212    *                                        may not be be included in the
00213    *                                        species solution vector.
00214    *  -  <B>cEST_strongAcidAssociated</B>   Species which always breaksapart into charged species.
00215    *                                        It may or may not be charged. Normally, these aren't included
00216    *                                        in the speciation vector.
00217    *  -  <B>cEST_polarNeutral </B>          Polar neutral species
00218    *  -  <B>cEST_nonpolarNeutral</B>        Non poloar neutral species
00219    *
00220    *  Polar and non-polar neutral species are differentiated, because some additions 
00221    *  to the activity 
00222    *  coefficient expressions distinguish between these two types of solutes. This is the so-called
00223    *  salt-out effect.
00224    *
00225    * The type of species is specified in the <TT>electrolyteSpeciesType</TT> XML block.
00226    * Note, this is not
00227    * considered a part of the specification of the standard state for the species, 
00228    * at this time. Therefore,
00229    * this information is put under the <TT>activityCoefficient</TT> XML block. An example 
00230    * is given below
00231    *
00232    * @code
00233    *         <electrolyteSpeciesType>
00234    *                H2L(L):solvent
00235    *                H+:chargedSpecies
00236    *                NaOH(aq):weakAcidAssociated
00237    *                NaCl(aq):strongAcidAssociated
00238    *                NH3(aq):polarNeutral
00239    *                O2(aq):nonpolarNeutral
00240    *         </electrolyteSpeciesType>
00241    * @endcode
00242    *
00243    *  Much of the species electrolyte type information is infered from other information in the
00244    *  input file. For example, as species which is charged is given the "chargedSpecies" default
00245    *  category. A neutral solute species is put into the "nonpolarNeutral" category by default.
00246    *
00247    * The specification of solute activity coefficients depends on the model
00248    * assumed for the Debye-Huckel term. The model is set by the
00249    * internal parameter #m_formDH. We will now describe each category in its own section.
00250    *
00251    *
00252    *  <H3> Debye-Huckel Dilute Limit </H3>
00253    *
00254    *  DHFORM_DILUTE_LIMIT = 0
00255    *
00256    *      This form assumes a dilute limit to DH, and is mainly
00257    *      for informational purposes:
00258    *  \f[
00259    *      \ln(\gamma_k^\triangle) = - z_k^2 A_{Debye} \sqrt{I}
00260    *  \f]
00261    *              where \f$ I\f$ is the ionic strength
00262    *  \f[
00263    *    I = \frac{1}{2} \sum_k{m_k  z_k^2}
00264    *  \f]
00265    *
00266    *  The activity for the solvent water,\f$ a_o \f$, is not independent and must be 
00267    *  determined from the Gibbs-Duhem relation.
00268    *
00269    *  \f[
00270    *       \ln(a_o) = \frac{X_o - 1.0}{X_o} + \frac{ 2 A_{Debye} \tilde{M}_o}{3} (I)^{3/2}
00271    *  \f]
00272    *     
00273    *
00274    *  <H3> Bdot Formulation </H3>
00275    *
00276    *    DHFORM_BDOT_AK       = 1
00277    *
00278    *      This form assumes Bethke's format for the Debye Huckel activity coefficient:
00279    *
00280    *   \f[
00281    *      \ln(\gamma_k^\triangle) = -z_k^2 \frac{A_{Debye} \sqrt{I}}{ 1 + B_{Debye}  a_k \sqrt{I}}
00282    *                        + \log(10) B^{dot}_k  I
00283    *   \f]
00284    *
00285    *      Note, this particular form where \f$ a_k \f$ can differ in 
00286    *          multielectrolyte
00287    *          solutions has problems with respect to a Gibbs-Duhem analysis. However,
00288    *          we include it here because there is a lot of data fit to it.
00289    *
00290    *  The activity for the solvent water,\f$ a_o \f$, is not independent and must be 
00291    *  determined from the Gibbs-Duhem relation. Here, we use:
00292    *
00293    *  \f[
00294    *       \ln(a_o) = \frac{X_o - 1.0}{X_o} 
00295    *        + \frac{ 2 A_{Debye} \tilde{M}_o}{3} (I)^{1/2}
00296    *                        \left[ \sum_k{\frac{1}{2} m_k z_k^2 \sigma( B_{Debye} a_k \sqrt{I} ) } \right]
00297    *                        - \frac{\log(10)}{2} \tilde{M}_o I \sum_k{ B^{dot}_k m_k}
00298    *  \f]
00299    *    where
00300    *  \f[
00301    *     \sigma (y) = \frac{3}{y^3} \left[ (1+y) - 2 \ln(1 + y) - \frac{1}{1+y} \right]
00302    *  \f]
00303    *
00304    * Additionally, Helgeson's formulation for the water activity is offered as an
00305    * alternative.
00306    *
00307    *
00308    *  <H3> Bdot Formulation with Uniform Size Parameter in the Denominator </H3>
00309    *
00310    *  DHFORM_BDOT_AUNIFORM = 2
00311    *
00312    *      This form assumes Bethke's format for the Debye-Huckel activity coefficient
00313    *
00314    *   \f[
00315    *    \ln(\gamma_k^\triangle) = -z_k^2 \frac{A_{Debye} \sqrt{I}}{ 1 + B_{Debye}  a \sqrt{I}}
00316    *                        + \log(10) B^{dot}_k  I
00317    *   \f]
00318    *      
00319    *         The value of a is determined at the beginning of the 
00320    *         calculation, and not changed.
00321    *
00322    *  \f[
00323    *       \ln(a_o) = \frac{X_o - 1.0}{X_o} 
00324    *        + \frac{ 2 A_{Debye} \tilde{M}_o}{3} (I)^{3/2} \sigma( B_{Debye} a \sqrt{I} )
00325    *                        - \frac{\log(10)}{2} \tilde{M}_o I \sum_k{ B^{dot}_k m_k}
00326    *  \f]
00327    *
00328    *
00329    *  <H3> Beta_IJ formulation </H3>
00330    *
00331    *  DHFORM_BETAIJ        = 3
00332    * 
00333    *      This form assumes a linear expansion in a virial coefficient form
00334    *      It is used extensively in the book by Newmann, "Electrochemistry Systems", 
00335    *      and is the beginning of
00336    *      more complex treatments for stronger electrolytes, fom Pitzer
00337    *      and from Harvey, Moller, and Weire.
00338    *  
00339    *   \f[
00340    *    \ln(\gamma_k^\triangle) = -z_k^2 \frac{A_{Debye} \sqrt{I}}{ 1 + B_{Debye}  a \sqrt{I}}
00341    *                         + 2 \sum_j \beta_{j,k} m_j
00342    *   \f]
00343    *
00344    *   In the current treatment the binary interaction coefficients, \f$ \beta_{j,k}\f$, are 
00345    *   independent of temperature and pressure.
00346    *
00347    *  \f[
00348    *       \ln(a_o) = \frac{X_o - 1.0}{X_o} 
00349    *        + \frac{ 2 A_{Debye} \tilde{M}_o}{3} (I)^{3/2} \sigma( B_{Debye} a \sqrt{I} )
00350    *        -  \tilde{M}_o  \sum_j \sum_k \beta_{j,k} m_j m_k
00351    *  \f]
00352    *
00353    * In this formulation the ionic radius, \f$ a \f$, is a constant. This must be supplied to the
00354    * model, in an <DFN> ionicRadius </DFN> XML block.
00355    *
00356    * The \f$ \beta_{j,k} \f$ parameters are binary interaction parameters. They are supplied to
00357    * the object in an <TT> DHBetaMatrix </TT> XML block. There are in principle \f$ N (N-1) /2 \f$
00358    * different, symmetric interaction parameters, where \f$ N \f$ are the number of solute species in the
00359    * mechanism.  
00360    * An example is given below.
00361    *
00362    * An example <TT> activityCoefficients </TT> XML block for this formulation is supplied below
00363    *
00364    * @code
00365    *  <activityCoefficients model="Beta_ij">
00366    *         <!-- A_Debye units = sqrt(kg/gmol) -->
00367    *         <A_Debye> 1.172576 </A_Debye>
00368    *         <!-- B_Debye units = sqrt(kg/gmol)/m   -->
00369    *         <B_Debye> 3.28640E9 </B_Debye>
00370    *         <ionicRadius default="3.042843"  units="Angstroms">
00371    *         </ionicRadius>
00372    *         <DHBetaMatrix>
00373    *               H+:Cl-:0.27
00374    *               Na+:Cl-:0.15
00375    *               Na+:OH-:0.06
00376    *         </DHBetaMatrix>
00377    *         <stoichIsMods>
00378    *                NaCl(aq):-1.0
00379    *         </stoichIsMods>
00380    *         <electrolyteSpeciesType>
00381    *                H+:chargedSpecies
00382    *                NaCl(aq):weakAcidAssociated
00383    *         </electrolyteSpeciesType>
00384    *  </activityCoefficients>
00385    * @endcode
00386    *
00387    *  <H3> Pitzer Beta_IJ formulation </H3>
00388    *
00389    *  DHFORM_PITZER_BETAIJ  = 4
00390    * 
00391    *      This form assumes an activity coefficient formulation consistent
00392    *      with a truncated form of Pitzer's formulation. Pitzer's formulation is equivalent
00393    *      to the formulations above in the dilute limit, where rigorous theory may be applied.
00394    *
00395    *   \f[
00396    *     \ln(\gamma_k^\triangle) = -z_k^2 \frac{A_{Debye}}{3} \frac{\sqrt{I}}{ 1 + B_{Debye}  a \sqrt{I}}
00397    *       -2 z_k^2 \frac{A_{Debye}}{3}  \frac{\ln(1 + B_{Debye}  a  \sqrt{I})}{ B_{Debye}  a}
00398    *                         + 2 \sum_j \beta_{j,k} m_j
00399    *   \f]
00400    *
00401    *
00402    *  \f[
00403    *       \ln(a_o) = \frac{X_o - 1.0}{X_o} 
00404    *        + \frac{ 2 A_{Debye} \tilde{M}_o}{3} \frac{(I)^{3/2} }{1 +  B_{Debye}  a \sqrt{I} }
00405    *        -  \tilde{M}_o  \sum_j \sum_k \beta_{j,k} m_j m_k
00406    *  \f]
00407    *
00408    * <H3> Specification of the Debye Huckel Constants </H3>
00409    *
00410    *  In the equations above, the formulas for  \f$  A_{Debye} \f$ and \f$  B_{Debye} \f$ 
00411    *  are needed. The %DebyeHuckel object uses two methods for specifying these quantities.
00412    *  The default method is to assume that \f$  A_{Debye} \f$  is a constant, given
00413    *  in the initialization process, and storred in the
00414    *  member double, m_A_Debye. Optionally, a full water treatment may be employed that makes
00415    *  \f$ A_{Debye} \f$ a full function of <I>T</I> and <I>P</I>.
00416    *
00417    *   \f[
00418    *      A_{Debye} = \frac{F e B_{Debye}}{8 \pi \epsilon R T} {\left( C_o \tilde{M}_o \right)}^{1/2}
00419    *   \f]
00420    * where
00421    * 
00422    *  \f[
00423    *         B_{Debye} = \frac{F} {{(\frac{\epsilon R T}{2})}^{1/2}} 
00424    *  \f]
00425    *  Therefore:
00426    * \f[
00427    *   A_{Debye} = \frac{1}{8 \pi} 
00428    *                 {\left(\frac{2 N_a \rho_o}{1000}\right)}^{1/2}
00429    *                 {\left(\frac{N_a e^2}{\epsilon R T }\right)}^{3/2}
00430    * \f]
00431    *
00432    *            Units = sqrt(kg/gmol)
00433    *
00434    *     where
00435    *      - \f$ N_a \f$ is Avrogadro's number
00436    *      - \f$ \rho_w \f$ is the density of water
00437    *      - \f$ e \f$ is the electronic charge
00438    *      - \f$ \epsilon = K \epsilon_o \f$ is the permitivity of water
00439    *           where \f$ K \f$ is the dielectric condstant of water,
00440    *           and  \f$ \epsilon_o \f$ is the permitivity of free space.
00441    *      - \f$ \rho_o \f$ is the density of the solvent in its standard state.
00442    *
00443    *            Nominal value at 298 K and 1 atm = 1.172576 (kg/gmol)<SUP>1/2</SUP>
00444    *                  based on:
00445    *                 -   \f$ \epsilon / \epsilon_0 \f$ = 78.54
00446    *                           (water at 25C)
00447    *                 -   \f$ \epsilon_0 \f$= 8.854187817E-12 C<SUP>2</SUP> N<SUP>-1</SUP> m<SUP>-2</SUP>
00448    *                 -   e = 1.60217653E-19 C
00449    *                 -   F = 9.6485309E7 C kmol<SUP>-1</SUP>
00450    *                 -   R = 8.314472E3 kg m<SUP>2</SUP> s<SUP>-2</SUP> kmol<SUP>-1</SUP> K<SUP>-1</SUP>
00451    *                 -   T = 298.15 K
00452    *                 -   B_Debye = 3.28640E9 (kg/gmol)<SUP>1/2</SUP> m<SUP>-1</SUP>
00453    *                 -   \f$N_a\f$ = 6.0221415E26 kmol<SUP>-1</SUP>
00454    *
00455    * An example of a fixed value implementation is given below.
00456    * @code
00457    *   <activityCoefficients model="Beta_ij">
00458    *         <!-- A_Debye units = sqrt(kg/gmol)  -->
00459    *         <A_Debye> 1.172576 </A_Debye>
00460    *         <!-- B_Debye units = sqrt(kg/gmol)/m  -->
00461    *         <B_Debye> 3.28640E9 </B_Debye>
00462    *   </activityCoefficients>
00463    * @endcode
00464    *
00465    * An example of a variable value implementation is given below.
00466    *
00467    * @code
00468    *   <activityCoefficients model="Beta_ij">
00469    *         <A_Debye model="water" /> 
00470    *         <!-- B_Debye units = sqrt(kg/gmol)/m  -->
00471    *         <B_Debye> 3.28640E9 </B_Debye>
00472    *   </activityCoefficients>
00473    * @endcode
00474    *
00475    *  Currently, \f$  B_{Debye} \f$ is a constant in the model, specified either by a default
00476    *  water value, or through the input file. This may have to be looked at, in the future.
00477    *
00478    * <HR>
00479    * <H2> %Application within %Kinetics Managers </H2>
00480    * <HR>
00481    *
00482    * For the time being, we have set the standard concentration for all species in
00483    * this phase equal to the default concentration of the solvent at 298 K and 1 atm. 
00484    * This means that the
00485    * kinetics operator essentially works on an activities basis, with units specified
00486    * as if it were on a concentration basis.
00487    *
00488    * For example, a bulk-phase binary reaction between liquid species j and k, producing
00489    * a new liquid species l would have the
00490    * following equation for its rate of progress variable, \f$ R^1 \f$, which has
00491    * units of kmol m-3 s-1.
00492    *
00493    *   \f[
00494    *    R^1 = k^1 C_j^a C_k^a =  k^1 (C_o a_j) (C_o a_k) 
00495    *   \f]
00496    * where
00497    *   \f[
00498    *      C_j^a = C_o a_j \quad and \quad C_k^a = C_o a_k
00499    *   \f]
00500    *   
00501    *  \f$ C_j^a \f$ is the activity concentration of species j, and 
00502    *  \f$ C_k^a \f$ is the activity concentration of species k. \f$ C_o \f$
00503    *  is the concentration of water at 298 K and 1 atm. \f$ a_j \f$ is
00504    *  the activity of species j at the current temperature and pressure
00505    *  and concentration of the liquid phase. \f$k^1 \f$ has units of m3 kmol-1 s-1.
00506    *
00507    *  The reverse rate constant can then be obtained from the law of microscopic reversibility
00508    * and the equilibrium expression for the system.
00509    *
00510    *   \f[
00511    *         \frac{a_j a_k}{ a_l} = K^{o,1} = \exp(\frac{\mu^o_l - \mu^o_j - \mu^o_k}{R T} )
00512    *   \f]
00513    *
00514    *  \f$  K^{o,1} \f$ is the dimensionless form of the equilibrium constant.
00515    *  
00516    *   \f[
00517    *    R^{-1} = k^{-1} C_l^a =  k^{-1} (C_o a_l)
00518    *   \f]
00519    *
00520    *  where
00521    *
00522    *    \f[
00523    *       k^{-1} =  k^1 K^{o,1} C_o
00524    *   \f]
00525    *
00526    *  \f$k^{-1} \f$ has units of s-1.
00527    * 
00528    *  Note, this treatment may be modified in the future, as events dictate.
00529    *
00530    * <HR>
00531    * <H2> Instantiation of the Class </H2>
00532    * <HR>
00533    *
00534    * The constructor for this phase is NOT located in the default ThermoFactory
00535    * for %Cantera. However, a new %DebyeHuckel object may be created by 
00536    * the following code snippets:
00537    *
00538    * @code
00539    *      DebyeHuckel *DH = new DebyeHuckel("DH_NaCl.xml", "NaCl_electrolyte");
00540    * @endcode
00541    *
00542    * or
00543    *
00544    * @code
00545    *    char iFile[80], file_ID[80];
00546    *    strcpy(iFile, "DH_NaCl.xml");
00547    *    sprintf(file_ID,"%s#NaCl_electrolyte", iFile);
00548    *    XML_Node *xm = get_XML_NameID("phase", file_ID, 0);
00549    *    DebyeHuckel *dh = new DebyeHuckel(*xm);
00550    * @endcode
00551    *
00552    * or by the following call to importPhase():
00553    *
00554    * @code
00555    *    char iFile[80], file_ID[80];
00556    *    strcpy(iFile, "DH_NaCl.xml");
00557    *    sprintf(file_ID,"%s#NaCl_electrolyte", iFile);
00558    *    XML_Node *xm = get_XML_NameID("phase", file_ID, 0);
00559    *    DebyeHuckel dhphase;
00560    *    importPhase(*xm, &dhphase);
00561    * @endcode
00562    *
00563    * <HR>
00564    * <H2> XML Example </H2>
00565    * <HR>
00566    *
00567    * The phase model name for this is called StoichSubstance. It must be supplied
00568    * as the model attribute of the thermo XML element entry.
00569    * Within the phase XML block,
00570    * the density of the phase must be specified. An example of an XML file
00571    * this phase is given below. 
00572    * 
00573    * @verbatim
00574    <phase id="NaCl_electrolyte" dim="3">
00575     <speciesArray datasrc="#species_waterSolution">
00576                H2O(L) Na+ Cl- H+ OH- NaCl(aq) NaOH(aq)
00577     </speciesArray>
00578     <state>
00579       <temperature units="K"> 300  </temperature>
00580       <pressure units="Pa">101325.0</pressure>
00581       <soluteMolalities>
00582              Na+:3.0
00583              Cl-:3.0
00584              H+:1.0499E-8
00585              OH-:1.3765E-6
00586              NaCl(aq):0.98492
00587              NaOH(aq):3.8836E-6
00588       </soluteMolalities>
00589     </state>
00590     <!-- thermo model identifies the inherited class
00591          from ThermoPhase that will handle the thermodynamics.
00592       -->
00593     <thermo model="DebyeHuckel">
00594        <standardConc model="solvent_volume" />
00595        <activityCoefficients model="Beta_ij">
00596                 <!-- A_Debye units = sqrt(kg/gmol)  -->
00597                 <A_Debye> 1.172576 </A_Debye>
00598                 <!-- B_Debye units = sqrt(kg/gmol)/m   -->
00599                 <B_Debye> 3.28640E9 </B_Debye>
00600                 <ionicRadius default="3.042843"  units="Angstroms">
00601                 </ionicRadius>
00602                 <DHBetaMatrix>
00603                   H+:Cl-:0.27
00604                   Na+:Cl-:0.15
00605                   Na+:OH-:0.06
00606                 </DHBetaMatrix>
00607                 <stoichIsMods>
00608                    NaCl(aq):-1.0
00609                 </stoichIsMods>
00610                 <electrolyteSpeciesType>
00611                    H+:chargedSpecies
00612                    NaCl(aq):weakAcidAssociated
00613                 </electrolyteSpeciesType>
00614        </activityCoefficients>
00615        <solvent> H2O(L) </solvent>
00616     </thermo>
00617     <elementArray datasrc="elements.xml"> O H Na Cl </elementArray>
00618   </phase> 
00619   @endverbatim
00620    *
00621    *
00622    */
00623   class DebyeHuckel : public MolalityVPSSTP {
00624 
00625   public:
00626         
00627     //! Empty Constructor
00628     DebyeHuckel();
00629 
00630     //! Copy constructor
00631     DebyeHuckel(const DebyeHuckel &);
00632 
00633     //! Assignment operator
00634     DebyeHuckel& operator=(const        DebyeHuckel&);
00635 
00636     //! Full constructor for creating the phase.
00637     /*!
00638      *  @param inputFile  File name containing the XML description of the phase
00639      *  @param id     id attribute containing the name of the phase. 
00640      *                (default is the empty string)
00641      */
00642     DebyeHuckel(std::string inputFile, std::string id = "");
00643 
00644     //! Full constructor for creating the phase.
00645     /*!
00646      *  @param phaseRef XML phase node containing the description of the phase
00647      *  @param id     id attribute containing the name of the phase. 
00648      *                (default is the empty string)
00649      */
00650     DebyeHuckel(XML_Node& phaseRef, std::string id = "");
00651 
00652     /// Destructor. 
00653     virtual ~DebyeHuckel();
00654 
00655     //! Duplicator from the ThermoPhase parent class
00656     /*!
00657      * Given a pointer to a ThermoPhase object, this function will
00658      * duplicate the ThermoPhase object and all underlying structures.
00659      * This is basically a wrapper around the copy constructor.
00660      *
00661      * @return returns a pointer to a ThermoPhase
00662      */
00663     ThermoPhase *duplMyselfAsThermoPhase() const;
00664 
00665     /**
00666      *   
00667      * @name  Utilities  
00668      * @{
00669      */
00670 
00671     /** 
00672      * Equation of state type flag. The base class returns
00673      * zero. Subclasses should define this to return a unique
00674      * non-zero value. Constants defined for this purpose are
00675      * listed in mix_defs.h.
00676      */
00677     virtual int eosType() const;
00678 
00679     /**
00680      * @} 
00681      * @name  Molar Thermodynamic Properties of the Solution --------------
00682      * @{
00683      */
00684 
00685     /// Molar enthalpy. Units: J/kmol. 
00686     /**
00687      * Molar enthalpy of the solution. Units: J/kmol.
00688      *      (HKM -> Bump up to Parent object)
00689      */
00690     virtual doublereal enthalpy_mole() const;
00691 
00692     /// Molar internal energy. Units: J/kmol. 
00693     /**
00694      * Molar internal energy of the solution. Units: J/kmol.
00695      *      (HKM -> Bump up to Parent object)
00696      */
00697     virtual doublereal intEnergy_mole() const;
00698 
00699     /// Molar entropy. Units: J/kmol/K. 
00700     /**
00701      * Molar entropy of the solution. Units: J/kmol/K.
00702      * For an ideal, constant partial molar volume solution mixture with
00703      * pure species phases which exhibit zero volume expansivity:
00704      * \f[
00705      * \hat s(T, P, X_k) = \sum_k X_k \hat s^0_k(T)  
00706      *      - \hat R  \sum_k X_k log(X_k)
00707      * \f]
00708      * The reference-state pure-species entropies 
00709      * \f$ \hat s^0_k(T,p_{ref}) \f$ are computed by the
00710      *  species thermodynamic 
00711      * property manager. The pure species entropies are independent of 
00712      * temperature since the volume expansivities are equal to zero.
00713      * @see SpeciesThermo
00714      *
00715      *      (HKM -> Bump up to Parent object)
00716      */
00717     virtual doublereal entropy_mole() const;
00718 
00719     /// Molar Gibbs function. Units: J/kmol. 
00720     /*
00721      *      (HKM -> Bump up to Parent object)
00722      */
00723     virtual doublereal gibbs_mole() const;
00724 
00725     /// Molar heat capacity at constant pressure. Units: J/kmol/K. 
00726     /*
00727      *     
00728      */
00729     virtual doublereal cp_mole() const;
00730 
00731     //! Molar heat capacity at constant volume. Units: J/kmol/K.
00732     /*
00733      *      (HKM -> Bump up to Parent object)
00734      */
00735     virtual doublereal cv_mole() const;
00736 
00737     //@}
00738     /** @name Mechanical Equation of State Properties -------------------------
00739      //@{
00740      *
00741      *   In this equation of state implementation, the density is a 
00742      *   function only of the mole fractions. Therefore, it can't be 
00743      *   an independent variable. Instead, the pressure is used as the
00744      *   independent variable. Functions which try to set the thermodynamic
00745      *   state by calling setDensity() may cause an exception to be
00746      *   thrown.  
00747      */
00748 
00749     //! Return the thermodynamic pressure (Pa).
00750     /*!
00751      * For this incompressible system, we return the internally storred
00752      * independent value of the pressure.
00753      */
00754     virtual doublereal pressure() const;
00755 
00756     //! Set the internally storred pressure (Pa) at constant
00757     //! temperature and composition
00758     /*!
00759      *  This method sets the pressure within the object.
00760      *  The water model is a completely compressible model.
00761      *  Also, the dielectric constant is pressure dependent.
00762      *
00763      *  @param p input Pressure (Pa)
00764      *
00765      * @todo Implement a variable pressure capability
00766      */
00767     virtual void setPressure(doublereal p);
00768 
00769   protected:
00770     //! Calculate the density of the mixture using the partial 
00771     //! molar volumes and mole fractions as input
00772     /*!
00773      * The formula for this is
00774      *
00775      * \f[ 
00776      * \rho = \frac{\sum_k{X_k W_k}}{\sum_k{X_k V_k}} 
00777      * \f]
00778      *
00779      * where \f$X_k\f$ are the mole fractions, \f$W_k\f$ are
00780      * the molecular weights, and \f$V_k\f$ are the pure species
00781      * molar volumes.
00782      *
00783      * Note, the basis behind this formula is that in an ideal
00784      * solution the partial molar volumes are equal to the pure
00785      * species molar volumes. We have additionally specified
00786      * in this class that the pure species molar volumes are
00787      * independent of temperature and pressure.
00788      */
00789     virtual void calcDensity();
00790 
00791   public:
00792     //! Set the internally storred density (gm/m^3) of the phase.
00793     /*!
00794      * Overwritten setDensity() function is necessary because the
00795      * density is not an indendent variable.
00796      *
00797      * This function will now throw an error condition
00798      *
00799      * @internal May have to adjust the strategy here to make
00800      * the eos for these materials slightly compressible, in order
00801      * to create a condition where the density is a function of 
00802      * the pressure.
00803      *
00804      * This function will now throw an error condition if the
00805      * input isn't exactly equal to the current density.
00806      *
00807      *
00808      * @todo Now have a compressible ss equation for liquid water.
00809      *       Therefore, this phase is compressible. May still
00810      *       want to change the independent variable however. 
00811      *
00812      *  NOTE: This is an overwritten function from the State.h
00813      *        class
00814      * 
00815      * @param rho Input density (kg/m^3).
00816      */
00817     void setDensity(const doublereal rho);
00818 
00819     //! Set the internally storred molar density (kmol/m^3) of the phase.
00820     /**
00821      * Overwritten setMolarDensity() function is necessary because the
00822      * density is not an indendent variable.
00823      *
00824      * This function will now throw an error condition if the input
00825      * isn't exactly equal to the current molar density.
00826      *
00827      *  NOTE: This is a virtual function overwritten from the State.h
00828      *        class
00829      *
00830      * @param conc   Input molar density (kmol/m^3).
00831      */
00832     virtual void setMolarDensity(const doublereal conc);
00833 
00834     //! Set the temperature (K)
00835     /*!
00836      * Overwritten setTemperature(double) from State.h. This
00837      * function sets the temperature, and makes sure that
00838      * the value propagates to underlying objects, such as
00839      * the water standard state model.
00840      *
00841      * @todo Make State::setTemperature a virtual function
00842      *
00843      * @param temp Temperature in kelvin
00844      */
00845     virtual void setTemperature(const doublereal temp);
00846 
00847     //! Set the temperature (K) and pressure (Pa)
00848     /*!
00849      *  Set the temperature and pressure.
00850      *
00851      * @param t    Temperature (K)
00852      * @param p    Pressure (Pa)
00853      */
00854     virtual void setState_TP(doublereal t, doublereal p);
00855 
00856     /**
00857      * The isothermal compressibility. Units: 1/Pa.
00858      * The isothermal compressibility is defined as
00859      * \f[
00860      * \kappa_T = -\frac{1}{v}\left(\frac{\partial v}{\partial P}\right)_T
00861      * \f]
00862      */
00863     virtual doublereal isothermalCompressibility() const;
00864 
00865     /**
00866      * The thermal expansion coefficient. Units: 1/K.
00867      * The thermal expansion coefficient is defined as
00868      *
00869      * \f[
00870      * \beta = \frac{1}{v}\left(\frac{\partial v}{\partial T}\right)_P
00871      * \f]
00872      */
00873     virtual doublereal thermalExpansionCoeff() const;
00874 
00875     /**
00876      * @} 
00877      * @name Potential Energy
00878      * 
00879      * Species may have an additional potential energy due to the
00880      * presence of external gravitation or electric fields. These
00881      * methods allow specifying a potential energy for individual
00882      * species.
00883      * @{
00884      */
00885 
00886     /**
00887      * @}
00888      * @name Activities, Standard States,  and Activity Concentrations
00889      *
00890      * The activity \f$a_k\f$ of a species in solution is
00891      * related to the chemical potential by \f[ \mu_k = \mu_k^0(T)
00892      * + \hat R T \log a_k. \f] The quantity \f$\mu_k^0(T,P)\f$ is
00893      * the chemical potential at unit activity, which depends only
00894      * on temperature and the pressure.
00895      * Activity is assumed to be molality-based here.
00896      * @{
00897      */
00898 
00899     //! This method returns an array of generalized concentrations
00900     /*!
00901      * \f$ C_k\f$ that are defined such that 
00902      * \f$ a_k = C_k / C^0_k, \f$ where \f$ C^0_k \f$ 
00903      * is a standard concentration
00904      * defined below.  These generalized concentrations are used
00905      * by kinetics manager classes to compute the forward and
00906      * reverse rates of elementary reactions. 
00907      *
00908      * @param c Array of generalized concentrations. The 
00909      *          units depend upon the implementation of the
00910      *          reaction rate expressions within the phase.
00911      */
00912     virtual void getActivityConcentrations(doublereal* c) const;
00913 
00914     //! Return the standard concentration for the kth species
00915     /*!
00916      * The standard concentration \f$ C^0_k \f$ used to normalize
00917      * the activity (i.e., generalized) concentration in
00918      * kinetics calculations.
00919      *
00920      * For the time being, we will use the concentration of pure
00921      * solvent for the the standard concentration of all species.
00922      * This has the effect of making reaction rates
00923      * based on the molality of species proportional to the
00924      * molality of the species.
00925      *
00926      * @param k Optional parameter indicating the species. The default
00927      *         is to assume this refers to species 0.
00928      * @return 
00929      *   Returns the standard Concentration in units of 
00930      *   m<SUP>3</SUP> kmol<SUP>-1</SUP>.
00931      */
00932     virtual doublereal standardConcentration(int k=0) const;
00933 
00934     //! Natural logarithm of the standard concentration of the kth species.
00935     /*!
00936      * @param k    index of the species (defaults to zero)
00937      */
00938     virtual doublereal logStandardConc(int k=0) const;
00939 
00940     //! Returns the units of the standard and generalized concentrations.
00941     /*!
00942      * Note they have the same units, as their
00943      * ratio is defined to be equal to the activity of the kth
00944      * species in the solution, which is unitless.
00945      *
00946      * This routine is used in print out applications where the
00947      * units are needed. Usually, MKS units are assumed throughout
00948      * the program and in the XML input files.
00949      *
00950      * The base %ThermoPhase class assigns the default quantities
00951      * of (kmol/m3) for all species.
00952      * Inherited classes are responsible for overriding the default 
00953      * values if necessary.
00954      *
00955      * @param uA Output vector containing the units
00956      *  uA[0] = kmol units - default  = 1
00957      *  uA[1] = m    units - default  = -nDim(), the number of spatial
00958      *                                dimensions in the Phase class.
00959      *  uA[2] = kg   units - default  = 0;
00960      *  uA[3] = Pa(pressure) units - default = 0;
00961      *  uA[4] = Temperature units - default = 0;
00962      *  uA[5] = time units - default = 0
00963      * @param k species index. Defaults to 0.
00964      * @param sizeUA output int containing the size of the vector.
00965      *        Currently, this is equal to 6.
00966      */
00967     virtual void getUnitsStandardConc(double *uA, int k = 0,
00968                                       int sizeUA = 6) const;
00969 
00970     //! Get the array of non-dimensional activities at
00971     //! the current solution temperature, pressure, and solution concentration.
00972     /*!
00973      *
00974      * We resolve this function at this level by calling
00975      * on the activityConcentration function. However, 
00976      * derived classes may want to override this default
00977      * implementation.
00978      *
00979      * (note solvent is on molar scale).
00980      *
00981      * @param ac  Output vector of activities. Length: m_kk.
00982      */
00983     virtual void getActivities(doublereal* ac) const;
00984 
00985     //! Get the array of non-dimensional molality-based 
00986     //! activity coefficients at
00987     //! the current solution temperature, pressure, and solution concentration.
00988     /*!
00989      *  note solvent is on molar scale. The solvent molar
00990      *  based activity coefficient is returned.
00991      *
00992      * @param acMolality Vector of Molality-based activity coefficients
00993      *                   Length: m_kk
00994      */
00995     virtual void 
00996     getMolalityActivityCoefficients(doublereal* acMolality) const;
00997 
00998     //@}
00999     /// @name  Partial Molar Properties of the Solution -----------------
01000     //@{
01001 
01002     
01003     //! Get the species chemical potentials. Units: J/kmol.
01004     /*!
01005      *
01006      * This function returns a vector of chemical potentials of the 
01007      * species in solution.
01008      *
01009      * \f[
01010      *    \mu_k = \mu^{\triangle}_k(T,P) + R T ln(\gamma_k^{\triangle} m_k)
01011      * \f]
01012      *  or another way to phrase this is
01013      *
01014      *  where
01015      *
01016      * @param mu  Output vector of species chemical 
01017      *            potentials. Length: m_kk. Units: J/kmol
01018      */
01019     virtual void getChemPotentials(doublereal* mu) const;
01020 
01021     //! Returns an array of partial molar enthalpies for the species
01022     //! in the mixture. Units (J/kmol)
01023     /*!
01024      * For this phase, the partial molar enthalpies are equal to the
01025      * standard state enthalpies modified by the derivative of the
01026      * molality-based activity coefficent wrt temperature
01027      *
01028      *  \f[
01029      * \bar h_k(T,P) = h^{\triangle}_k(T,P) - R T^2 \frac{d \ln(\gamma_k^\triangle)}{dT}
01030      * \f]
01031      * The solvent partial molar enthalpy is equal to 
01032      *  \f[
01033      * \bar h_o(T,P) = h^{o}_o(T,P) - R T^2 \frac{d \ln(a_o}{dT}
01034      * \f]
01035      *
01036      * The temperature dependence of the activity coefficients currently
01037      * only occurs through the temperature dependence of the Debye constant.
01038      *
01039      * @param hbar    Output vector of species partial molar enthalpies.
01040      *                Length: m_kk. units are J/kmol.
01041      */
01042     virtual void getPartialMolarEnthalpies(doublereal* hbar) const;
01043 
01044     //! Returns an array of partial molar entropies of the species in the
01045     //! solution. Units: J/kmol/K.
01046     /**
01047      * Maxwell's equations provide an insight in how to calculate this
01048      *   (p.215 Smith and Van Ness)
01049      *
01050      *      d(chemPot_i)/dT = -sbar_i
01051      *      
01052      * For this phase, the partial molar entropies are equal to the
01053      * SS species entropies plus the ideal solution contribution.following
01054      * contribution:
01055      *  \f[
01056      *     \bar s_k(T,P) =  \hat s^0_k(T) - R log(M0 * molality[k])
01057      * \f]
01058      * \f[
01059      *      \bar s_solvent(T,P) =  \hat s^0_solvent(T) 
01060      *                  - R ((xmolSolvent - 1.0) / xmolSolvent)
01061      * \f]
01062      *
01063      * The reference-state pure-species entropies,\f$ \hat s^0_k(T) \f$,
01064      * at the reference pressure, \f$ P_{ref} \f$,  are computed by the
01065      * species thermodynamic
01066      * property manager. They are polynomial functions of temperature.
01067      * @see SpeciesThermo
01068      *
01069      *  @param sbar    Output vector of species partial molar entropies.
01070      *                 Length = m_kk. units are J/kmol/K.
01071      */
01072     virtual void getPartialMolarEntropies(doublereal* sbar) const;
01073      
01074     //! Return an array of partial molar heat capacities for the
01075     //! species in the mixture.  Units: J/kmol/K
01076     /*!
01077      * @param cpbar   Output vector of species partial molar heat 
01078      *                capacities at constant pressure.
01079      *                Length = m_kk. units are J/kmol/K.
01080      */
01081     virtual void getPartialMolarCp(doublereal* cpbar) const;
01082 
01083     //! Return an array of partial molar volumes for the
01084     //! species in the mixture. Units: m^3/kmol.
01085     /*!
01086      * For this solution, the partial molar volumes are equal to the
01087      * constant species molar volumes.
01088      *
01089      *  @param vbar   Output vector of speciar partial molar volumes.
01090      *                Length = m_kk. units are m^3/kmol.
01091      */
01092     virtual void getPartialMolarVolumes(doublereal* vbar) const;
01093 
01094     //@}
01095 
01096 
01097   protected:
01098 
01099     //! Updates the standard state thermodynamic functions at the current T and P of the solution.
01100     /*!
01101      * @internal
01102      *
01103      * This function gets called for every call to a public function in this
01104      * class. It checks to see whether the temperature or pressure has changed and
01105      * thus whether the ss thermodynamics functions must be recalculated.
01106      *
01107      * @param pres  Pressure at which to evaluate the standard states.
01108      *              The default, indicated by a -1.0, is to use the current pressure
01109      */                    
01110     //virtual void _updateStandardStateThermo() const;
01111 
01112     //@}
01113     /// @name Thermodynamic Values for the Species Reference States ---
01114     //@{
01115 
01116 
01117     ///////////////////////////////////////////////////////
01118     //
01119     //  The methods below are not virtual, and should not
01120     //  be overloaded.
01121     //
01122     //////////////////////////////////////////////////////
01123 
01124     /**
01125      * @name Specific Properties
01126      * @{
01127      */
01128 
01129 
01130     /**
01131      * @name Setting the State
01132      *
01133      * These methods set all or part of the thermodynamic
01134      * state.
01135      * @{
01136      */
01137 
01138     //@}
01139 
01140     /**
01141      * @name Chemical Equilibrium
01142      * Chemical equilibrium.
01143      * @{
01144      */
01145 
01146     //!This method is used by the ChemEquil equilibrium solver.
01147     /*!
01148      * It sets the state such that the chemical potentials satisfy
01149      * \f[ \frac{\mu_k}{\hat R T} = \sum_m A_{k,m}
01150      * \left(\frac{\lambda_m} {\hat R T}\right) \f] where 
01151      * \f$ \lambda_m \f$ is the element potential of element m. The
01152      * temperature is unchanged.  Any phase (ideal or not) that
01153      * implements this method can be equilibrated by ChemEquil.
01154      *
01155      * @param lambda_RT Input vector of dimensionless element potentials
01156      *                  The length is equal to nElements().
01157      */ 
01158   public:
01159     virtual void setToEquilState(const doublereal* lambda_RT) {
01160       err("setToEquilState");
01161     }
01162 
01163 
01164     //@}
01165 
01166 
01167     //! Set the equation of state parameters
01168     /*!
01169      * @internal
01170      *  The number and meaning of these depends on the subclass. 
01171      *
01172      * @param n number of parameters
01173      * @param c array of \a n coefficients
01174      */
01175     virtual void setParameters(int n, doublereal* const c);
01176 
01177     //! Get the equation of state parameters in a vector
01178     /*!
01179      * @internal
01180      * The number and meaning of these depends on the subclass. 
01181      *
01182      * @param n number of parameters
01183      * @param c array of \a n coefficients
01184      */
01185     virtual void getParameters(int &n, doublereal * const c) const;
01186 
01187     //! Set equation of state parameter values from XML entries.
01188     /*!
01189      *
01190      * This method is called by function importPhase() in
01191      * file importCTML.cpp when processing a phase definition in
01192      * an input file. It should be overloaded in subclasses to set
01193      * any parameters that are specific to that particular phase
01194      * model. Note, this method is called before the phase is
01195      * initialzed with elements and/or species.
01196      *   
01197      * @param eosdata An XML_Node object corresponding to
01198      *                the "thermo" entry for this phase in the input file.
01199      */
01200     virtual void setParametersFromXML(const XML_Node& eosdata);
01201  
01202     //---------------------------------------------------------
01203     /// @name Critical state properties.
01204     /// These methods are only implemented by some subclasses.
01205         
01206     //@{
01207         
01208    
01209         
01210     //@}
01211         
01212     /// @name Saturation properties.
01213     /// These methods are only implemented by subclasses that 
01214     /// implement full liquid-vapor equations of state.
01215     ///
01216     virtual doublereal satTemperature(doublereal p) const {
01217       err("satTemperature"); return -1.0;
01218     }
01219 
01220     //! Get the saturation pressure for a given temperature. 
01221     /*!
01222      * Note the limitations of this function. Stability considerations
01223      * concernting multiphase equilibrium are ignored in this 
01224      * calculation. Therefore, the call is made directly to the SS of 
01225      * water underneath. The object is put back into its original
01226      * state at the end of the call.
01227      *
01228      * @todo This is probably not implemented correctly. The stability
01229      *       of the salt should be added into this calculation. The
01230      *       underlying water model may be called to get the stability
01231      *       of the pure water solution, if needed.
01232      *
01233      * @param T  Temperature (kelvin)
01234      */   
01235     virtual doublereal satPressure(doublereal T) const {
01236       err("satPressure"); return -1.0;
01237     }
01238         
01239     virtual doublereal vaporFraction() const {
01240       err("vaprFraction"); return -1.0;
01241     }
01242         
01243     virtual void setState_Tsat(doublereal t, doublereal x) {
01244       err("setState_sat"); 
01245     }
01246 
01247     virtual void setState_Psat(doublereal p, doublereal x) {
01248       err("setState_sat"); 
01249     }
01250 
01251     //@}
01252 
01253 
01254     /*
01255      *  -------------- Utilities -------------------------------
01256      */
01257 
01258  
01259     /**
01260      * Return a reference to the species thermodynamic property
01261      * manager.  @todo This method will fail if no species thermo
01262      * manager has been installed.
01263      */
01264     SpeciesThermo& speciesThermo() { return *m_spthermo; }
01265 
01266     //! Initialize the object's internal lengths after species are set
01267     /**
01268      * @internal Initialize. This method is provided to allow
01269      * subclasses to perform any initialization required after all
01270      * species have been added. For example, it might be used to
01271      * resize internal work arrays that must have an entry for
01272      * each species.  The base class implementation does nothing,
01273      * and subclasses that do not require initialization do not
01274      * need to overload this method.  When importing a CTML phase
01275      * description, this method is called just prior to returning
01276      * from function importPhase().
01277      *
01278      * Cascading call sequence downwards starting with Parent.
01279      *
01280      * @internal
01281      *
01282      * @see importCTML.cpp
01283      */
01284     virtual void initThermo();
01285 
01286     
01287     //! Initialization of a DebyeHuckel phase using an xml file
01288     /*!
01289      * This routine is a precursor to initThermo(XML_Node*)
01290      * routine, which does most of the work.
01291      *
01292      * @param infile XML file containing the description of the
01293      *        phase
01294      *
01295      * @param id  Optional parameter identifying the name of the
01296      *            phase. If none is given, the first XML
01297      *            phase element will be used.
01298      */
01299     void constructPhaseFile(std::string infile, std::string id="");
01300     
01301     //!   Import and initialize a DebyeHuckel phase 
01302     //!   specification in an XML tree into the current object.
01303     /*!
01304      *   Here we read an XML description of the phase.
01305      *   We import descriptions of the elements that make up the
01306      *   species in a phase.
01307      *   We import information about the species, including their
01308      *   reference state thermodynamic polynomials. We then freeze
01309      *   the state of the species.
01310      *
01311      *   Then, we read the species molar volumes from the xml 
01312      *   tree to finish the initialization.
01313      *
01314      * @param phaseNode This object must be the phase node of a
01315      *             complete XML tree
01316      *             description of the phase, including all of the
01317      *             species data. In other words while "phase" must
01318      *             point to an XML phase object, it must have
01319      *             sibling nodes "speciesData" that describe
01320      *             the species in the phase.
01321      *
01322      * @param id   ID of the phase. If nonnull, a check is done
01323      *             to see if phaseNode is pointing to the phase
01324      *             with the correct id. 
01325      */
01326     void constructPhaseXML(XML_Node& phaseNode, std::string id="");
01327     
01328     //! Process the XML file after species are set up.
01329     /*!
01330      *  This gets called from importPhase(). It processes the XML file
01331      *  after the species are set up. This is the main routine for
01332      *  reading in activity coefficient parameters.
01333      *
01334      * @param phaseNode This object must be the phase node of a
01335      *             complete XML tree
01336      *             description of the phase, including all of the
01337      *             species data. In other words while "phase" must
01338      *             point to an XML phase object, it must have
01339      *             sibling nodes "speciesData" that describe
01340      *             the species in the phase.
01341      * @param id   ID of the phase. If nonnull, a check is done
01342      *             to see if phaseNode is pointing to the phase
01343      *             with the correct id.
01344      */
01345     virtual void  initThermoXML(XML_Node& phaseNode, std::string id);
01346     
01347     //! Return  the Debye Huckel constant as a function of temperature
01348     //! and pressure (Units = sqrt(kg/gmol))
01349     /*!
01350      *  The default is to assume that it is constant, given
01351      *  in the initialization process, and storred in the
01352      *  member double, m_A_Debye. Optionally, a full water treatment may be employed that makes
01353      *  \f$ A_{Debye} \f$ a full function of T and P.
01354      *
01355      *   \f[
01356      *      A_{Debye} = \frac{F e B_{Debye}}{8 \pi \epsilon R T} {\left( C_o \tilde{M}_o \right)}^{1/2}
01357      *   \f]
01358      * where
01359      * 
01360      *  \f[
01361      *         B_{Debye} = \frac{F} {{(\frac{\epsilon R T}{2})}^{1/2}} 
01362      *  \f]
01363      *  Therefore:
01364      * \f[
01365      *   A_{Debye} = \frac{1}{8 \pi} 
01366      *                 {\left(\frac{2 N_a \rho_o}{1000}\right)}^{1/2}
01367      *                 {\left(\frac{N_a e^2}{\epsilon R T }\right)}^{3/2}
01368      * \f]
01369      *
01370      *            Units = sqrt(kg/gmol)
01371      *
01372      *     where
01373      *      - \f$ N_a \f$ is Avrogadro's number
01374      *      - \f$ \rho_w \f$ is the density of water
01375      *      - \f$ e \f$ is the electronic charge
01376      *      - \f$ \epsilon = K \epsilon_o \f$ is the permitivity of water
01377      *           where \f$ K \f$ is the dielectric condstant of water,
01378      *           and  \f$ \epsilon_o \f$ is the permitivity of free space.
01379      *      = \f$ \rho_o \f$ is the density of the solvent in its standard state.
01380      *
01381      *            Nominal value at 298 K and 1 atm = 1.172576 (kg/gmol)<SUP>1/2</SUP>
01382      *                  based on:
01383      *                 -   \f$ \epsilon / \epsilon_0 \f$ = 78.54
01384      *                           (water at 25C)
01385      *                 -   \f$ \epsilon_0 \f$= 8.854187817E-12 C<SUP>2</SUP> N<SUP>-1</SUP> m<SUP>-2</SUP>
01386      *                 -   e = 1.60217653E-19 C
01387      *                 -   F = 9.6485309E7 C kmol<SUP>-1</SUP>
01388      *                 -   R = 8.314472E3 kg m<SUP>2</SUP> s<SUP>-2</SUP> kmol<SUP>-1</SUP> K<SUP>-1</SUP>
01389      *                 -   T = 298.15 K
01390      *                 -   B_Debye = 3.28640E9 (kg/gmol)<SUP>1/2</SUP> m<SUP>-1</SUP>
01391      *                 -   \f$N_a\f$ = 6.0221415E26 kmol<SUP>-1</SUP>
01392      *   
01393      * @param temperature Temperature in kelvin. Defaults to -1, in which
01394      *                    case the   temperature of the phase is assumed.
01395      *
01396      * @param pressure Pressure (Pa). Defaults to -1, in which
01397      *                    case the pressure of the phase is assumed.
01398      */
01399     virtual double A_Debye_TP(double temperature = -1.0, 
01400                               double pressure = -1.0) const;
01401 
01402     
01403     //! Value of the derivative of the Debye Huckel constant with 
01404     //! respect to temperature.
01405     /*!
01406      * This is a function of temperature and pressure. See A_Debye_TP() for 
01407      * a definition of \f$ A_{Debye} \f$.
01408      *     
01409      *            Units = sqrt(kg/gmol) K-1
01410      *
01411      * @param temperature Temperature in kelvin. Defaults to -1, in which
01412      *                    case the   temperature of the phase is assumed.
01413      *
01414      * @param pressure Pressure (Pa). Defaults to -1, in which
01415      *                    case the pressure of the phase is assumed.
01416      */
01417     virtual double dA_DebyedT_TP(double temperature = -1.0, 
01418                                  double pressure = -1.0) const;
01419     
01420     //! Value of the 2nd derivative of the Debye Huckel constant with 
01421     //! respect to temperature as a function of temperature and pressure.
01422     /*!
01423      * This is a function of temperature and pressure. See A_Debye_TP() for 
01424      * a definition of \f$ A_{Debye} \f$.
01425      *     
01426      *            Units = sqrt(kg/gmol) K-2
01427      *
01428      * @param temperature Temperature in kelvin. Defaults to -1, in which
01429      *                    case the   temperature of the phase is assumed.
01430      *
01431      * @param pressure Pressure (Pa). Defaults to -1, in which
01432      *                    case the pressure of the phase is assumed.
01433      */
01434     virtual double d2A_DebyedT2_TP(double temperature = -1.0, 
01435                                    double pressure = -1.0) const;
01436 
01437     //! Value of the derivative of the Debye Huckel constant with 
01438     //! respect to pressure, as a function of temperature and pressure.
01439     /*!
01440      * This is a function of temperature and pressure. See A_Debye_TP() for 
01441      * a definition of \f$ A_{Debye} \f$.
01442      *     
01443      *            Units = sqrt(kg/gmol) Pa-1
01444      *
01445      * @param temperature Temperature in kelvin. Defaults to -1, in which
01446      *                    case the   temperature of the phase is assumed.
01447      *
01448      * @param pressure Pressure (Pa). Defaults to -1, in which
01449      *                    case the pressure of the phase is assumed.
01450      */
01451     virtual double dA_DebyedP_TP(double temperature = -1.0, 
01452                                  double pressure = -1.0) const;
01453 
01454     //!Reports the ionic radius of the kth species
01455     /*!
01456      * @param k  species index.
01457      */
01458     double AionicRadius(int k = 0) const;
01459 
01460     //! Returns the form of the Debye-Huckel parameterization used
01461     int formDH() const { return m_formDH; }
01462 
01463     //! Returns a reference to M_Beta_ij
01464     Array2D& get_Beta_ij() { return m_Beta_ij; }
01465 
01466   private:
01467 
01468 
01469     //!  Static function that implements the non-polar species
01470     //!   salt-out modifications.
01471     /*!
01472      *   Returns the calculated activity coefficients.
01473      *
01474      * @param IionicMolality Value of the ionic molality (sqrt(gmol/kg))
01475      */
01476     double _nonpolarActCoeff(double IionicMolality) const;
01477 
01478     
01479     //!      Formula for the osmotic coefficient that occurs in the GWB.
01480     /*!
01481      * It is originally from Helgeson for a variable
01482      *      NaCl brine. It's to be used with extreme caution.
01483      */
01484     double _osmoticCoeffHelgesonFixedForm() const;
01485 
01486     //!      Formula for the log of the water activity that occurs in the GWB.
01487     /*!
01488      * It is originally from Helgeson for a variable
01489      *      NaCl brine. It's to be used with extreme caution.
01490      */
01491     double _lnactivityWaterHelgesonFixedForm() const;
01492  
01493  
01494     //@}
01495 
01496          
01497   protected:
01498 
01499    
01500     //! form of the Debye-Huckel parameterization  used in the model.
01501     /*!
01502      * The options are described at the top of this document,
01503      * and in the general documentation.
01504      * The list is repeated here:
01505      *
01506      * DHFORM_DILUTE_LIMIT  = 0       (default)
01507      * DHFORM_BDOT_AK       = 1
01508      * DHFORM_BDOT_AUNIFORM = 2
01509      * DHFORM_BETAIJ        = 3
01510      * DHFORM_PITZER_BETAIJ = 4
01511      */
01512     int m_formDH;
01513 
01514     /**
01515      * Format for the generalized concentration:
01516      *
01517      *  0 = unity
01518      *  1 = molar_volume
01519      *  2 = solvent_volume    (default)
01520      *
01521      * The generalized concentrations can have three different forms
01522      * depending on the value of the member attribute m_formGC, which
01523      * is supplied in the constructor.
01524      *                          <TABLE>
01525      *  <TR><TD> m_formGC </TD><TD> GeneralizedConc </TD><TD> StandardConc </TD></TR>
01526      *  <TR><TD> 0        </TD><TD> X_k             </TD><TD> 1.0          </TD></TR>
01527      *  <TR><TD> 1        </TD><TD> X_k / V_k       </TD><TD> 1.0 / V_k    </TD></TR>
01528      *  <TR><TD> 2        </TD><TD> X_k / V_N       </TD><TD> 1.0 / V_N    </TD></TR>
01529      *                         </TABLE>
01530      *
01531      * The value and form of the generalized concentration will affect
01532      * reaction rate constants involving species in this phase.
01533      *
01534      * (HKM Note: Using option #1 may lead to spurious results and
01535      *  has been included only with warnings. The reason is that it
01536      *  molar volumes of electrolytes may often be negative. The
01537      *  molar volume of H+ is defined to be zero too. Either options
01538      *  0 or 2 are the appropriate choice. Option 0 leads to 
01539      *  bulk reaction rate constants which have units of s-1.
01540      *  Option 2 leads to bulk reaction rate constants for 
01541      *  bimolecular rxns which have units of m-3 kmol-1 s-1.)
01542      */
01543     int m_formGC;
01544 
01545     //! Vector containing the electrolyte species type
01546     /*!
01547      * The possible types are:
01548      *  - solvent
01549      *  - Charged Species
01550      *  - weakAcidAssociated
01551      *  - strongAcidAssociated
01552      *  - polarNeutral
01553      *  - nonpolarNeutral
01554      *  .
01555      */
01556     vector_int  m_electrolyteSpeciesType;
01557 
01558     /**
01559      * Species molar volumes \f$ m^3 kmol^-1 \f$
01560      *  -> m_speciesSize in Constituents.h
01561      */
01562     //array_fp m_speciesMolarVolume;
01563 
01564     /**
01565      *  a_k = Size of the ionic species in the DH formulation
01566      *        units = meters
01567      */
01568     array_fp m_Aionic;
01569 
01570     /**
01571      * Current value of the ionic strength on the molality scale
01572      */
01573     mutable double m_IionicMolality;
01574 
01575     /**
01576      * Maximum value of the ionic strength allowed in the
01577      * calculation of the activity coefficients.
01578      */
01579     double m_maxIionicStrength;
01580 
01581   public:
01582 
01583     /**
01584      * If true, then the fixed for of Helgeson's activity
01585      * for water is used instead of the rigoruous form 
01586      * obtained from Gibbs-Duhem relation. This should be
01587      * used with caution, and is really only included as a 
01588      * validation exercise.
01589      */
01590     bool m_useHelgesonFixedForm;
01591   protected:
01592 
01593     //! Stoichiometric ionic strength on the molality scale
01594     mutable double m_IionicMolalityStoich;
01595 
01596   public:
01597 
01598     /**
01599      * Form of the constant outside the Debye-Huckel term
01600      * called A. It's normally a function of temperature 
01601      * and pressure. However, it can be set from the
01602      * input file in order to aid in numerical comparisons.
01603      * Acceptable forms:
01604      *
01605      *       A_DEBYE_CONST  0
01606      *       A_DEBYE_WATER  1
01607      *
01608      * The A_DEBYE_WATER form may be used for water solvents
01609      * with needs to cover varying temperatures and pressures.
01610      * Note, the dielectric constant of water is a relatively
01611      * strong function of T, and its variability must be
01612      * accounted for,
01613      */
01614     int m_form_A_Debye;
01615 
01616   protected:
01617 
01618     //! Current value of the Debye Constant, A_Debye
01619     /**
01620      * A_Debye -> this expression appears on the top of the
01621      *            ln actCoeff term in the general Debye-Huckel
01622      *            expression
01623      *            It depends on temperature and pressure.
01624      *            
01625      *            A_Debye = (F e B_Debye) / (8 Pi epsilon R T)
01626      *
01627      *            Units = sqrt(kg/gmol)
01628      *
01629      *            Nominal value(298K, atm) = 1.172576 sqrt(kg/gmol)
01630      *                  based on:
01631      *                    epsilon/epsilon_0 = 78.54
01632      *                           (water at 25C)
01633      *                    epsilon_0 = 8.854187817E12 C2 N-1 m-2
01634      *                    e = 8.314472E3 kg m2 s-2 kmol-1 K-1
01635      *                    F = 9.6485309E7 C kmol-1
01636      *                    R = 8.314472E3 kg m2 s-2 kmol-1 K-1
01637      *                    T = 298.15 K
01638      *                    B_Debye = 3.28640E9 sqrt(kg/gmol)/m
01639      *
01640      *            note in Pitzer's nomenclature, A_phi = A_Debye/3.0
01641      */
01642     mutable double m_A_Debye;
01643 
01644     //! Current value of the constant that appears in the denominator
01645     /**
01646      * B_Debye -> this expression appears on the bottom of the
01647      *            ln actCoeff term in the general Debye-Huckel
01648      *            expression
01649      *            It depends on temperature
01650      *            
01651      *            B_Bebye = F / sqrt( epsilon R T / 2 )
01652      *
01653      *            Units = sqrt(kg/gmol) / m
01654      *
01655      *            Nominal value = 3.28640E9 sqrt(kg/gmol) / m
01656      *                  based on:
01657      *                    epsilon/epsilon_0 = 78.54
01658      *                           (water at 25C)
01659      *                    epsilon_0 = 8.854187817E12 C2 N-1 m-2
01660      *                    e = 8.314472E3 kg m2 s-2 kmol-1 K-1
01661      *                    F = 9.6485309E7 C kmol-1
01662      *                    R = 8.314472E3 kg m2 s-2 kmol-1 K-1
01663      *                    T = 298.15 K
01664      */
01665     double m_B_Debye;
01666 
01667     //! Array of B_Dot valyes
01668     /**
01669      *  B_Dot ->  This expression is an extension of the 
01670      *            Debye-Huckel expression used in some formulations
01671      *            to extend DH to higher molalities.
01672      *            B_dot is specific to the major ionic pair.
01673      */
01674     array_fp  m_B_Dot;
01675 
01676     /**
01677      * m_npActCoeff -> These are coefficients to describe
01678      *  the increase in activity coeff for non-polar molecules
01679      *  due to the electrolyte becoming stronger (the so-called
01680      *  salt-out effect)
01681      */
01682     array_fp m_npActCoeff;
01683 
01684     
01685     //! Pointer to the  Water standard state object
01686     /*!
01687      *  derived from the equation of state for water.
01688      */
01689     PDSS_Water *m_waterSS;
01690 
01691     //! Storage for the density of water's standard state
01692     /*!
01693      * Density depends on temperature and pressure.
01694      */
01695     double m_densWaterSS;
01696 
01697     /**
01698      *  Pointer to the water property calculator
01699      */
01700     WaterProps *m_waterProps;
01701 
01702     /**
01703      * Vector containing the species reference exp(-G/RT) functions
01704      * at T = m_tlast
01705      */
01706     mutable vector_fp      m_expg0_RT;
01707 
01708     /**
01709      * Vector of potential energies for the species.
01710      */
01711     mutable vector_fp      m_pe;
01712 
01713     /**
01714      * Temporary array used in equilibrium calculations
01715      */
01716     mutable vector_fp      m_pp;
01717 
01718     /**
01719      * vector of size m_kk, used as a temporary holding area.
01720      */
01721     mutable vector_fp      m_tmpV;
01722 
01723     /**
01724      * Stoichiometric species charge -> This is for calculations
01725      * of the ionic strength which ignore ion-ion pairing into
01726      * neutral molecules. The Stoichiometric species charge is the
01727      * charge of one of the ion that would occur if the species broke
01728      * into two charged ion pairs.
01729      *  NaCl ->   m_speciesCharge_Stoich = -1;
01730      *  HSO4- -> H+ + SO42-              = -2
01731      *      -> The other charge is calculated.
01732      * For species that aren't ion pairs, its equal to the
01733      * m_speciesCharge[] value.
01734      */
01735     vector_fp  m_speciesCharge_Stoich;
01736 
01737     /**
01738      *  Array of 2D data used in the DHFORM_BETAIJ formulation
01739      *  Beta_ij.value(i,j) is the coefficient of the jth species
01740      *  for the specification of the chemical potential of the ith
01741      *  species.
01742      */
01743     Array2D m_Beta_ij;
01744 
01745     //!  Logarithm of the activity coefficients on the molality scale.
01746     /*!
01747      *       mutable because we change this if the composition
01748      *       or temperature or pressure changes.
01749      */
01750     mutable array_fp m_lnActCoeffMolal;
01751 
01752     //! Derivative of log act coeff wrt T
01753     mutable array_fp m_dlnActCoeffMolaldT;
01754 
01755     //! 2nd Derivative of log act coeff wrt T
01756     mutable array_fp m_d2lnActCoeffMolaldT2;
01757 
01758     //! Derivative of log act coeff wrt P
01759     mutable array_fp m_dlnActCoeffMolaldP;
01760   
01761   private:
01762     doublereal err(std::string msg) const;
01763 
01764     //! Initialize the internal lengths.
01765     /*!
01766      * This internal function adjusts the lengths of arrays based on
01767      * the number of species.
01768      */
01769     void initLengths();
01770 
01771   private:
01772     //! Calculate the log activity coefficients
01773     /*!
01774      * This function updates the internally storred
01775      * natural logarithm of the molality activity coefficients 
01776      */
01777     void s_update_lnMolalityActCoeff() const;
01778 
01779     //! Calculation of temperatue derivative of activity coefficient
01780     /*!
01781      *   Using internally stored values, this function calculates
01782      *   the temperature derivative of the logarithm of the
01783      *   activity coefficient for all species in the mechanism.
01784      *
01785      *   We assume that the activity coefficients are current in this routine
01786      *
01787      *
01788      *
01789      *   The solvent activity coefficient is on the molality scale. It's derivative is too.
01790      */
01791     void s_update_dlnMolalityActCoeff_dT() const;
01792 
01793     //! Calculate the temperature 2nd derivative of the activity coefficient
01794     /*!
01795      *   Using internally stored values, this function calculates
01796      *   the temperature 2nd derivative of the logarithm of the
01797      *   activity coefficient for all species in the mechanism.
01798      *
01799      *   We assume that the activity coefficients are current in this routine
01800      *
01801      *   solvent activity coefficient is on the molality
01802      *   scale. It's derivatives are too.
01803      *
01804      * note: private routine
01805      */
01806     void s_update_d2lnMolalityActCoeff_dT2() const;
01807 
01808     //! Calculate the pressure derivative of the activity coefficient
01809     /*!
01810      *   Using internally stored values, this function calculates
01811      *   the pressure derivative of the logarithm of the
01812      *   activity coefficient for all species in the mechanism.
01813      *
01814      *   We assume that the activity coefficients, molalities,
01815      *   and A_Debye are current.
01816      *
01817      *   solvent activity coefficient is on the molality
01818      *   scale. It's derivatives are too.
01819      */
01820     void s_update_dlnMolalityActCoeff_dP() const;
01821   };
01822 
01823 }
01824         
01825 #endif
01826 
01827 
01828 
01829 
01830 
Generated by  doxygen 1.6.3