Cantera  2.5.1
OneDim.h
Go to the documentation of this file.
1 /**
2  * @file OneDim.h
3  */
4 
5 // This file is part of Cantera. See License.txt in the top-level directory or
6 // at https://cantera.org/license.txt for license and copyright information.
7 
8 #ifndef CT_ONEDIM_H
9 #define CT_ONEDIM_H
10 
11 #include "Domain1D.h"
12 #include "MultiJac.h"
13 
14 namespace Cantera
15 {
16 
17 class Func1;
18 class MultiNewton;
19 
20 /**
21  * Container class for multiple-domain 1D problems. Each domain is
22  * represented by an instance of Domain1D.
23  * @ingroup onedim
24  */
25 class OneDim
26 {
27 public:
28  OneDim();
29 
30  //! Construct a OneDim container for the domains in the list *domains*.
31  OneDim(std::vector<Domain1D*> domains);
32  virtual ~OneDim();
33  OneDim(const OneDim&) = delete;
34  OneDim& operator=(const OneDim&) = delete;
35 
36  /// Add a domain. Domains are added left-to-right.
37  void addDomain(Domain1D* d);
38 
39  //! Return a reference to the Jacobian evaluator.
40  MultiJac& jacobian();
41 
42  /// Return a reference to the Newton iterator.
44 
45  /**
46  * Solve F(x) = 0, where F(x) is the multi-domain residual function.
47  * @param x0 Starting estimate of solution.
48  * @param x1 Final solution satisfying F(x1) = 0.
49  * @param loglevel Controls amount of diagnostic output.
50  */
51  int solve(doublereal* x0, doublereal* x1, int loglevel);
52 
53  /// Number of domains.
54  size_t nDomains() const {
55  return m_dom.size();
56  }
57 
58  /// Return a reference to domain i.
59  Domain1D& domain(size_t i) const {
60  return *m_dom[i];
61  }
62 
63  size_t domainIndex(const std::string& name);
64 
65  //! Check that the specified domain index is in range.
66  //! Throws an exception if n is greater than nDomains()-1
67  void checkDomainIndex(size_t n) const {
68  if (n >= m_dom.size()) {
69  throw IndexError("OneDim::checkDomainIndex", "domains", n,
70  m_dom.size()-1);
71  }
72  }
73 
74  //! Check that an array size is at least nDomains().
75  //! Throws an exception if nn is less than nDomains(). Used before calls
76  //! which take an array pointer.
77  void checkDomainArraySize(size_t nn) const {
78  if (m_dom.size() > nn) {
79  throw ArraySizeError("OneDim::checkDomainArraySize", nn,
80  m_dom.size());
81  }
82  }
83 
84  /// The index of the start of domain i in the solution vector.
85  size_t start(size_t i) const {
86  if (m_dom[i]->nComponents()) {
87  return m_dom[i]->loc();
88  } else {
89  // Special case for domains with no solution components to avoid
90  // spurious out-of-bounds memory access
91  return 0;
92  }
93  }
94 
95  /// Total solution vector length;
96  size_t size() const {
97  return m_size;
98  }
99 
100  /// Pointer to left-most domain (first added).
102  return m_dom[0];
103  }
104 
105  /// Pointer to right-most domain (last added).
107  return m_dom.back();
108  }
109 
110  /// Number of solution components at global point jg.
111  size_t nVars(size_t jg) {
112  return m_nvars[jg];
113  }
114 
115  //! Location in the solution vector of the first component of global point
116  //! jg.
117  size_t loc(size_t jg) {
118  return m_loc[jg];
119  }
120 
121  //! Return the domain, local point index, and component name for the i-th
122  //! component of the global solution vector
123  std::tuple<std::string, size_t, std::string> component(size_t i);
124 
125  /// Jacobian bandwidth.
126  size_t bandwidth() const {
127  return m_bw;
128  }
129 
130  /*!
131  * Initialize all domains. On the first call, this methods calls the init
132  * method of each domain, proceeding from left to right. Subsequent calls
133  * do nothing.
134  */
135  void init();
136 
137  /// Total number of points.
138  size_t points() {
139  return m_pts;
140  }
141 
142  /**
143  * Steady-state max norm (infinity norm) of the residual evaluated using
144  * solution x. On return, array r contains the steady-state residual
145  * values. Used only for diagnostic output.
146  */
147  doublereal ssnorm(doublereal* x, doublereal* r);
148 
149  /// Reciprocal of the time step.
150  doublereal rdt() const {
151  return m_rdt;
152  }
153 
154  //! Prepare for time stepping beginning with solution *x* and timestep *dt*.
155  void initTimeInteg(doublereal dt, doublereal* x);
156 
157  /// True if transient mode.
158  bool transient() const {
159  return (m_rdt != 0.0);
160  }
161 
162  /// True if steady mode.
163  bool steady() const {
164  return (m_rdt == 0.0);
165  }
166 
167  /*!
168  * Prepare to solve the steady-state problem. After invoking this method,
169  * subsequent calls to solve() will solve the steady-state problem. Sets
170  * the reciprocal of the time step to zero, and, if it was previously non-
171  * zero, signals that a new Jacobian will be needed.
172  */
173  void setSteadyMode();
174 
175  /**
176  * Evaluate the multi-domain residual function
177  *
178  * @param j if j != npos, only evaluate residual for points j-1, j,
179  * and j + 1; otherwise, evaluate at all grid points.
180  * @param x solution vector
181  * @param r on return, contains the residual vector
182  * @param rdt Reciprocal of the time step. if omitted, then
183  * the default value is used.
184  * @param count Set to zero to omit this call from the statistics
185  */
186  void eval(size_t j, double* x, double* r, doublereal rdt=-1.0,
187  int count = 1);
188 
189  //! Return a pointer to the domain global point *i* belongs to.
190  /*!
191  * The domains are scanned right-to-left, and the first one with starting
192  * location less or equal to i is returned.
193  */
194  Domain1D* pointDomain(size_t i);
195 
196  //! Call after one or more grids has changed size, e.g. after being refined.
197  virtual void resize();
198 
199  vector_int& transientMask() {
200  return m_mask;
201  }
202 
203  /*!
204  * Take time steps using Backward Euler.
205  *
206  * @param nsteps number of steps
207  * @param dt initial step size
208  * @param x current solution vector
209  * @param r solution vector after time stepping
210  * @param loglevel controls amount of printed diagnostics
211  * @returns size of last timestep taken
212  */
213  double timeStep(int nsteps, double dt, double* x,
214  double* r, int loglevel);
215 
216  void resetBadValues(double* x);
217 
218  //! Write statistics about the number of iterations and Jacobians at each
219  //! grid level
220  /*!
221  * @param printTime Boolean that indicates whether time should be printed
222  * out The default is true. It's turned off for test
223  * problems where we don't want to print any times
224  */
225  void writeStats(int printTime = 1);
226 
227  void save(const std::string& fname, std::string id,
228  const std::string& desc, doublereal* sol, int loglevel);
229 
230  // options
231  void setMinTimeStep(doublereal tmin) {
232  m_tmin = tmin;
233  }
234  void setMaxTimeStep(doublereal tmax) {
235  m_tmax = tmax;
236  }
237  void setTimeStepFactor(doublereal tfactor) {
238  m_tfactor = tfactor;
239  }
240 
241  //! Set the maximum number of timeteps allowed before successful
242  //! steady-state solve
243  void setMaxTimeStepCount(int nmax) {
244  m_nsteps_max = nmax;
245  }
246 
247  //! Return the maximum number of timeteps allowed before successful
248  //! steady-state solve
249  int maxTimeStepCount() const {
250  return m_nsteps_max;
251  }
252 
253  void setJacAge(int ss_age, int ts_age=-1);
254 
255  /**
256  * Save statistics on function and Jacobian evaluation, and reset the
257  * counters. Statistics are saved only if the number of Jacobian
258  * evaluations is greater than zero. The statistics saved are:
259  *
260  * - number of grid points
261  * - number of Jacobian evaluations
262  * - CPU time spent evaluating Jacobians
263  * - number of non-Jacobian function evaluations
264  * - CPU time spent evaluating functions
265  * - number of time steps
266  */
267  void saveStats();
268 
269  //! Clear saved statistics
270  void clearStats();
271 
272  //! Return total grid size in each call to solve()
273  const std::vector<size_t>& gridSizeStats() {
274  saveStats();
275  return m_gridpts;
276  }
277 
278  //! Return CPU time spent evaluating Jacobians in each call to solve()
280  saveStats();
281  return m_jacElapsed;
282  }
283 
284  //! Return CPU time spent on non-Jacobian function evaluations in each call
285  //! to solve()
287  saveStats();
288  return m_funcElapsed;
289  }
290 
291  //! Return number of Jacobian evaluations made in each call to solve()
293  saveStats();
294  return m_jacEvals;
295  }
296 
297  //! Return number of non-Jacobian function evaluations made in each call to
298  //! solve()
300  saveStats();
301  return m_funcEvals;
302  }
303 
304  //! Return number of time steps taken in each call to solve()
306  saveStats();
307  return m_timeSteps;
308  }
309 
310  //! Set a function that will be called every time #eval is called.
311  //! Can be used to provide keyboard interrupt support in the high-level
312  //! language interfaces.
313  void setInterrupt(Func1* interrupt) {
314  m_interrupt = interrupt;
315  }
316 
317  //! Set a function that will be called after each successful timestep. The
318  //! function will be called with the size of the timestep as the argument.
319  //! Intended to be used for observing solver progress for debugging
320  //! purposes.
321  void setTimeStepCallback(Func1* callback) {
322  m_time_step_callback = callback;
323  }
324 
325 protected:
326  void evalSSJacobian(doublereal* x, doublereal* xnew);
327 
328  doublereal m_tmin; //!< minimum timestep size
329  doublereal m_tmax; //!< maximum timestep size
330 
331  //! factor time step is multiplied by if time stepping fails ( < 1 )
332  doublereal m_tfactor;
333 
334  std::unique_ptr<MultiJac> m_jac; //!< Jacobian evaluator
335  std::unique_ptr<MultiNewton> m_newt; //!< Newton iterator
336  doublereal m_rdt; //!< reciprocal of time step
337  bool m_jac_ok; //!< if true, Jacobian is current
338 
339  size_t m_bw; //!< Jacobian bandwidth
340  size_t m_size; //!< solution vector size
341 
342  std::vector<Domain1D*> m_dom, m_connect, m_bulk;
343 
344  bool m_init;
345  std::vector<size_t> m_nvars;
346  std::vector<size_t> m_loc;
347  vector_int m_mask;
348  size_t m_pts;
349  doublereal m_solve_time;
350 
351  // options
352  int m_ss_jac_age, m_ts_jac_age;
353 
354  //! Function called at the start of every call to #eval.
356 
357  //! User-supplied function called after each successful timestep.
359 
360  //! Number of time steps taken in the current call to solve()
361  int m_nsteps;
362 
363  //! Maximum number of timesteps allowed per call to solve()
365 
366 private:
367  // statistics
368  int m_nevals;
369  doublereal m_evaltime;
370  std::vector<size_t> m_gridpts;
371  vector_int m_jacEvals;
372  vector_fp m_jacElapsed;
373  vector_int m_funcEvals;
374  vector_fp m_funcElapsed;
375 
376  //! Number of time steps taken in each call to solve() (e.g. for each
377  //! successive grid refinement)
379 };
380 
381 }
382 
383 #endif
Array size error.
Definition: ctexceptions.h:128
Base class for one-dimensional domains.
Definition: Domain1D.h:39
Base class for 'functor' classes that evaluate a function of one variable.
Definition: Func1.h:44
An array index is out of range.
Definition: ctexceptions.h:158
Class MultiJac evaluates the Jacobian of a system of equations defined by a residual function supplie...
Definition: MultiJac.h:23
Newton iterator for multi-domain, one-dimensional problems.
Definition: MultiNewton.h:20
Container class for multiple-domain 1D problems.
Definition: OneDim.h:26
size_t start(size_t i) const
The index of the start of domain i in the solution vector.
Definition: OneDim.h:85
int m_nsteps
Number of time steps taken in the current call to solve()
Definition: OneDim.h:361
void checkDomainIndex(size_t n) const
Check that the specified domain index is in range.
Definition: OneDim.h:67
vector_int m_timeSteps
Number of time steps taken in each call to solve() (e.g.
Definition: OneDim.h:378
doublereal m_rdt
reciprocal of time step
Definition: OneDim.h:336
size_t m_size
solution vector size
Definition: OneDim.h:340
const vector_int & jacobianCountStats()
Return number of Jacobian evaluations made in each call to solve()
Definition: OneDim.h:292
int m_nsteps_max
Maximum number of timesteps allowed per call to solve()
Definition: OneDim.h:364
virtual void resize()
Call after one or more grids has changed size, e.g. after being refined.
Definition: OneDim.cpp:168
std::unique_ptr< MultiJac > m_jac
Jacobian evaluator.
Definition: OneDim.h:334
void saveStats()
Save statistics on function and Jacobian evaluation, and reset the counters.
Definition: OneDim.cpp:137
size_t size() const
Total solution vector length;.
Definition: OneDim.h:96
doublereal ssnorm(doublereal *x, doublereal *r)
Steady-state max norm (infinity norm) of the residual evaluated using solution x.
Definition: OneDim.cpp:290
const vector_int & evalCountStats()
Return number of non-Jacobian function evaluations made in each call to solve()
Definition: OneDim.h:299
size_t loc(size_t jg)
Location in the solution vector of the first component of global point jg.
Definition: OneDim.h:117
Domain1D * left()
Pointer to left-most domain (first added).
Definition: OneDim.h:101
size_t nDomains() const
Number of domains.
Definition: OneDim.h:54
std::tuple< std::string, size_t, std::string > component(size_t i)
Return the domain, local point index, and component name for the i-th component of the global solutio...
Definition: OneDim.cpp:65
const vector_int & timeStepStats()
Return number of time steps taken in each call to solve()
Definition: OneDim.h:305
Domain1D * right()
Pointer to right-most domain (last added).
Definition: OneDim.h:106
doublereal m_tmin
minimum timestep size
Definition: OneDim.h:328
size_t bandwidth() const
Jacobian bandwidth.
Definition: OneDim.h:126
double timeStep(int nsteps, double dt, double *x, double *r, int loglevel)
Definition: OneDim.cpp:348
void eval(size_t j, double *x, double *r, doublereal rdt=-1.0, int count=1)
Evaluate the multi-domain residual function.
Definition: OneDim.cpp:258
const vector_fp & evalTimeStats()
Return CPU time spent on non-Jacobian function evaluations in each call to solve()
Definition: OneDim.h:286
void setTimeStepCallback(Func1 *callback)
Set a function that will be called after each successful timestep.
Definition: OneDim.h:321
Func1 * m_interrupt
Function called at the start of every call to eval.
Definition: OneDim.h:355
void checkDomainArraySize(size_t nn) const
Check that an array size is at least nDomains().
Definition: OneDim.h:77
void setMaxTimeStepCount(int nmax)
Set the maximum number of timeteps allowed before successful steady-state solve.
Definition: OneDim.h:243
void initTimeInteg(doublereal dt, doublereal *x)
Prepare for time stepping beginning with solution x and timestep dt.
Definition: OneDim.cpp:300
size_t nVars(size_t jg)
Number of solution components at global point jg.
Definition: OneDim.h:111
std::unique_ptr< MultiNewton > m_newt
Newton iterator.
Definition: OneDim.h:335
size_t m_bw
Jacobian bandwidth.
Definition: OneDim.h:339
bool m_jac_ok
if true, Jacobian is current
Definition: OneDim.h:337
const std::vector< size_t > & gridSizeStats()
Return total grid size in each call to solve()
Definition: OneDim.h:273
int maxTimeStepCount() const
Return the maximum number of timeteps allowed before successful steady-state solve.
Definition: OneDim.h:249
Domain1D * pointDomain(size_t i)
Return a pointer to the domain global point i belongs to.
Definition: OneDim.cpp:246
doublereal m_tmax
maximum timestep size
Definition: OneDim.h:329
void addDomain(Domain1D *d)
Add a domain. Domains are added left-to-right.
Definition: OneDim.cpp:79
size_t points()
Total number of points.
Definition: OneDim.h:138
MultiJac & jacobian()
Return a reference to the Jacobian evaluator.
Definition: OneDim.cpp:101
void writeStats(int printTime=1)
Write statistics about the number of iterations and Jacobians at each grid level.
Definition: OneDim.cpp:120
void clearStats()
Clear saved statistics.
Definition: OneDim.cpp:155
void setSteadyMode()
Definition: OneDim.cpp:319
const vector_fp & jacobianTimeStats()
Return CPU time spent evaluating Jacobians in each call to solve()
Definition: OneDim.h:279
Func1 * m_time_step_callback
User-supplied function called after each successful timestep.
Definition: OneDim.h:358
doublereal m_tfactor
factor time step is multiplied by if time stepping fails ( < 1 )
Definition: OneDim.h:332
int solve(doublereal *x0, doublereal *x1, int loglevel)
Solve F(x) = 0, where F(x) is the multi-domain residual function.
Definition: OneDim.cpp:224
Domain1D & domain(size_t i) const
Return a reference to domain i.
Definition: OneDim.h:59
bool steady() const
True if steady mode.
Definition: OneDim.h:163
MultiNewton & newton()
Return a reference to the Newton iterator.
Definition: OneDim.cpp:105
void setInterrupt(Func1 *interrupt)
Set a function that will be called every time eval is called.
Definition: OneDim.h:313
doublereal rdt() const
Reciprocal of the time step.
Definition: OneDim.h:150
std::vector< int > vector_int
Vector of ints.
Definition: ct_defs.h:182
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:180
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:264