Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Domain1D.h
Go to the documentation of this file.
1 /**
2  * @file Domain1D.h
3  */
4 /*
5  * Copyright 2002 California Institute of Technology
6  */
7 
8 #ifndef CT_DOMAIN1D_H
9 #define CT_DOMAIN1D_H
10 
13 #include "refine.h"
14 
15 namespace Cantera
16 {
17 
18 // domain types
19 const int cFlowType = 50;
20 const int cConnectorType = 100;
21 const int cSurfType = 102;
22 const int cInletType = 104;
23 const int cSymmType = 105;
24 const int cOutletType = 106;
25 const int cEmptyType = 107;
26 const int cOutletResType = 108;
27 const int cPorousType = 109;
28 
29 class MultiJac;
30 class OneDim;
31 class XML_Node;
32 
33 /**
34  * Base class for one-dimensional domains.
35  * @ingroup onedim
36  */
37 class Domain1D
38 {
39 public:
40  /**
41  * Constructor.
42  * @param nv Number of variables at each grid point.
43  * @param points Number of grid points.
44  * @param time (unused)
45  */
46  Domain1D(size_t nv=1, size_t points=1,
47  doublereal time = 0.0) :
48  m_rdt(0.0),
49  m_nv(0),
50  m_time(time),
51  m_container(0),
52  m_index(npos),
53  m_type(0),
54  m_iloc(0),
55  m_jstart(0),
56  m_left(0),
57  m_right(0),
58  m_id(""), m_desc(""),
59  m_refiner(0), m_bw(-1) {
60  resize(nv, points);
61  }
62 
63  virtual ~Domain1D() {
64  delete m_refiner;
65  }
66 
67  //! Domain type flag.
68  int domainType() {
69  return m_type;
70  }
71 
72  //! The left-to-right location of this domain.
73  size_t domainIndex() {
74  return m_index;
75  }
76 
77  //! True if the domain is a connector domain.
78  bool isConnector() {
79  return (m_type >= cConnectorType);
80  }
81 
82  //! The container holding this domain.
83  const OneDim& container() const {
84  return *m_container;
85  }
86 
87  /*!
88  * Specify the container object for this domain, and the
89  * position of this domain in the list.
90  */
91  void setContainer(OneDim* c, size_t index) {
92  m_container = c;
93  m_index = index;
94  }
95 
96  //! Set the Jacobian bandwidth. See the discussion of method bandwidth().
97  void setBandwidth(int bw = -1) {
98  m_bw = bw;
99  }
100 
101  //! Set the Jacobian bandwidth for this domain.
102  /**
103  * When class OneDim computes the bandwidth of the overall multi-domain
104  * problem (in OneDim::resize()), it calls this method for the bandwidth
105  * of each domain. If setBandwidth has not been called, then a negative
106  * bandwidth is returned, in which case OneDim assumes that this domain is
107  * dense -- that is, at each point, all components depend on the value of
108  * all other components at that point. In this case, the bandwidth is bw =
109  * 2*nComponents() - 1. However, if this domain contains some components
110  * that are uncoupled from other components at the same point, then this
111  * default bandwidth may greatly overestimate the true bandwidth, with a
112  * substantial penalty in performance. For such domains, use method
113  * setBandwidth to specify the bandwidth before passing this domain to the
114  * Sim1D or OneDim constructor.
115  */
116  size_t bandwidth() {
117  return m_bw;
118  }
119 
120  /*!
121  * Initialize. This method is called by OneDim::init() for
122  * each domain once at the beginning of a simulation. Base
123  * class method does nothing, but may be overloaded.
124  */
125  virtual void init() { }
126 
127  virtual void setInitialState(doublereal* xlocal = 0) {}
128  virtual void setState(size_t point, const doublereal* state, doublereal* x) {}
129 
130  /*!
131  * Resize the domain to have nv components and np grid points.
132  * This method is virtual so that subclasses can perform other
133  * actions required to resize the domain.
134  */
135  virtual void resize(size_t nv, size_t np) {
136  // if the number of components is being changed, then a
137  // new grid refiner is required.
138  if (nv != m_nv || !m_refiner) {
139  m_nv = nv;
140  delete m_refiner;
141  m_refiner = new Refiner(*this);
142  }
143  m_nv = nv;
144  m_td.resize(m_nv, 1);
145  m_name.resize(m_nv,"");
146  m_max.resize(m_nv, 0.0);
147  m_min.resize(m_nv, 0.0);
148  m_rtol_ss.resize(m_nv, 1.0e-8);
149  m_atol_ss.resize(m_nv, 1.0e-15);
150  m_rtol_ts.resize(m_nv, 1.0e-8);
151  m_atol_ts.resize(m_nv, 1.0e-15);
152  m_points = np;
153  m_z.resize(np, 0.0);
154  m_slast.resize(m_nv * m_points, 0.0);
155  locate();
156  }
157 
158  //! Return a reference to the grid refiner.
160  return *m_refiner;
161  }
162 
163  //! Number of components at each grid point.
164  size_t nComponents() const {
165  return m_nv;
166  }
167 
168  //! Check that the specified component index is in range
169  //! Throws an exception if n is greater than nComponents()-1
170  void checkComponentIndex(size_t n) const {
171  if (n >= m_nv) {
172  throw IndexError("checkComponentIndex", "points", n, m_nv-1);
173  }
174  }
175 
176  //! Check that an array size is at least nComponents()
177  //! Throws an exception if nn is less than nComponents(). Used before calls
178  //! which take an array pointer.
179  void checkComponentArraySize(size_t nn) const {
180  if (m_nv > nn) {
181  throw ArraySizeError("checkComponentArraySize", nn, m_nv);
182  }
183  }
184 
185  //! Number of grid points in this domain.
186  size_t nPoints() const {
187  return m_points;
188  }
189 
190  //! Check that the specified point index is in range
191  //! Throws an exception if n is greater than nPoints()-1
192  void checkPointIndex(size_t n) const {
193  if (n >= m_points) {
194  throw IndexError("checkPointIndex", "points", n, m_points-1);
195  }
196  }
197 
198  //! Check that an array size is at least nPoints()
199  //! Throws an exception if nn is less than nPoints(). Used before calls
200  //! which take an array pointer.
201  void checkPointArraySize(size_t nn) const {
202  if (m_points > nn) {
203  throw ArraySizeError("checkPointArraySize", nn, m_points);
204  }
205  }
206 
207  //! Name of the nth component. May be overloaded.
208  virtual std::string componentName(size_t n) const {
209  if (m_name[n] != "") {
210  return m_name[n];
211  } else {
212  return "component " + int2str(n);
213  }
214  }
215 
216  void setComponentName(size_t n, const std::string& name) {
217  m_name[n] = name;
218  }
219 
220  void setComponentType(size_t n, int ctype) {
221  if (ctype == 0) {
222  setAlgebraic(n);
223  }
224  }
225 
226  //! index of component with name \a name.
227  size_t componentIndex(const std::string& name) const {
228  size_t nc = nComponents();
229  for (size_t n = 0; n < nc; n++) {
230  if (name == componentName(n)) {
231  return n;
232  }
233  }
234  throw CanteraError("Domain1D::componentIndex",
235  "no component named "+name);
236  }
237 
238  void setBounds(size_t n, doublereal lower, doublereal upper) {
239  m_min[n] = lower;
240  m_max[n] = upper;
241  }
242 
243  //! Set tolerances for time-stepping mode
244  /*!
245  * @param rtol Relative tolerance
246  * @param atol Absolute tolerance
247  * @param n component index these tolerances apply to. If set to -1
248  * (the default), these tolerances will be applied to all solution
249  * components.
250  */
251  void setTransientTolerances(doublereal rtol, doublereal atol, size_t n=npos);
252 
253  //! Set tolerances for steady-state mode
254  /*!
255  * @param rtol Relative tolerance
256  * @param atol Absolute tolerance
257  * @param n component index these tolerances apply to. If set to -1
258  * (the default), these tolerances will be applied to all solution
259  * components.
260  */
261  void setSteadyTolerances(doublereal rtol, doublereal atol, size_t n=npos);
262 
263  //! Relative tolerance of the nth component.
264  doublereal rtol(size_t n) {
265  return (m_rdt == 0.0 ? m_rtol_ss[n] : m_rtol_ts[n]);
266  }
267 
268  //! Absolute tolerance of the nth component.
269  doublereal atol(size_t n) {
270  return (m_rdt == 0.0 ? m_atol_ss[n] : m_atol_ts[n]);
271  }
272 
273  //! Upper bound on the nth component.
274  doublereal upperBound(size_t n) const {
275  return m_max[n];
276  }
277 
278  //! Lower bound on the nth component
279  doublereal lowerBound(size_t n) const {
280  return m_min[n];
281  }
282 
283  /*!
284  * Prepare to do time stepping with time step dt. Copy the internally-
285  * stored solution at the last time step to array x0.
286  */
287  void initTimeInteg(doublereal dt, const doublereal* x0) {
288  std::copy(x0 + loc(), x0 + loc() + size(), m_slast.begin());
289  m_rdt = 1.0/dt;
290  }
291 
292  /*!
293  * Prepare to solve the steady-state problem. Set the internally-stored
294  * reciprocal of the time step to 0,0
295  */
296  void setSteadyMode() {
297  m_rdt = 0.0;
298  }
299 
300  //! True if in steady-state mode
301  bool steady() {
302  return (m_rdt == 0.0);
303  }
304 
305  //! True if not in steady-state mode
306  bool transient() {
307  return (m_rdt != 0.0);
308  }
309 
310  /*!
311  * Set this if something has changed in the governing
312  * equations (e.g. the value of a constant has been changed,
313  * so that the last-computed Jacobian is no longer valid.
314  */
315  void needJacUpdate();
316 
317  /*!
318  * Evaluate the steady-state residual at all points, even if in
319  * transient mode. Used only to print diagnostic output.
320  */
321  void evalss(doublereal* x, doublereal* r, integer* mask) {
322  eval(npos,x,r,mask,0.0);
323  }
324 
325  //! Evaluate the residual function at point j. If j == npos,
326  //! evaluate the residual function at all points.
327  /*!
328  * @param j Grid point at which to update the residual
329  * @param[in] x State vector
330  * @param[out] r residual vector
331  * @param[out] mask Boolean mask indicating whether each solution
332  * component has a time derivative (1) or not (0).
333  * @param[in] rdt Reciprocal of the timestep (`rdt=0` implies steady-
334  * state.)
335  */
336  virtual void eval(size_t j, doublereal* x, doublereal* r,
337  integer* mask, doublereal rdt=0.0);
338 
339  virtual doublereal residual(doublereal* x, size_t n, size_t j) {
340  throw CanteraError("Domain1D::residual","residual function must be overloaded in derived class "+id());
341  }
342 
343  int timeDerivativeFlag(size_t n) {
344  return m_td[n];
345  }
346  void setAlgebraic(size_t n) {
347  m_td[n] = 0;
348  }
349 
350  virtual void update(doublereal* x) {}
351 
352  doublereal time() const {
353  return m_time;
354  }
355  void incrementTime(doublereal dt) {
356  m_time += dt;
357  }
358  size_t index(size_t n, size_t j) const {
359  return m_nv*j + n;
360  }
361  doublereal value(const doublereal* x, size_t n, size_t j) const {
362  return x[index(n,j)];
363  }
364 
365  virtual void setJac(MultiJac* jac) {}
366 
367  //! Save the current solution for this domain into an XML_Node
368  /*!
369  * Base class version of the general domain1D save function. Derived
370  * classes should call the base class method in addition to saving their
371  * own data.
372  *
373  * @param o XML_Node to save the solution to.
374  * @param sol Current value of the solution vector.
375  * The object will pick out which part of the solution
376  * vector pertains to this object.
377  * @return XML_Node created to represent this domain
378  */
379  virtual XML_Node& save(XML_Node& o, const doublereal* const sol);
380 
381  //! Restore the solution for this domain from an XML_Node
382  /*!
383  * Base class version of the general Domain1D restore function. Derived
384  * classes should call the base class method in addition to restoring
385  * their own data.
386  *
387  * @param dom XML_Node for this domain
388  * @param soln Current value of the solution vector, local to this object.
389  * @param loglevel 0 to suppress all output; 1 to show warnings; 2 for
390  * verbose output
391  */
392  virtual void restore(const XML_Node& dom, doublereal* soln, int loglevel);
393 
394  size_t size() const {
395  return m_nv*m_points;
396  }
397 
398  /**
399  * Find the index of the first grid point in this domain, and
400  * the start of its variables in the global solution vector.
401  */
402  void locate() {
403 
404  if (m_left) {
405  // there is a domain on the left, so the first grid point
406  // in this domain is one more than the last one on the left
407  m_jstart = m_left->lastPoint() + 1;
408 
409  // the starting location in the solution vector
410  m_iloc = m_left->loc() + m_left->size();
411  } else {
412  // this is the left-most domain
413  m_jstart = 0;
414  m_iloc = 0;
415  }
416  // if there is a domain to the right of this one, then
417  // repeat this for it
418  if (m_right) {
419  m_right->locate();
420  }
421  }
422 
423  /**
424  * Location of the start of the local solution vector in the global
425  * solution vector,
426  */
427  virtual size_t loc(size_t j = 0) const {
428  return m_iloc;
429  }
430 
431  /**
432  * The index of the first (i.e., left-most) grid point
433  * belonging to this domain.
434  */
435  size_t firstPoint() const {
436  return m_jstart;
437  }
438 
439  /**
440  * The index of the last (i.e., right-most) grid point
441  * belonging to this domain.
442  */
443  size_t lastPoint() const {
444  return m_jstart + m_points - 1;
445  }
446 
447  /**
448  * Set the left neighbor to domain 'left.' Method 'locate' is called to
449  * update the global positions of this domain and all those to its right.
450  */
452  m_left = left;
453  locate();
454  }
455 
456  //! Set the right neighbor to domain 'right.'
458  m_right = right;
459  }
460 
461  //! Append domain 'right' to this one, and update all links.
463  linkRight(right);
464  right->linkLeft(this);
465  }
466 
467  //! Return a pointer to the left neighbor.
468  Domain1D* left() const {
469  return m_left;
470  }
471 
472  //! Return a pointer to the right neighbor.
473  Domain1D* right() const {
474  return m_right;
475  }
476 
477  //! Value of component n at point j in the previous solution.
478  double prevSoln(size_t n, size_t j) const {
479  return m_slast[m_nv*j + n];
480  }
481 
482  //! Specify an identifying tag for this domain.
483  void setID(const std::string& s) {
484  m_id = s;
485  }
486 
487  std::string id() const {
488  if (m_id != "") {
489  return m_id;
490  } else {
491  return std::string("domain ") + int2str(m_index);
492  }
493  }
494 
495  //! Specify descriptive text for this domain.
496  void setDesc(const std::string& s) {
497  m_desc = s;
498  }
499  const std::string& desc() {
500  return m_desc;
501  }
502 
503  virtual void getTransientMask(integer* mask) {}
504 
505  virtual void showSolution_s(std::ostream& s, const doublereal* x) {}
506 
507  //! Print the solution.
508  virtual void showSolution(const doublereal* x);
509 
510  doublereal z(size_t jlocal) const {
511  return m_z[jlocal];
512  }
513  doublereal zmin() const {
514  return m_z[0];
515  }
516  doublereal zmax() const {
517  return m_z[m_points - 1];
518  }
519 
520  void setProfile(const std::string& name, doublereal* values, doublereal* soln) {
521  for (size_t n = 0; n < m_nv; n++) {
522  if (name == componentName(n)) {
523  for (size_t j = 0; j < m_points; j++) {
524  soln[index(n, j) + m_iloc] = values[j];
525  }
526  return;
527  }
528  }
529  throw CanteraError("Domain1D::setProfile",
530  "unknown component: "+name);
531  }
532 
533  vector_fp& grid() {
534  return m_z;
535  }
536  const vector_fp& grid() const {
537  return m_z;
538  }
539  doublereal grid(size_t point) {
540  return m_z[point];
541  }
542 
543  //! called to set up initial grid, and after grid refinement
544  virtual void setupGrid(size_t n, const doublereal* z);
545 
546  /**
547  * Writes some or all initial solution values into the global
548  * solution array, beginning at the location pointed to by
549  * x. This method is called by the Sim1D constructor, and
550  * allows default values or ones that have been set locally
551  * prior to installing this domain into the container to be
552  * written to the global solution vector.
553  */
554  virtual void _getInitialSoln(doublereal* x);
555 
556  //! Initial value of solution component \a n at grid point \a j.
557  virtual doublereal initialValue(size_t n, size_t j);
558 
559  /**
560  * In some cases, a domain may need to set parameters that
561  * depend on the initial solution estimate. In such cases, the
562  * parameters may be set in method _finalize. This method is
563  * called just before the Newton solver is called, and the x
564  * array is guaranteed to be the local solution vector for
565  * this domain that will be used as the initial guess. If no
566  * such parameters need to be set, then method _finalize does
567  * not need to be overloaded.
568  */
569  virtual void _finalize(const doublereal* x) {}
570 
571 protected:
572  doublereal m_rdt;
573  size_t m_nv;
574  size_t m_points;
575  vector_fp m_slast;
576  doublereal m_time;
577  vector_fp m_max;
578  vector_fp m_min;
579  vector_fp m_rtol_ss, m_rtol_ts;
580  vector_fp m_atol_ss, m_atol_ts;
581  vector_fp m_z;
582  OneDim* m_container;
583  size_t m_index;
584  int m_type;
585 
586  //! Starting location within the solution vector for unknowns that
587  //! correspond to this domain
588  /*!
589  * Remember there may be multiple domains associated with this problem
590  */
591  size_t m_iloc;
592 
593  size_t m_jstart;
594 
595  Domain1D* m_left, *m_right;
596 
597  //! Identity tag for the domain
598  std::string m_id;
599  std::string m_desc;
600  Refiner* m_refiner;
601  vector_int m_td;
602  std::vector<std::string> m_name;
603  int m_bw;
604 };
605 }
606 
607 #endif
Container class for multiple-domain 1D problems.
Definition: OneDim.h:21
Array size error.
Definition: ctexceptions.h:154
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Definition: stringUtils.cpp:39
virtual void _getInitialSoln(doublereal *x)
Writes some or all initial solution values into the global solution array, beginning at the location ...
Definition: Domain1D.cpp:206
size_t componentIndex(const std::string &name) const
index of component with name name.
Definition: Domain1D.h:227
size_t nPoints() const
Number of grid points in this domain.
Definition: Domain1D.h:186
Domain1D * left() const
Return a pointer to the left neighbor.
Definition: Domain1D.h:468
void locate()
Find the index of the first grid point in this domain, and the start of its variables in the global s...
Definition: Domain1D.h:402
void setSteadyMode()
Definition: Domain1D.h:296
void checkPointIndex(size_t n) const
Check that the specified point index is in range Throws an exception if n is greater than nPoints()-1...
Definition: Domain1D.h:192
size_t m_iloc
Starting location within the solution vector for unknowns that correspond to this domain...
Definition: Domain1D.h:591
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
size_t firstPoint() const
The index of the first (i.e., left-most) grid point belonging to this domain.
Definition: Domain1D.h:435
virtual std::string componentName(size_t n) const
Name of the nth component. May be overloaded.
Definition: Domain1D.h:208
virtual size_t loc(size_t j=0) const
Location of the start of the local solution vector in the global solution vector,.
Definition: Domain1D.h:427
void setContainer(OneDim *c, size_t index)
Definition: Domain1D.h:91
virtual void restore(const XML_Node &dom, doublereal *soln, int loglevel)
Restore the solution for this domain from an XML_Node.
Definition: Domain1D.cpp:108
virtual XML_Node & save(XML_Node &o, const doublereal *const sol)
Save the current solution for this domain into an XML_Node.
Definition: Domain1D.cpp:95
void linkLeft(Domain1D *left)
Set the left neighbor to domain 'left.
Definition: Domain1D.h:451
std::vector< int > vector_int
Vector of ints.
Definition: ct_defs.h:159
void checkComponentIndex(size_t n) const
Check that the specified component index is in range Throws an exception if n is greater than nCompon...
Definition: Domain1D.h:170
void setBandwidth(int bw=-1)
Set the Jacobian bandwidth. See the discussion of method bandwidth().
Definition: Domain1D.h:97
size_t nComponents() const
Number of components at each grid point.
Definition: Domain1D.h:164
Base class for one-dimensional domains.
Definition: Domain1D.h:37
std::string m_id
Identity tag for the domain.
Definition: Domain1D.h:598
size_t bandwidth()
Set the Jacobian bandwidth for this domain.
Definition: Domain1D.h:116
size_t lastPoint() const
The index of the last (i.e., right-most) grid point belonging to this domain.
Definition: Domain1D.h:443
void setID(const std::string &s)
Specify an identifying tag for this domain.
Definition: Domain1D.h:483
doublereal lowerBound(size_t n) const
Lower bound on the nth component.
Definition: Domain1D.h:279
virtual void _finalize(const doublereal *x)
In some cases, a domain may need to set parameters that depend on the initial solution estimate...
Definition: Domain1D.h:569
virtual void showSolution(const doublereal *x)
Print the solution.
Definition: Domain1D.cpp:159
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
Domain1D * right() const
Return a pointer to the right neighbor.
Definition: Domain1D.h:473
virtual void resize(size_t nv, size_t np)
Definition: Domain1D.h:135
void setDesc(const std::string &s)
Specify descriptive text for this domain.
Definition: Domain1D.h:496
Refiner & refiner()
Return a reference to the grid refiner.
Definition: Domain1D.h:159
doublereal upperBound(size_t n) const
Upper bound on the nth component.
Definition: Domain1D.h:274
void evalss(doublereal *x, doublereal *r, integer *mask)
Definition: Domain1D.h:321
void checkPointArraySize(size_t nn) const
Check that an array size is at least nPoints() Throws an exception if nn is less than nPoints()...
Definition: Domain1D.h:201
int domainType()
Domain type flag.
Definition: Domain1D.h:68
size_t domainIndex()
The left-to-right location of this domain.
Definition: Domain1D.h:73
Domain1D(size_t nv=1, size_t points=1, doublereal time=0.0)
Constructor.
Definition: Domain1D.h:46
void setSteadyTolerances(doublereal rtol, doublereal atol, size_t n=npos)
Set tolerances for steady-state mode.
Definition: Domain1D.cpp:29
virtual void eval(size_t j, doublereal *x, doublereal *r, integer *mask, doublereal rdt=0.0)
Evaluate the residual function at point j.
Definition: Domain1D.cpp:50
void append(Domain1D *right)
Append domain 'right' to this one, and update all links.
Definition: Domain1D.h:462
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:157
bool steady()
True if in steady-state mode.
Definition: Domain1D.h:301
Contains declarations for string manipulation functions within Cantera.
void linkRight(Domain1D *right)
Set the right neighbor to domain 'right.'.
Definition: Domain1D.h:457
void checkComponentArraySize(size_t nn) const
Check that an array size is at least nComponents() Throws an exception if nn is less than nComponents...
Definition: Domain1D.h:179
doublereal atol(size_t n)
Absolute tolerance of the nth component.
Definition: Domain1D.h:269
const OneDim & container() const
The container holding this domain.
Definition: Domain1D.h:83
Refine Domain1D grids so that profiles satisfy adaptation tolerances.
Definition: refine.h:13
doublereal rtol(size_t n)
Relative tolerance of the nth component.
Definition: Domain1D.h:264
An array index is out of range.
Definition: ctexceptions.h:184
void needJacUpdate()
Definition: Domain1D.cpp:42
bool isConnector()
True if the domain is a connector domain.
Definition: Domain1D.h:78
double prevSoln(size_t n, size_t j) const
Value of component n at point j in the previous solution.
Definition: Domain1D.h:478
void setTransientTolerances(doublereal rtol, doublereal atol, size_t n=npos)
Set tolerances for time-stepping mode.
Definition: Domain1D.cpp:16
virtual void setupGrid(size_t n, const doublereal *z)
called to set up initial grid, and after grid refinement
Definition: Domain1D.cpp:149
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
virtual void init()
Definition: Domain1D.h:125
virtual doublereal initialValue(size_t n, size_t j)
Initial value of solution component n at grid point j.
Definition: Domain1D.cpp:215
void initTimeInteg(doublereal dt, const doublereal *x0)
Definition: Domain1D.h:287