Cantera  2.0
ChemEquil.h
Go to the documentation of this file.
1 /**
2  * @file ChemEquil.h
3  *
4  * Chemical equilibrium.
5  */
6 /*
7  * Copyright 2001 California Institute of Technology
8  */
9 
10 
11 #ifndef CT_CHEM_EQUIL_H
12 #define CT_CHEM_EQUIL_H
13 
14 
15 // Cantera includes
16 #include "cantera/base/ct_defs.h"
21 
22 #include "MultiPhaseEquil.h"
23 
24 #include <memory>
25 
26 namespace Cantera
27 {
28 
29 int _equilflag(const char* xy);
30 
31 /**
32  * Chemical equilibrium options. Used internally by class ChemEquil.
33  */
34 class EquilOpt
35 {
36 public:
37  EquilOpt() : relTolerance(1.e-8), absElemTol(1.0E-70),maxIterations(1000),
38  iterations(0),
39  maxStepSize(10.0), propertyPair(TP), contin(false) {}
40 
41  doublereal relTolerance; ///< Relative tolerance
42  doublereal absElemTol; ///< Abs Tol in element number
43  int maxIterations; ///< Maximum number of iterations
44  int iterations; ///< Iteration counter
45 
46  /**
47  * Maximum step size. Largest change in any element potential or
48  * in log(T) allowed in one Newton step. Default: 10.0
49  */
50  doublereal maxStepSize;
51 
52  /**
53  * Property pair flag. Determines which two thermodynamic properties
54  * are fixed.
55  */
57 
58  /**
59  * Continuation flag. Set true if the calculation should be
60  * initialized from the last calculation. Otherwise, the
61  * calculation will be started from scratch and the initial
62  * composition and element potentials estimated.
63  */
64  bool contin;
65 };
66 
67 template<class M>
68 class PropertyCalculator;
69 
70 /**
71  * @defgroup equil Chemical Equilibrium
72  *
73  */
74 
75 /**
76  * Class ChemEquil implements a chemical equilibrium solver for
77  * single-phase solutions. It is a "non-stoichiometric" solver in
78  * the terminology of Smith and Missen, meaning that every
79  * intermediate state is a valid chemical equilibrium state, but
80  * does not necessarily satisfy the element constraints. In
81  * contrast, the solver implemented in class MultiPhaseEquil uses
82  * a "stoichiometric" algorithm, in which each intermediate state
83  * satisfies the element constraints but is not a state of
84  * chemical equilibrium. Non-stoichiometric methods are faster
85  * when they converge, but stoichiometric ones tend to be more
86  * robust and can be used also for problems with multiple
87  * condensed phases. As expected, the ChemEquil solver is faster
88  * than MultiPhaseEquil for many single-phase equilibrium
89  * problems (particularly if there are only a few elements but
90  * very many species), but can be less stable. Problem
91  * situations include low temperatures where only a few species
92  * have non-zero mole fractions, precisely stoichiometric
93  * compositions (e.g. 2 H2 + O2). In general, if speed is
94  * important, this solver should be tried first, and if it fails
95  * then use MultiPhaseEquil.
96  * @ingroup equil
97  */
98 class ChemEquil
99 {
100 
101 public:
102  //! Default Constructor
103  ChemEquil();
104 
105  //! Constructor combined with the initialization function
106  /*!
107  * This constructor initializes the ChemEquil object with everything it
108  * needs to start solving equilibrium problems.
109  * @param s ThermoPhase object that will be used in the equilibrium calls.
110  */
111  ChemEquil(thermo_t& s);
112 
113  virtual ~ChemEquil();
114 
115  int equilibrate(thermo_t& s, const char* XY,
116  bool useThermoPhaseElementPotentials = false, int loglevel = 0);
117  int equilibrate(thermo_t& s, const char* XY, vector_fp& elMoles,
118  bool useThermoPhaseElementPotentials = false, int loglevel = 0);
119  const vector_fp& elementPotentials() const {
120  return m_lambda;
121  }
122 
123  /**
124  * Options controlling how the calculation is carried out.
125  * @see EquilOptions
126  */
128 
129 
130 protected:
131 
132  //! Pointer to the %ThermoPhase object used to initialize this object.
133 
134  /*!
135  * This %ThermoPhase object must be compatible with the %ThermoPhase
136  * objects input from the equilibrate function. Currently, this
137  * means that the 2 %ThermoPhases have to have consist of the same
138  * species and elements.
139  */
141 
142  /// number of atoms of element m in species k.
143  doublereal nAtoms(size_t k, size_t m) const {
144  return m_comp[k*m_mm + m];
145  }
146 
147  void initialize(thermo_t& s);
148 
149  void setToEquilState(thermo_t& s,
150  const vector_fp& x, doublereal t);
151 
152  int setInitialMoles(thermo_t& s, vector_fp& elMoleGoal, int loglevel = 0);
153 
155  vector_fp& elMolesGoal, int loglevel = 0);
156 
157  int estimateEP_Brinkley(thermo_t& s, vector_fp& lambda, vector_fp& elMoles);
158 
159  int dampStep(thermo_t& s, vector_fp& oldx,
160  double oldf, vector_fp& grad, vector_fp& step, vector_fp& x,
161  double& f, vector_fp& elmols, double xval, double yval);
162 
163  void equilResidual(thermo_t& s, const vector_fp& x,
164  const vector_fp& elmtotal, vector_fp& resid,
165  double xval, double yval, int loglevel = 0);
166 
167  void equilJacobian(thermo_t& s, vector_fp& x,
168  const vector_fp& elmols, DenseMatrix& jac,
169  double xval, double yval, int loglevel = 0);
170 
171  void adjustEloc(thermo_t& s, vector_fp& elMolesGoal);
172 
173  void update(const thermo_t& s);
174 
175  double calcEmoles(thermo_t& s, vector_fp& x,
176  const double& n_t, const vector_fp& Xmol_i_calc,
177  vector_fp& eMolesCalc, vector_fp& n_i_calc,
178  double pressureConst);
179 
180  size_t m_mm;
181  size_t m_kk;
182  size_t m_skip;
183 
184  /**
185  * This is equal to the rank of the stoichiometric coefficient
186  * matrix when it is computed. It's initialized to m_mm.
187  */
189 
190  std::auto_ptr<PropertyCalculator<thermo_t> > m_p1, m_p2;
191 
192  /**
193  * Current value of the mole fractions in the single phase.
194  * -> length = m_kk.
195  */
197  /**
198  * Current value of the dimensional element potentials
199  * -> length = m_mm
200  */
202 
203  /*
204  * Current value of the sum of the element abundances given the
205  * current element potentials.
206  */
207  doublereal m_elementTotalSum;
208  /*
209  * Current value of the element mole fractions. Note these aren't
210  * the goal element mole fractions.
211  */
212  vector_fp m_elementmolefracs;
213  vector_fp m_reswork;
214  vector_fp m_jwork1;
215  vector_fp m_jwork2;
216  /*
217  * Storage of the element compositions
218  * natom(k,m) = m_comp[k*m_mm+ m];
219  */
220  vector_fp m_comp;
221  doublereal m_temp, m_dens;
222  doublereal m_p0;
223  /**
224  * Index of the element id corresponding to the electric charge of each
225  * species. Equal to -1 if there is no such element id.
226  */
227  size_t m_eloc;
228 
229  vector_fp m_startSoln;
230 
231  vector_fp m_grt;
232  vector_fp m_mu_RT;
233  /**
234  * Dimensionless values of the gibbs free energy for the
235  * standard state of each species, at the temperature and
236  * pressure of the solution (the star standard state).
237  */
239  std::vector<size_t> m_component;
240 
241  /*
242  * element fractional cutoff, below which the element will be
243  * zeroed.
244  */
245  double m_elemFracCutoff;
246  bool m_doResPerturb;
247 
248 
249  std::vector<size_t> m_orderVectorElements;
250  std::vector<size_t> m_orderVectorSpecies;
251 
252 
253 };
254 
255 extern int ChemEquil_print_lvl;
256 
257 }
258 
259 #endif