Cantera  2.0
MolalityVPSSTP.h
Go to the documentation of this file.
1 /**
2  * @file MolalityVPSSTP.h
3  * Header for intermediate ThermoPhase object for phases which
4  * employ molality based activity coefficient formulations
5  * (see \ref thermoprops
6  * and class \link Cantera::MolalityVPSSTP MolalityVPSSTP\endlink).
7  *
8  * Header file for a derived class of ThermoPhase that handles
9  * variable pressure standard state methods for calculating
10  * thermodynamic properties that are further based upon activities
11  * based on the molality scale. These include most of the methods for
12  * calculating liquid electrolyte thermodynamics.
13  */
14 /*
15  * Copyright (2006) Sandia Corporation. Under the terms of
16  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
17  * U.S. Government retains certain rights in this software.
18  */
19 #ifndef CT_MOLALITYVPSSTP_H
20 #define CT_MOLALITYVPSSTP_H
21 
22 #include "VPStandardStateTP.h"
23 
24 namespace Cantera
25 {
26 
27 /**
28  * @ingroup thermoprops
29  */
30 
31 /*!
32  * MolalityVPSSTP is a derived class of ThermoPhase that handles
33  * variable pressure standard state methods for calculating
34  * thermodynamic properties that are further based on
35  * molality-scaled activities.
36  * This category incorporates most of the methods
37  * for calculating liquid electrolyte thermodynamics that have been
38  * developed since the 1970's.
39  *
40  * This class adds additional functions onto the %ThermoPhase interface
41  * that handle molality based standard states. The %ThermoPhase
42  * class includes a member function, ThermoPhase::activityConvention()
43  * that indicates which convention the activities are based on. The
44  * default is to assume activities are based on the molar convention.
45  * However, classes which derive from the MolalityVPSSTP class return
46  * <b>cAC_CONVENTION_MOLALITY</b> from this member function.
47  *
48  * The molality of a solute, \f$ m_i \f$, is defined as
49  *
50  * \f[
51  * m_i = \frac{n_i}{\tilde{M}_o n_o}
52  * \f]
53  * where
54  * \f[
55  * \tilde{M}_o = \frac{M_o}{1000}
56  * \f]
57  *
58  * where \f$ M_o \f$ is the molecular weight of the solvent. The molality
59  * has units of gmol kg<SUP>-1</SUP>. For the solute, the molality may be
60  * considered as the amount of gmol's of solute per kg of solvent, a natural
61  * experimental quantity.
62  *
63  * The formulas for calculating mole fractions if given the molalities of
64  * the solutes is stated below. First calculate \f$ L^{sum} \f$, an intermediate
65  * quantity.
66  *
67  * \f[
68  * L^{sum} = \frac{1}{\tilde{M}_o X_o} = \frac{1}{\tilde{M}_o} + \sum_{i\ne o} m_i
69  * \f]
70  * Then,
71  * \f[
72  * X_o = \frac{1}{\tilde{M}_o L^{sum}}
73  * \f]
74  * \f[
75  * X_i = \frac{m_i}{L^{sum}}
76  * \f]
77  * where \f$ X_o \f$ is the mole fraction of solvent, and \f$ X_o \f$ is the
78  * mole fraction of solute <I>i</I>. Thus, the molality scale and the mole fraction
79  * scale offer a one-to-one mapping between each other, except in the limit
80  * of a zero solvent mole fraction.
81  *
82  * The standard states for thermodynamic objects that derive from <b>MolalityVPSSTP</b>
83  * are on the unit molality basis. Chemical potentials
84  * of the solutes, \f$ \mu_k \f$, and the solvent, \f$ \mu_o \f$, which are based
85  * on the molality form, have the following general format:
86  *
87  * \f[
88  * \mu_k = \mu^{\triangle}_k(T,P) + R T ln(\gamma_k^{\triangle} \frac{m_k}{m^\triangle})
89  * \f]
90  * \f[
91  * \mu_o = \mu^o_o(T,P) + RT ln(a_o)
92  * \f]
93  *
94  * where \f$ \gamma_k^{\triangle} \f$ is the molality based activity coefficient for species
95  * \f$k\f$.
96  *
97  * The chemical potential of the solvent is thus expressed in a different format
98  * than the chemical potential of the solutes. Additionally, the activity of the
99  * solvent, \f$ a_o \f$, is further reexpressed in terms of an osmotic coefficient,
100  * \f$ \phi \f$.
101  * \f[
102  * \phi = \frac{- ln(a_o)}{\tilde{M}_o \sum_{i \ne o} m_i}
103  * \f]
104  *
105  * MolalityVPSSTP::osmoticCoefficient() returns the value of \f$ \phi \f$.
106  * Note there are a few of definitions of the osmotic coefficient floating
107  * around. We use the one defined in
108  * (Activity Coefficients in Electrolyte Solutions, K. S. Pitzer
109  * CRC Press, Boca Raton, 1991, p. 85, Eqn. 28). This definition is most clearly
110  * related to theoretical calculation.
111  *
112  * The molar-based activity coefficients \f$ \gamma_k \f$ may be calculated
113  * from the molality-based
114  * activity coefficients, \f$ \gamma_k^\triangle \f$ by the following
115  * formula.
116  * \f[
117  * \gamma_k = \frac{\gamma_k^\triangle}{X_o}
118  * \f]
119  * For purposes of establishing a convention, the molar activity coefficient of the
120  * solvent is set equal to the molality-based activity coefficient of the
121  * solvent:
122  * \f[
123  * \gamma_o = \gamma_o^\triangle
124  * \f]
125  *
126  * The molality-based and molarity-based standard states may be related to one
127  * another by the following formula.
128  *
129  * \f[
130  * \mu_k^\triangle(T,P) = \mu_k^o(T,P) + R T \ln(\tilde{M}_o m^\triangle)
131  * \f]
132  *
133  * An important convention is followed in all routines that derive from <b>%MolalityVPSSTP</b>.
134  * Standard state thermodynamic functions and reference state thermodynamic functions
135  * return the molality-based quantities. Also all functions which return
136  * activities return the molality-based activities. The reason for this convention
137  * has been discussed in supporting memos. However, it's important because the
138  * term in the equation above is non-trivial. For example it's equal
139  * to 2.38 kcal gmol<SUP>-1</SUP> for water at 298 K.
140  *
141  *
142  * In order to prevent a singularity, this class includes the concept of a minimum
143  * value for the solvent mole fraction. All calculations involving the formulation
144  * of activity coefficients and other non-ideal solution behavior adhere to
145  * this concept of a minimal value for the solvent mole fraction. This makes sense
146  * because these solution behavior were all designed and measured far away from
147  * the zero solvent singularity condition and are not applicable in that limit.
148  *
149  *
150  * This objects add a layer that supports molality. It inherits from VPStandardStateTP.
151  *
152  * All objects that derive from this are assumed to have molality based standard states.
153  *
154  * Molality based activity coefficients are scaled according to the current
155  * pH scale. See the Eq3/6 manual for details.
156  *
157  * Activity coefficients for species k may be altered between scales s1 to s2
158  * using the following formula
159  *
160  * \f[
161  * ln(\gamma_k^{s2}) = ln(\gamma_k^{s1})
162  * + \frac{z_k}{z_j} \left( ln(\gamma_j^{s2}) - ln(\gamma_j^{s1}) \right)
163  * \f]
164  *
165  * where j is any one species. For the NBS scale, j is equal to the Cl- species
166  * and
167  *
168  * \f[
169  * ln(\gamma_{Cl-}^{s2}) = \frac{-A_{\phi} \sqrt{I}}{1.0 + 1.5 \sqrt{I}}
170  * \f]
171  *
172  * The Pitzer scale doesn't actually change anything. The pitzer scale is defined
173  * as the raw unscaled activity coefficients produced by the underlying objects.
174  *
175  * <H3> SetState Strategy </H3>
176  *
177  * The MolalityVPSSTP object does not have a setState strategy concerning the
178  * molalities. It does not keep track of whether the molalities have changed.
179  * It's strictly an interfacial layer that writes the current mole fractions to the
180  * State object. When molalities are needed it recalculates the molalities from
181  * the State object's mole fraction vector.
182  *
183  *
184  * @todo Make two solvent minimum fractions. One would be for calculation of the non-ideal
185  * factors. The other one would be for purposes of stoichiometry evaluation. the
186  * stoichiometry evaluation one would be a 1E-13 limit. Anything less would create
187  * problems with roundoff error.
188  *
189  */
191 {
192 
193 public:
194 
195  /// Constructors
196  /*!
197  * This doesn't do much more than initialize constants with
198  * default values for water at 25C. Water molecular weight
199  * comes from the default elements.xml file. It actually
200  * differs slightly from the IAPWS95 value of 18.015268. However,
201  * density conservation and therefore element conservation
202  * is the more important principle to follow.
203  */
204  MolalityVPSSTP();
205 
206  //! Copy constructor
207  /*!
208  * Note this stuff will not work until the underlying phase
209  * has a working copy constructor
210  *
211  * @param b class to be copied
212  */
213  MolalityVPSSTP(const MolalityVPSSTP& b);
214 
215  /// Assignment operator
216  /*!
217  * Note this stuff will not work until the underlying phase
218  * has a working assignment operator
219  *
220  * @param b class to be copied.
221  */
223 
224  /// Destructor.
225  virtual ~MolalityVPSSTP();
226 
227  //! Duplication routine for objects which inherit from ThermoPhase.
228  /*!
229  * This virtual routine can be used to duplicate thermophase objects
230  * inherited from ThermoPhase even if the application only has
231  * a pointer to ThermoPhase to work with.
232  */
233  virtual ThermoPhase* duplMyselfAsThermoPhase() const;
234 
235  /**
236  *
237  * @name Utilities
238  * @{
239  */
240 
241 
242  //! Equation of state type flag.
243  /*!
244  * The ThermoPhase base class returns
245  * zero. Subclasses should define this to return a unique
246  * non-zero value. Known constants defined for this purpose are
247  * listed in mix_defs.h. The MolalityVPSSTP class also returns
248  * zero, as it is a non-complete class.
249  */
250  virtual int eosType() const;
251 
252  //! Set the pH scale, which determines the scale for single-ion activity
253  //! coefficients.
254  /*!
255  * Single ion activity coefficients are not unique in terms of the
256  * representing actual measurable quantities.
257  *
258  * @param pHscaleType Integer representing the pHscale
259  */
260  void setpHScale(const int pHscaleType);
261 
262  //! Reports the pH scale, which determines the scale for single-ion activity
263  //! coefficients.
264  /*!
265  * Single ion activity coefficients are not unique in terms of the
266  * representing actual measurable quantities.
267  *
268  * @return Return the pHscale type
269  */
270  int pHScale() const;
271 
272  /**
273  * @}
274  * @name Molar Thermodynamic Properties
275  * @{
276  */
277 
278 
279  /**
280  * @}
281  * @name Utilities for Solvent ID and Molality
282  * @{
283  */
284 
285  /**
286  * This routine sets the index number of the solvent for
287  * the phase.
288  *
289  * Note, having a solvent
290  * is a precursor to many things having to do with molality.
291  *
292  * @param k the solvent index number
293  */
294  void setSolvent(size_t k);
295 
296  /**
297  * Sets the minimum mole fraction in the molality formulation.
298  * Note the molality formulation is singular in the limit that
299  * the solvent mole fraction goes to zero. Numerically, how
300  * this limit is treated and resolved is an ongoing issue within
301  * Cantera.
302  *
303  * @param xmolSolventMIN Input double containing the minimum mole fraction
304  */
305  void setMoleFSolventMin(doublereal xmolSolventMIN);
306 
307  //! Returns the solvent index.
308  size_t solventIndex() const;
309 
310  /**
311  * Returns the minimum mole fraction in the molality
312  * formulation.
313  */
314  doublereal moleFSolventMin() const;
315 
316  //! Calculates the molality of all species and stores the result internally.
317  /*!
318  * We calculate the vector of molalities of the species
319  * in the phase and store the result internally:
320  * \f[
321  * m_i = \frac{X_i}{1000 * M_o * X_{o,p}}
322  * \f]
323  * where
324  * - \f$ M_o \f$ is the molecular weight of the solvent
325  * - \f$ X_o \f$ is the mole fraction of the solvent
326  * - \f$ X_i \f$ is the mole fraction of the solute.
327  * - \f$ X_{o,p} = max (X_{o}^{min}, X_o) \f$
328  * - \f$ X_{o}^{min} \f$ = minimum mole fraction of solvent allowed
329  * in the denominator.
330  */
331  void calcMolalities() const;
332 
333  //! This function will return the molalities of the species.
334  /*!
335  * We calculate the vector of molalities of the species
336  * in the phase
337  * \f[
338  * m_i = \frac{X_i}{1000 * M_o * X_{o,p}}
339  * \f]
340  * where
341  * - \f$ M_o \f$ is the molecular weight of the solvent
342  * - \f$ X_o \f$ is the mole fraction of the solvent
343  * - \f$ X_i \f$ is the mole fraction of the solute.
344  * - \f$ X_{o,p} = \max (X_{o}^{min}, X_o) \f$
345  * - \f$ X_{o}^{min} \f$ = minimum mole fraction of solvent allowed
346  * in the denominator.
347  *
348  * @param molal Output vector of molalities. Length: m_kk.
349  */
350  void getMolalities(doublereal* const molal) const;
351 
352  //! Set the molalities of the solutes in a phase
353  /*!
354  * Note, the entry for the solvent is not used.
355  * We are supplied with the molalities of all of the
356  * solute species. We then calculate the mole fractions of all
357  * species and update the %ThermoPhase object.
358  * \f[
359  * m_i = \frac{X_i}{M_o/1000 * X_{o,p}}
360  * \f]
361  * where
362  * - \f$M_o\f$ is the molecular weight of the solvent
363  * - \f$X_o\f$ is the mole fraction of the solvent
364  * - \f$X_i\f$ is the mole fraction of the solute.
365  * - \f$X_{o,p} = \max(X_o^{min}, X_o)\f$
366  * - \f$X_o^{min}\f$ = minimum mole fraction of solvent allowed
367  * in the denominator.
368  *
369  * The formulas for calculating mole fractions are
370  * \f[
371  * L^{sum} = \frac{1}{\tilde{M}_o X_o} = \frac{1}{\tilde{M}_o} + \sum_{i\ne o} m_i
372  * \f]
373  * Then,
374  * \f[
375  * X_o = \frac{1}{\tilde{M}_o L^{sum}}
376  * \f]
377  * \f[
378  * X_i = \frac{m_i}{L^{sum}}
379  * \f]
380  * It is currently an error if the solvent mole fraction is attempted to be set
381  * to a value lower than \f$X_o^{min}\f$.
382  *
383  * @param molal Input vector of molalities. Length: m_kk.
384  */
385  void setMolalities(const doublereal* const molal);
386 
387  //! Set the molalities of a phase
388  /*!
389  * Set the molalities of the solutes in a phase. Note, the entry for the
390  * solvent is not used.
391  *
392  * @param xMap Composition Map containing the molalities.
393  */
395 
396  //! Set the molalities of a phase
397  /*!
398  * Set the molalities of the solutes in a phase. Note, the entry for the
399  * solvent is not used.
400  *
401  * @param name String containing the information for a composition map.
402  */
403  void setMolalitiesByName(const std::string& name);
404 
405  /**
406  * @}
407  * @name Mechanical Properties
408  * @{
409  */
410 
411  /**
412  * @}
413  * @name Potential Energy
414  *
415  * Species may have an additional potential energy due to the
416  * presence of external gravitation or electric fields. These
417  * methods allow specifying a potential energy for individual
418  * species.
419  * @{
420  */
421 
422  /**
423  * @}
424  * @name Activities, Standard States, and Activity Concentrations
425  *
426  * The activity \f$a_k\f$ of a species in solution is
427  * related to the chemical potential by \f[ \mu_k = \mu_k^0(T)
428  * + \hat R T \log a_k. \f] The quantity \f$\mu_k^0(T,P)\f$ is
429  * the chemical potential at unit activity, which depends only
430  * on temperature and pressure.
431  * @{
432  */
433 
434  /**
435  * This method returns the activity convention.
436  * Currently, there are two activity conventions
437  * Molar-based activities
438  * Unit activity of species at either a hypothetical pure
439  * solution of the species or at a hypothetical
440  * pure ideal solution at infinite dilution
441  * cAC_CONVENTION_MOLAR 0
442  * - default
443  *
444  * Molality based activities
445  * (unit activity of solutes at a hypothetical 1 molal
446  * solution referenced to infinite dilution at all
447  * pressures and temperatures).
448  * cAC_CONVENTION_MOLALITY 1
449  *
450  * We set the convention to molality here.
451  */
452  int activityConvention() const;
453 
454  /**
455  * This method returns an array of generalized concentrations
456  * \f$ C_k\f$ that are defined such that
457  * \f$ a_k = C_k / C^0_k, \f$ where \f$ C^0_k \f$
458  * is a standard concentration
459  * defined below. These generalized concentrations are used
460  * by kinetics manager classes to compute the forward and
461  * reverse rates of elementary reactions.
462  *
463  * @param c Array of generalized concentrations. The
464  * units depend upon the implementation of the
465  * reaction rate expressions within the phase.
466  */
467  virtual void getActivityConcentrations(doublereal* c) const;
468 
469  /**
470  * The standard concentration \f$ C^0_k \f$ used to normalize
471  * the generalized concentration. In many cases, this quantity
472  * will be the same for all species in a phase - for example,
473  * for an ideal gas \f$ C^0_k = P/\hat R T \f$. For this
474  * reason, this method returns a single value, instead of an
475  * array. However, for phases in which the standard
476  * concentration is species-specific (e.g. surface species of
477  * different sizes), this method may be called with an
478  * optional parameter indicating the species.
479  *
480  * @param k species index. Defaults to zero.
481  */
482  virtual doublereal standardConcentration(size_t k=0) const;
483 
484  /**
485  * Returns the natural logarithm of the standard
486  * concentration of the kth species
487  *
488  * @param k species index
489  */
490  virtual doublereal logStandardConc(size_t k=0) const;
491 
492  /**
493  * Returns the units of the standard and generalized
494  * concentrations Note they have the same units, as their
495  * ratio is defined to be equal to the activity of the kth
496  * species in the solution, which is unitless.
497  *
498  * This routine is used in print out applications where the
499  * units are needed. Usually, MKS units are assumed throughout
500  * the program and in the XML input files.
501  *
502  * @param uA Output vector containing the units
503  * uA[0] = kmol units - default = 1
504  * uA[1] = m units - default = -nDim(), the number of spatial
505  * dimensions in the Phase class.
506  * uA[2] = kg units - default = 0;
507  * uA[3] = Pa(pressure) units - default = 0;
508  * uA[4] = Temperature units - default = 0;
509  * uA[5] = time units - default = 0
510  * @param k species index. Defaults to 0.
511  * @param sizeUA output int containing the size of the vector.
512  * Currently, this is equal to 6.
513  */
514  virtual void getUnitsStandardConc(double* uA, int k = 0,
515  int sizeUA = 6) const;
516 
517 
518  //! Get the array of non-dimensional activities (molality
519  //! based for this class and classes that derive from it) at
520  //! the current solution temperature, pressure, and solution concentration.
521  /*!
522  * All standard state properties for molality-based phases are
523  * evaluated consistent with the molality scale. Therefore, this function
524  * must return molality-based activities.
525  *
526  * \f[
527  * a_i^\triangle = \gamma_k^{\triangle} \frac{m_k}{m^\triangle}
528  * \f]
529  *
530  * This function must be implemented in derived classes.
531  *
532  * @param ac Output vector of molality-based activities. Length: m_kk.
533  */
534  virtual void getActivities(doublereal* ac) const;
535 
536  //! Get the array of non-dimensional activity coefficients at
537  //! the current solution temperature, pressure, and solution concentration.
538  /*!
539  * These are mole-fraction based activity coefficients. In this
540  * object, their calculation is based on translating the values
541  * of the molality-based activity coefficients.
542  * See Denbigh p. 278 for a thorough discussion.
543  *
544  * The molar-based activity coefficients \f$ \gamma_k \f$ may be calculated from the
545  * molality-based
546  * activity coefficients, \f$ \gamma_k^\triangle \f$ by the following
547  * formula.
548  * \f[
549  * \gamma_k = \frac{\gamma_k^\triangle}{X_o}
550  * \f]
551  *
552  * For purposes of establishing a convention, the molar activity coefficient of the
553  * solvent is set equal to the molality-based activity coefficient of the
554  * solvent:
555  *
556  * \f[
557  * \gamma_o = \gamma_o^\triangle
558  * \f]
559  *
560  * Derived classes don't need to overload this function. This function is
561  * handled at this level.
562  *
563  * @param ac Output vector containing the mole-fraction based activity coefficients.
564  * length: m_kk.
565  */
566  void getActivityCoefficients(doublereal* ac) const;
567 
568  //! Get the array of non-dimensional molality based
569  //! activity coefficients at the current solution temperature,
570  //! pressure, and solution concentration.
571  /*!
572  * See Denbigh p. 278 for a thorough discussion. This class must be overwritten in
573  * classes which derive from %MolalityVPSSTP. This function takes over from the
574  * molar-based activity coefficient calculation, getActivityCoefficients(), in
575  * derived classes.
576  *
577  * These molality based activity coefficients are scaled according to the current
578  * pH scale. See the Eq3/6 manual for details.
579  *
580  * Activity coefficients for species k may be altered between scales s1 to s2
581  * using the following formula
582  *
583  * \f[
584  * ln(\gamma_k^{s2}) = ln(\gamma_k^{s1})
585  * + \frac{z_k}{z_j} \left( ln(\gamma_j^{s2}) - ln(\gamma_j^{s1}) \right)
586  * \f]
587  *
588  * where j is any one species. For the NBS scale, j is equal to the Cl- species
589  * and
590  *
591  * \f[
592  * ln(\gamma_{Cl-}^{s2}) = \frac{-A_{\phi} \sqrt{I}}{1.0 + 1.5 \sqrt{I}}
593  * \f]
594  *
595  * @param acMolality Output vector containing the molality based activity coefficients.
596  * length: m_kk.
597  */
598  virtual void getMolalityActivityCoefficients(doublereal* acMolality) const;
599 
600 
601 
602  //! Calculate the osmotic coefficient
603  /*!
604  * \f[
605  * \phi = \frac{- ln(a_o)}{\tilde{M}_o \sum_{i \ne o} m_i}
606  * \f]
607  *
608  * Note there are a few of definitions of the osmotic coefficient floating
609  * around. We use the one defined in
610  * (Activity Coefficients in Electrolyte Solutions, K. S. Pitzer
611  * CRC Press, Boca Raton, 1991, p. 85, Eqn. 28). This definition is most clearly
612  * related to theoretical calculation.
613  *
614  * units = dimensionless
615  */
616  virtual double osmoticCoefficient() const;
617 
618  //@}
619  /// @name Partial Molar Properties of the Solution
620  //@{
621 
622 
623  /**
624  * Get the species electrochemical potentials.
625  * These are partial molar quantities.
626  * This method adds a term \f$ Fz_k \phi_k \f$ to the
627  * to each chemical potential.
628  *
629  * Units: J/kmol
630  *
631  * @param mu output vector containing the species electrochemical potentials.
632  * Length: m_kk.
633  */
634  void getElectrochemPotentials(doublereal* mu) const;
635 
636 
637  //@}
638  /// @name Properties of the Standard State of the Species in the Solution
639  //@{
640 
641 
642 
643  //@}
644  /// @name Thermodynamic Values for the Species Reference States
645  //@{
646 
647 
648  ///////////////////////////////////////////////////////
649  //
650  // The methods below are not virtual, and should not
651  // be overloaded.
652  //
653  //////////////////////////////////////////////////////
654 
655  /**
656  * @name Specific Properties
657  * @{
658  */
659 
660 
661  /**
662  * @name Setting the State
663  *
664  * These methods set all or part of the thermodynamic
665  * state.
666  * @{
667  */
668 
669  //@}
670 
671  /**
672  * @name Chemical Equilibrium
673  * Routines that implement the Chemical equilibrium capability
674  * for a single phase, based on the element-potential method.
675  * @{
676  */
677 
678  /**
679  * This method is used by the ChemEquil element-potential
680  * based equilibrium solver.
681  * It sets the state such that the chemical potentials of the
682  * species within the current phase satisfy
683  * \f[ \frac{\mu_k}{\hat R T} = \sum_m A_{k,m}
684  * \left(\frac{\lambda_m} {\hat R T}\right) \f] where
685  * \f$ \lambda_m \f$ is the element potential of element m. The
686  * temperature is unchanged. Any phase (ideal or not) that
687  * implements this method can be equilibrated by ChemEquil.
688  *
689  * @param lambda_RT Input vector containing the dimensionless
690  * element potentials.
691  */
692  virtual void setToEquilState(const doublereal* lambda_RT);
693 
694 
695  //@}
696 
697 
698  //! Set equation of state parameter values from XML entries.
699  /*!
700  * This method is called by function importPhase() in
701  * file importCTML.cpp when processing a phase definition in
702  * an input file. It should be overloaded in subclasses to set
703  * any parameters that are specific to that particular phase
704  * model.
705  *
706  * The MolalityVPSSTP object defines a new method for setting
707  * the concentrations of a phase. The new method is defined by a
708  * block called "soluteMolalities". If this block
709  * is found, the concentrations within that phase are
710  * set to the "name":"molalities pairs found within that
711  * XML block. The solvent concentration is then set
712  * to everything else.
713  *
714  * The function first calls the overloaded function ,
715  * VPStandardStateTP::setStateFromXML(), to pick up the parent class
716  * behavior.
717  *
718  * usage: Overloaded functions should call this function
719  * before carrying out their own behavior.
720  *
721  * @param state An XML_Node object corresponding to
722  * the "state" entry for this phase in the input file.
723  */
724  virtual void setStateFromXML(const XML_Node& state);
725 
726  /// The following methods are used in the process of constructing
727  /// the phase and setting its parameters from a specification in an
728  /// input file. They are not normally used in application programs.
729  /// To see how they are used, see files importCTML.cpp and
730  /// ThermoFactory.cpp.
731 
732 
733  /*!
734  * @internal Initialize. This method is provided to allow
735  * subclasses to perform any initialization required after all
736  * species have been added. For example, it might be used to
737  * resize internal work arrays that must have an entry for
738  * each species. The base class implementation does nothing,
739  * and subclasses that do not require initialization do not
740  * need to overload this method. When importing a CTML phase
741  * description, this method is called just prior to returning
742  * from function importPhase.
743  *
744  * @see importCTML.cpp
745  */
746  virtual void initThermo();
747 
748 
749  /**
750  * Import and initialize a ThermoPhase object
751  *
752  * @param phaseNode This object must be the phase node of a
753  * complete XML tree
754  * description of the phase, including all of the
755  * species data. In other words while "phase" must
756  * point to an XML phase object, it must have
757  * sibling nodes "speciesData" that describe
758  * the species in the phase.
759  * @param id ID of the phase. If nonnull, a check is done
760  * to see if phaseNode is pointing to the phase
761  * with the correct id.
762  */
763  void initThermoXML(XML_Node& phaseNode, std::string id);
764 
765 
766  //! Set the temperature (K), pressure (Pa), and molalities
767  //!(gmol kg-1) of the solutes
768  /*!
769  * @param t Temperature (K)
770  * @param p Pressure (Pa)
771  * @param molalities Input vector of molalities of the solutes.
772  * Length: m_kk.
773  */
774  void setState_TPM(doublereal t, doublereal p,
775  const doublereal* const molalities);
776 
777  //! Set the temperature (K), pressure (Pa), and molalities.
778  /*!
779  * @param t Temperature (K)
780  * @param p Pressure (Pa)
781  * @param m compositionMap containing the molalities
782  */
783  void setState_TPM(doublereal t, doublereal p, compositionMap& m);
784 
785  //! Set the temperature (K), pressure (Pa), and molalities.
786  /*!
787  * @param t Temperature (K)
788  * @param p Pressure (Pa)
789  * @param m String which gets translated into a composition
790  * map for the molalities of the solutes.
791  */
792  void setState_TPM(doublereal t, doublereal p, const std::string& m);
793 
794  //! Get the array of derivatives of the log activity coefficients with respect to the log of the species mole numbers
795  /*!
796  * Implementations should take the derivative of the logarithm of the activity coefficient with respect to a
797  * species log mole number (with all other species mole numbers held constant). The default treatment in the
798  * %ThermoPhase object is to set this vector to zero.
799  *
800  * units = 1 / kmol
801  *
802  * dlnActCoeffdlnN[ ld * k + m] will contain the derivative of log act_coeff for the <I>m</I><SUP>th</SUP>
803  * species with respect to the number of moles of the <I>k</I><SUP>th</SUP> species.
804  *
805  * \f[
806  * \frac{d \ln(\gamma_m) }{d \ln( n_k ) }\Bigg|_{n_i}
807  * \f]
808  *
809  * @param ld Number of rows in the matrix
810  * @param dlnActCoeffdlnN Output vector of derivatives of the
811  * log Activity Coefficients. length = m_kk * m_kk
812  */
813  virtual void getdlnActCoeffdlnN(const size_t ld, doublereal* const dlnActCoeffdlnN) {
814  getdlnActCoeffdlnN_numderiv(ld, dlnActCoeffdlnN);
815  }
816 
817  //! returns a summary of the state of the phase as a string
818  /*!
819  * @param show_thermo If true, extra information is printed out
820  * about the thermodynamic state of the system.
821  */
822  virtual std::string report(bool show_thermo = true) const;
823 
824  //! returns a summary of the state of the phase to specified
825  //! comma separated files
826  /*!
827  * @param csvFile ofstream file to print comma separated data for
828  * the phase
829  */
830  virtual void reportCSV(std::ofstream& csvFile) const;
831 
832 protected:
833 
834  //! Get the array of unscaled non-dimensional molality based
835  //! activity coefficients at the current solution temperature,
836  //! pressure, and solution concentration.
837  /*!
838  * See Denbigh p. 278 for a thorough discussion. This class must be overwritten in
839  * classes which derive from %MolalityVPSSTP. This function takes over from the
840  * molar-based activity coefficient calculation, getActivityCoefficients(), in
841  * derived classes.
842  *
843  * @param acMolality Output vector containing the molality based activity coefficients.
844  * length: m_kk.
845  */
846  virtual void getUnscaledMolalityActivityCoefficients(doublereal* acMolality) const;
847 
848  //! Apply the current phScale to a set of activity Coefficients or activities
849  /*!
850  * See the Eq3/6 Manual for a thorough discussion.
851  *
852  * @param acMolality input/Output vector containing the molality based
853  * activity coefficients. length: m_kk.
854  */
855  virtual void applyphScale(doublereal* acMolality) const;
856 
857 private:
858  //! Returns the index of the Cl- species.
859  /*!
860  * The Cl- species is special in the sense that its single ion
861  * molality-based activity coefficient is used in the specification
862  * of the pH scale for single ions. Therefore, we need to know
863  * what species index is Cl-. If the species isn't in the species
864  * list then this routine returns -1, and we can't use the NBS
865  * pH scale.
866  *
867  * Right now we use a restrictive interpretation. The species
868  * must be named "Cl-". It must consist of exactly one Cl and one E
869  * atom.
870  */
871  virtual size_t findCLMIndex() const;
872 
873  //! Initialize lengths of local variables after all species have
874  //! been identified.
875  void initLengths();
876 
877 protected:
878 
879  //! Index of the solvent
880  /*!
881  * Currently the index of the solvent is hard-coded to the value 0
882  */
884 
885  //! Scaling to be used for output of single-ion species activity
886  //! coefficients.
887  /*!
888  * Index of the species to be used in the single-ion scaling
889  * law. This is the identity of the Cl- species for the PHSCALE_NBS
890  * scaling.
891  * Either PHSCALE_PITZER or PHSCALE_NBS
892  */
894 
895  //! Index of the phScale species
896  /*!
897  * Index of the species to be used in the single-ion scaling
898  * law. This is the identity of the Cl- species for the PHSCALE_NBS
899  * scaling
900  */
901  size_t m_indexCLM;
902 
903  //! Molecular weight of the Solvent
904  doublereal m_weightSolvent;
905 
906  /*!
907  * In any molality implementation, it makes sense to have
908  * a minimum solvent mole fraction requirement, since the
909  * implementation becomes singular in the xmolSolvent=0
910  * limit. The default is to set it to 0.01.
911  * We then modify the molality definition to ensure that
912  * molal_solvent = 0 when xmol_solvent = 0.
913  */
914  doublereal m_xmolSolventMIN;
915 
916  //! This is the multiplication factor that goes inside
917  //! log expressions involving the molalities of species.
918  /*!
919  * It's equal to Wt_0 / 1000,
920  * where Wt_0 = weight of solvent (kg/kmol)
921  */
922  doublereal m_Mnaught;
923 
924  //! Current value of the molalities of the species in the phase.
925  /*!
926  * Note this vector is a mutable quantity.
927  * units are (kg/kmol)
928  */
930 
931 private:
932  //! Error function
933  /*!
934  * Print an error string and exit
935  *
936  * @param msg Message to be printed
937  */
938  doublereal err(std::string msg) const;
939 
940 };
941 
942 
943 //! Scale to be used for the output of single-ion activity coefficients
944 //! is that used by Pitzer.
945 /*!
946  * This is the internal scale used within the code. One property is that
947  * the activity coefficients for the cation and anion of a single salt
948  * will be equal. This scale is the one presumed by the formulation of the
949  * single-ion activity coefficients described in this report.
950  *
951  * Activity coefficients for species k may be altered between scales s1 to s2
952  * using the following formula
953  *
954  * \f[
955  * ln(\gamma_k^{s2}) = ln(\gamma_k^{s1})
956  * + \frac{z_k}{z_j} \left( ln(\gamma_j^{s2}) - ln(\gamma_j^{s1}) \right)
957  * \f]
958  *
959  * where j is any one species.
960  *
961  *
962  */
963 const int PHSCALE_PITZER = 0;
964 
965 //! Scale to be used for evaluation of single-ion activity coefficients
966 //! is that used by the NBS standard for evaluation of the pH variable.
967 /*!
968  * This is not the internal scale used within the code.
969  *
970  * Activity coefficients for species k may be altered between scales s1 to s2
971  * using the following formula
972  *
973  * \f[
974  * ln(\gamma_k^{s2}) = ln(\gamma_k^{s1})
975  * + \frac{z_k}{z_j} \left( ln(\gamma_j^{s2}) - ln(\gamma_j^{s1}) \right)
976  * \f]
977  *
978  * where j is any one species. For the NBS scale, j is equal to the Cl- species
979  * and
980  *
981  * \f[
982  * ln(\gamma_{Cl-}^{s2}) = \frac{-A_{\phi} \sqrt{I}}{1.0 + 1.5 \sqrt{I}}
983  * \f]
984  *
985  * This is the NBS pH scale, which is used in all conventional pH
986  * measurements. and is based on the Bates-Guggenheim equations.
987  *
988  */
989 const int PHSCALE_NBS = 1;
990 
991 }
992 
993 #endif
994 
995 
996 
997 
998