Cantera  2.0
solveProb.h
Go to the documentation of this file.
1 /**
2  * @file solveProb.h
3  * Header file for implicit nonlinear solver with the option of a pseudotransient
4  * (see \ref numerics and class \link Cantera::solveProb solveProb\endlink).
5  */
6 
7 /*
8  * Copyright 2004 Sandia Corporation. Under the terms of Contract
9  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
10  * retains certain rights in this software.
11  * See file License.txt for licensing information.
12  */
13 
14 #ifndef SOLVEPROB_H
15 #define SOLVEPROB_H
16 /**
17  * @defgroup solverGroup Solvers for Equation Systems
18  */
19 
20 #include <vector>
21 #include "cantera/base/Array.h"
22 #include "ResidEval.h"
23 
24 //! Solution Methods
25 /*!
26  * Flag to specify the solution method
27  *
28  * 1: SOLVEPROB_INITIALIZE = This assumes that the initial guess supplied to the
29  * routine is far from the correct one. Substantial
30  * work plus transient time-stepping is to be expected
31  * to find a solution.
32  * 2: SOLVEPROB_RESIDUAL = Need to solve the surface problem in order to
33  * calculate the surface fluxes of gas-phase species.
34  * (Can expect a moderate change in the solution
35  * vector -> try to solve the system by direct
36  * methods
37  * with no damping first -> then, try time-stepping
38  * if the first method fails)
39  * A "time_scale" supplied here is used in the
40  * algorithm to determine when to shut off
41  * time-stepping.
42  * 3: SOLVEPROB_JACOBIAN = Calculation of the surface problem is due to the
43  * need for a numerical jacobian for the gas-problem.
44  * The solution is expected to be very close to the
45  * initial guess, and accuracy is needed.
46  * 4: SOLVEPROB_TRANSIENT = The transient calculation is performed here for an
47  * amount of time specified by "time_scale". It is
48  * not guaranteed to be time-accurate - just stable
49  * and fairly fast. The solution after del_t time is
50  * returned, whether it's converged to a steady
51  * state or not.
52  */
53 const int SOLVEPROB_INITIALIZE = 1;
54 const int SOLVEPROB_RESIDUAL = 2;
55 const int SOLVEPROB_JACOBIAN = 3;
56 const int SOLVEPROB_TRANSIENT = 4;
57 
58 
59 
60 
61 namespace Cantera
62 {
63 
64 
65 //! Method to solve a pseudo steady state of a nonlinear problem
66 /*!
67  * The following class handles the solution of a nonlinear problem.
68  *
69  * Res_ss(C) = - Res(C) = 0
70  *
71  * Optionally a pseudo transient algorithm may be used to relax the residual if
72  * it is available.
73  *
74  * Res_td(C) = dC/dt - Res(C) = 0;
75  *
76  * Res_ss(C) is the steady state residual to be solved. Res_td(C) is the
77  * time dependent residual which leads to the steady state residual.
78  *
79  *
80  * Solution Method
81  *
82  * This routine is typically used within a residual calculation in a large code.
83  * It's typically invoked millions of times for large calculations, and it must
84  * work every time. Therefore, requirements demand that it be robust but also
85  * efficient.
86  *
87  * The solution methodology is largely determined by the <TT>ifunc<\TT> parameter,
88  * that is input to the solution object. This parameter may have the following
89  * 4 values:
90  *
91  *
92  * 1: SOLVEPROB_INITIALIZE = This assumes that the initial guess supplied to the
93  * routine is far from the correct one. Substantial
94  * work plus transient time-stepping is to be expected
95  * to find a solution.
96  *
97  * 2: SOLVEPROB_RESIDUAL = Need to solve the nonlinear problem in order to
98  * calculate quantities for a residual calculation
99  * (Can expect a moderate change in the solution
100  * vector -> try to solve the system by direct methods
101  * with no damping first -> then, try time-stepping
102  * if the first method fails)
103  * A "time_scale" supplied here is used in the
104  * algorithm to determine when to shut off
105  * time-stepping.
106  *
107  * 3: SOLVEPROB_JACOBIAN = Calculation of the surface problem is due to the
108  * need for a numerical jacobian for the gas-problem.
109  * The solution is expected to be very close to the
110  * initial guess, and extra accuracy is needed because
111  * solution variables have been delta'd from
112  * nominal values to create jacobian entries.
113  *
114  * 4: SOLVEPROB_TRANSIENT = The transient calculation is performed here for an
115  * amount of time specified by "time_scale". It is
116  * not guaranteed to be time-accurate - just stable
117  * and fairly fast. The solution after del_t time is
118  * returned, whether it's converged to a steady
119  * state or not. This is a poor man's time stepping
120  * algorithm.
121  *
122  * Pseudo time stepping algorithm:
123  * The time step is determined from sdot[], so that the time step
124  * doesn't ever change the value of a variable by more than 100%.
125  *
126  * This algorithm does use a damped Newton's method to relax the equations.
127  * Damping is based on a "delta damping" technique. The solution unknowns
128  * are not allowed to vary too much between iterations.
129  *
130  *
131  * EXTRA_ACCURACY:A constant that is the ratio of the required update norm in
132  * this Newton iteration compared to that in the nonlinear solver.
133  * A value of 0.1 is used so surface species are safely overconverged.
134  *
135  * Functions called:
136  *----------------------------------------------------------------------------
137  *
138  * ct_dgetrf -- First half of LAPACK direct solve of a full Matrix
139  *
140  * ct_dgetrs -- Second half of LAPACK direct solve of a full matrix. Returns
141  * solution vector in the right-hand-side vector, resid.
142  *
143  *----------------------------------------------------------------------------
144  *
145  * @ingroup solverGroup
146  */
148 {
149 
150 public:
151 
152  //! Constructor for the object
153  /*!
154  * @param surfChemPtr Pointer to the ImplicitSurfChem object that
155  * defines the surface problem to be solved.
156  *
157  * @param bulkFunc Integer representing how the bulk phases
158  * should be handled. Currently, only the
159  * default value of BULK_ETCH is supported.
160  */
161  solveProb(ResidEval* resid);
162 
163  //! Destructor. Deletes the integrator.
164  virtual ~solveProb();
165 
166 private:
167 
168  //! Unimplemented private copy constructor
169  solveProb(const solveProb& right);
170 
171  //! Unimplemented private assignment operator
172  solveProb& operator=(const solveProb& right);
173 
174 public:
175 
176  //! Main routine that actually calculates the pseudo steady state
177  //! of the surface problem
178  /*!
179  * The actual converged solution is returned as part of the
180  * internal state of the InterfaceKinetics objects.
181  *
182  * @param ifunc Determines the type of solution algorithm to be
183  * used. Possible values are SOLVEPROB_INITIALIZE ,
184  * SOLVEPROB_RESIDUAL SOLVEPROB_JACOBIAN SOLVEPROB_TRANSIENT .
185  *
186  * @param time_scale Time over which to integrate the surface equations,
187  * where applicable
188  *
189  * @param reltol Relative tolerance to use
190  *
191  * @return Returns 1 if the surface problem is successfully solved.
192  * Returns -1 if the surface problem wasn't solved successfully.
193  * Note the actual converged solution is returned as part of the
194  * internal state of the InterfaceKinetics objects.
195  */
196  int solve(int ifunc, doublereal time_scale, doublereal reltol);
197 
198  //! Report the current state of the solution
199  /*!
200  * @param Report the solution vector for the nonlinear problem
201  */
202  virtual void reportState(doublereal* const CSoln) const;
203 
204  //! Set the bottom and top bounds on the solution vector
205  /*!
206  * The default is for the bottom is 0.0, while the default for the top is 1.0
207  *
208  * @param botBounds Vector of bottom bounds
209  * @param topBounds vector of top bounds
210  */
211  virtual void setBounds(const doublereal botBounds[], const doublereal topBounds[]);
212 
213 
214  void setAtol(const doublereal atol[]);
215  void setAtolConst(const doublereal atolconst);
216 
217 private:
218 
219  //! Printing routine that gets called at the start of every
220  //! invocation
221  virtual void print_header(int ioflag, int ifunc, doublereal time_scale,
222  doublereal reltol,
223  doublereal netProdRate[]);
224 
225 #ifdef DEBUG_SOLVEPROB
226 
227  virtual void printResJac(int ioflag, int neq, const Array2D& Jac,
228  doublereal resid[], doublereal wtResid[], doublereal norm);
229 #endif
230 
231  //! Printing routine that gets called after every iteration
232  virtual void printIteration(int ioflag, doublereal damp, size_t label_d, size_t label_t,
233  doublereal inv_t, doublereal t_real, int iter,
234  doublereal update_norm, doublereal resid_norm,
235  doublereal netProdRate[], doublereal CSolnSP[],
236  doublereal resid[],
237  doublereal wtSpecies[], size_t dim, bool do_time);
238 
239 
240  //! Print a summary of the solution
241  /*!
242  *
243  */
244  virtual void printFinal(int ioflag, doublereal damp, size_t label_d, size_t label_t,
245  doublereal inv_t, doublereal t_real, int iter,
246  doublereal update_norm, doublereal resid_norm,
247  doublereal netProdRateKinSpecies[], const doublereal CSolnSP[],
248  const doublereal resid[],
249  const doublereal wtSpecies[], const doublereal wtRes[],
250  size_t dim, bool do_time);
251 
252  //! Calculate a conservative delta T to use in a pseudo-steady state
253  //! algorithm
254  /*!
255  * This routine calculates a pretty conservative 1/del_t based
256  * on MAX_i(sdot_i/(X_i*SDen0)). This probably guarantees
257  * diagonal dominance.
258  *
259  * Small surface fractions are allowed to intervene in the del_t
260  * determination, no matter how small. This may be changed.
261  * Now minimum changed to 1.0e-12,
262  *
263  * Maximum time step set to time_scale.
264  *
265  * @param netProdRateSolnSP Output variable. Net production rate
266  * of all of the species in the solution vector.
267  * @param XMolSolnSP output variable.
268  * Mole fraction of all of the species in the solution vector
269  * @param label Output variable. Pointer to the value of the
270  * species index (kindexSP) that is controlling
271  * the time step
272  * @param label_old Output variable. Pointer to the value of the
273  * species index (kindexSP) that controlled
274  * the time step at the previous iteration
275  * @param label_factor Output variable. Pointer to the current
276  * factor that is used to indicate the same species
277  * is controlling the time step.
278  *
279  * @param ioflag Level of the output requested.
280  *
281  * @return Returns the 1. / delta T to be used on the next step
282  */
283  virtual doublereal calc_t(doublereal netProdRateSolnSP[], doublereal Csoln[],
284  size_t* label, size_t* label_old,
285  doublereal* label_factor, int ioflag);
286 
287  //! Calculate the solution and residual weights
288  /*!
289  * @param wtSpecies Weights to use for the soln unknowns. These
290  * are in concentration units
291  * @param wtResid Weights to sue for the residual unknowns.
292  *
293  * @param CSolnSP Solution vector for the surface problem
294  */
295  virtual void calcWeights(doublereal wtSpecies[], doublereal wtResid[],
296  const doublereal CSolnSP[]);
297 
298 #ifdef DEBUG_SOLVEPROB
299  //! Utility routine to print a header for high lvls of debugging
300  /*!
301  * @param ioflag Lvl of debugging
302  * @param damp lvl of damping
303  * @param inv_t Inverse of the value of delta T
304  * @param t_real Value of the time
305  * @param iter Iteration number
306  * @param do_time boolean indicating whether time stepping is taking
307  * place
308  */
309  virtual void printIterationHeader(int ioflag, doublereal damp,
310  doublereal inv_t, doublereal t_real, int iter,
311  bool do_time);
312 #endif
313 
314  //! Main Function evaluation
315  /*!
316  *
317  * @param resid output Vector of residuals, length = m_neq
318  * @param CSolnSP Vector of species concentrations, unknowns in the
319  * problem, length = m_neq
320  * @param CSolnSPOld Old Vector of species concentrations, unknowns in the
321  * problem, length = m_neq
322  * @param do_time Calculate a time dependent residual
323  * @param deltaT Delta time for time dependent problem.
324  */
325  virtual void fun_eval(doublereal* const resid, const doublereal* const CSolnSP,
326  const doublereal* const CSolnOldSP, const bool do_time, const doublereal deltaT);
327 
328  //! Main routine that calculates the current residual and Jacobian
329  /*!
330  * @param JacCol Vector of pointers to the tops of columns of the
331  * Jacobian to be evaluated.
332  * @param resid output Vector of residuals, length = m_neq
333  * @param CSolnSP Vector of species concentrations, unknowns in the
334  * problem, length = m_neq. These are tweaked in order
335  * to derive the columns of the jacobian.
336  * @param CSolnSPOld Old Vector of species concentrations, unknowns in the
337  * problem, length = m_neq
338  * @param do_time Calculate a time dependent residual
339  * @param deltaT Delta time for time dependent problem.
340  */
341  virtual void resjac_eval(std::vector<doublereal*>& JacCol, doublereal* resid,
342  doublereal* CSolnSP,
343  const doublereal* CSolnSPOld, const bool do_time,
344  const doublereal deltaT);
345 
346  //! This function calculates a damping factor for the Newton iteration update
347  //! vector, dxneg, to insure that all solution components stay within prescribed bounds
348  /*!
349  * The default for this class is that all solution components are bounded between zero and one.
350  * this is because the original unknowns were mole fractions and surface site fractions.
351  *
352  * dxneg[] = negative of the update vector.
353  *
354  * The constant "APPROACH" sets the fraction of the distance to the boundary
355  * that the step can take. If the full step would not force any fraction
356  * outside of the bounds, then Newton's method is mostly allowed to operate normally.
357  * There is also some solution damping employed.
358  *
359  * @param x Vector of the current solution components
360  * @param dxneg Vector of the negative of the full solution update vector.
361  * @param dim Size of the solution vector
362  * @param label return int, stating which solution component caused the most damping.
363  */
364  virtual doublereal calc_damping(doublereal x[], doublereal dxneg[], size_t dim, size_t* label);
365 
366  //! residual function pointer to be solved.
368 
369  //! Total number of equations to solve in the implicit problem.
370  /*!
371  * Note, this can be zero, and frequently is
372  */
373  size_t m_neq;
374 
375  //! m_atol is the absolute tolerance in real units.
377 
378  //! m_rtol is the relative error tolerance.
379  doublereal m_rtol;
380 
381  //! maximum value of the time step
382  /*!
383  * units = seconds
384  */
385  doublereal m_maxstep;
386 
387  //! Temporary vector with length MAX(1, m_neq)
389 
390  //! Temporary vector with length MAX(1, m_neq)
392 
393  //! Temporary vector with length MAX(1, m_neq)
395 
396  //! Temporary vector with length MAX(1, m_neq)
398 
399  //! Solution vector
400  /*!
401  * length MAX(1, m_neq)
402  */
404 
405  //! Saved initial solution vector
406  /*!
407  * length MAX(1, m_neq)
408  */
410 
411  //! Saved solution vector at the old time step
412  /*!
413  * length MAX(1, m_neq)
414  */
416 
417  //! Weights for the residual norm calculation
418  /*!
419  * length MAX(1, m_neq)
420  */
422 
423  //! Weights for the species concentrations norm calculation
424  /*!
425  * length MAX(1, m_neq)
426  */
428 
429  //! Residual for the surface problem
430  /*!
431  * The residual vector of length "dim" that, that has the value
432  * of "sdot" for surface species. The residuals for the bulk
433  * species are a function of the sdots for all species in the bulk
434  * phase. The last residual of each phase enforces {Sum(fractions)
435  * = 1}. After linear solve (dgetrf_ & dgetrs_), resid holds the
436  * update vector.
437  *
438  * length MAX(1, m_neq)
439  */
441 
442  //! pivots
443  /*!
444  * length MAX(1, m_neq)
445  */
447 
448  //! Vector of pointers to the top of the columns of the
449  //! jacobians
450  /*!
451  * The "dim" by "dim" computed Jacobian matrix for the
452  * local Newton's method.
453  */
454  std::vector<doublereal*> m_JacCol;
455 
456  //! Jacobian
457  /*!
458  * m_neq by m_neq computed Jacobian matrix for the
459  * local Newton's method.
460  */
462 
463  //! Top bounds for the solution vector
464  /*!
465  * This defaults to 1.0
466  */
468 
469  //! Bottom bounds for the solution vector
470  /*!
471  * This defaults to 0.0
472  */
474 
475 
476 public:
477  int m_ioflag;
478 };
479 }
480 #endif