Cantera  2.3.0
Domain1D.cpp
Go to the documentation of this file.
1 /**
2  * @file Domain1D.cpp
3  */
4 
5 // This file is part of Cantera. See License.txt in the top-level directory or
6 // at http://www.cantera.org/license.txt for license and copyright information.
7 
10 #include "cantera/base/ctml.h"
11 
12 using namespace std;
13 
14 namespace Cantera
15 {
16 
17 Domain1D::Domain1D(size_t nv, size_t points, double time) :
18  m_rdt(0.0),
19  m_nv(0),
20  m_time(time),
21  m_container(0),
22  m_index(npos),
23  m_type(0),
24  m_iloc(0),
25  m_jstart(0),
26  m_left(0),
27  m_right(0),
28  m_bw(-1),
29  m_force_full_update(false)
30 {
31  resize(nv, points);
32 }
33 
34 void Domain1D::resize(size_t nv, size_t np)
35 {
36  // if the number of components is being changed, then a
37  // new grid refiner is required.
38  if (nv != m_nv || !m_refiner) {
39  m_nv = nv;
40  m_refiner.reset(new Refiner(*this));
41  }
42  m_nv = nv;
43  m_td.resize(m_nv, 1);
44  m_name.resize(m_nv,"");
45  m_max.resize(m_nv, 0.0);
46  m_min.resize(m_nv, 0.0);
47  // Default error tolerances for all domains
48  m_rtol_ss.resize(m_nv, 1.0e-4);
49  m_atol_ss.resize(m_nv, 1.0e-9);
50  m_rtol_ts.resize(m_nv, 1.0e-4);
51  m_atol_ts.resize(m_nv, 1.0e-11);
52  m_points = np;
53  m_z.resize(np, 0.0);
54  m_slast.resize(m_nv * m_points, 0.0);
55  locate();
56 }
57 
58 std::string Domain1D::componentName(size_t n) const
59 {
60  if (m_name[n] != "") {
61  return m_name[n];
62  } else {
63  return fmt::format("component {}", n);
64  }
65 }
66 
67 size_t Domain1D::componentIndex(const std::string& name) const
68 {
69  for (size_t n = 0; n < nComponents(); n++) {
70  if (name == componentName(n)) {
71  return n;
72  }
73  }
74  throw CanteraError("Domain1D::componentIndex",
75  "no component named "+name);
76 }
77 
78 void Domain1D::setTransientTolerances(doublereal rtol, doublereal atol, size_t n)
79 {
80  if (n == npos) {
81  for (n = 0; n < m_nv; n++) {
82  m_rtol_ts[n] = rtol;
83  m_atol_ts[n] = atol;
84  }
85  } else {
86  m_rtol_ts[n] = rtol;
87  m_atol_ts[n] = atol;
88  }
89 }
90 
91 void Domain1D::setSteadyTolerances(doublereal rtol, doublereal atol, size_t n)
92 {
93  if (n == npos) {
94  for (n = 0; n < m_nv; n++) {
95  m_rtol_ss[n] = rtol;
96  m_atol_ss[n] = atol;
97  }
98  } else {
99  m_rtol_ss[n] = rtol;
100  m_atol_ss[n] = atol;
101  }
102 }
103 
105 {
106  if (m_container) {
107  m_container->jacobian().setAge(10000);
108  m_container->saveStats();
109  }
110 }
111 
112 void Domain1D::eval(size_t jg, doublereal* xg, doublereal* rg,
113  integer* mask, doublereal rdt)
114 {
115  warn_deprecated("Domain1D::eval",
116  "Derived classes should implement eval directly. The 'residual' method"
117  " will be removed after Cantera 2.3.");
118 
119  if (jg != npos && (jg + 1 < firstPoint() || jg > lastPoint() + 1)) {
120  return;
121  }
122 
123  // if evaluating a Jacobian, compute the steady-state residual
124  if (jg != npos) {
125  rdt = 0.0;
126  }
127 
128  // start of local part of global arrays
129  doublereal* x = xg + loc();
130  doublereal* rsd = rg + loc();
131  integer* diag = mask + loc();
132 
133  size_t jmin, jmax;
134  size_t jpt = jg - firstPoint();
135 
136  if (jg == npos) { // evaluate all points
137  jmin = 0;
138  jmax = m_points - 1;
139  } else { // evaluate points for Jacobian
140  jmin = std::max<size_t>(jpt, 1) - 1;
141  jmax = std::min(jpt+1,m_points-1);
142  }
143 
144  for (size_t j = jmin; j <= jmax; j++) {
145  if (j == 0 || j == m_points - 1) {
146  for (size_t i = 0; i < m_nv; i++) {
147  rsd[index(i,j)] = residual(x,i,j);
148  diag[index(i,j)] = 0;
149  }
150  } else {
151  for (size_t i = 0; i < m_nv; i++) {
152  rsd[index(i,j)] = residual(x,i,j)
153  - timeDerivativeFlag(i)*rdt*(value(x,i,j) - prevSoln(i,j));
154  diag[index(i,j)] = timeDerivativeFlag(i);
155  }
156  }
157  }
158 }
159 
160 XML_Node& Domain1D::save(XML_Node& o, const doublereal* const sol)
161 {
162  XML_Node& d = o.addChild("domain");
163  d.addAttribute("points", nPoints());
164  d.addAttribute("components", nComponents());
165  d.addAttribute("id", id());
166  addFloatArray(d, "abstol_transient", nComponents(), &m_atol_ts[0]);
167  addFloatArray(d, "reltol_transient", nComponents(), &m_rtol_ts[0]);
168  addFloatArray(d, "abstol_steady", nComponents(), &m_atol_ss[0]);
169  addFloatArray(d, "reltol_steady", nComponents(), &m_rtol_ss[0]);
170  return d;
171 }
172 
173 void Domain1D::restore(const XML_Node& dom, doublereal* soln, int loglevel)
174 {
175  vector_fp values;
176  vector<XML_Node*> nodes = dom.getChildren("floatArray");
177  for (size_t i = 0; i < nodes.size(); i++) {
178  string title = nodes[i]->attrib("title");
179  getFloatArray(*nodes[i], values, false);
180  if (values.size() != nComponents()) {
181  if (loglevel > 0) {
182  writelog("Warning: Domain1D::restore: Got an array of length {}"
183  " when one of length {} was expected. "
184  "Tolerances for individual species may not be preserved.\n",
185  values.size(), nComponents());
186  }
187  // The number of components will differ when restoring from a
188  // mechanism with a different number of species. Assuming that
189  // tolerances are the same for all species, we can just copy the
190  // tolerance from the last species.
191  if (!values.empty()) {
192  values.resize(nComponents(), values[values.size()-1]);
193  } else {
194  // If the tolerance vector is empty, just leave the defaults
195  // in place.
196  continue;
197  }
198  }
199  if (title == "abstol_transient") {
200  m_atol_ts = values;
201  } else if (title == "reltol_transient") {
202  m_rtol_ts = values;
203  } else if (title == "abstol_steady") {
204  m_atol_ss = values;
205  } else if (title == "reltol_steady") {
206  m_rtol_ss = values;
207  } else {
208  throw CanteraError("Domain1D::restore",
209  "Got an unexpected array, '" + title + "'");
210  }
211  }
212 }
213 
215 {
216  if (m_left) {
217  // there is a domain on the left, so the first grid point in this domain
218  // is one more than the last one on the left
219  m_jstart = m_left->lastPoint() + 1;
220 
221  // the starting location in the solution vector
222  m_iloc = m_left->loc() + m_left->size();
223  } else {
224  // this is the left-most domain
225  m_jstart = 0;
226  m_iloc = 0;
227  }
228  // if there is a domain to the right of this one, then repeat this for it
229  if (m_right) {
230  m_right->locate();
231  }
232 }
233 
234 void Domain1D::setupGrid(size_t n, const doublereal* z)
235 {
236  if (n > 1) {
237  resize(m_nv, n);
238  for (size_t j = 0; j < m_points; j++) {
239  m_z[j] = z[j];
240  }
241  }
242 }
243 
244 void Domain1D::showSolution(const doublereal* x)
245 {
246  size_t nn = m_nv/5;
247  for (size_t i = 0; i < nn; i++) {
248  writeline('-', 79, false, true);
249  writelog("\n z ");
250  for (size_t n = 0; n < 5; n++) {
251  writelog(" {:>10s} ", componentName(i*5 + n));
252  }
253  writeline('-', 79, false, true);
254  for (size_t j = 0; j < m_points; j++) {
255  writelog("\n {:10.4g} ", m_z[j]);
256  for (size_t n = 0; n < 5; n++) {
257  double v = value(x, i*5+n, j);
258  writelog(" {:10.4g} ", v);
259  }
260  }
261  writelog("\n");
262  }
263  size_t nrem = m_nv - 5*nn;
264  writeline('-', 79, false, true);
265  writelog("\n z ");
266  for (size_t n = 0; n < nrem; n++) {
267  writelog(" {:>10s} ", componentName(nn*5 + n));
268  }
269  writeline('-', 79, false, true);
270  for (size_t j = 0; j < m_points; j++) {
271  writelog("\n {:10.4g} ", m_z[j]);
272  for (size_t n = 0; n < nrem; n++) {
273  double v = value(x, nn*5+n, j);
274  writelog(" {:10.4g} ", v);
275  }
276  }
277  writelog("\n");
278 }
279 
280 void Domain1D::setProfile(const std::string& name, double* values, double* soln)
281 {
282  for (size_t n = 0; n < m_nv; n++) {
283  if (name == componentName(n)) {
284  for (size_t j = 0; j < m_points; j++) {
285  soln[index(n, j) + m_iloc] = values[j];
286  }
287  return;
288  }
289  }
290  throw CanteraError("Domain1D::setProfile", "unknown component: "+name);
291 }
292 
293 void Domain1D::_getInitialSoln(doublereal* x)
294 {
295  for (size_t j = 0; j < m_points; j++) {
296  for (size_t n = 0; n < m_nv; n++) {
297  x[index(n,j)] = initialValue(n,j);
298  }
299  }
300 }
301 
302 doublereal Domain1D::initialValue(size_t n, size_t j)
303 {
304  throw CanteraError("Domain1D::initialValue",
305  "base class method called!");
306  return 0.0;
307 }
308 
309 } // namespace
void addFloatArray(XML_Node &node, const std::string &title, const size_t n, const doublereal *const vals, const std::string &units, const std::string &type, const doublereal minval, const doublereal maxval)
This function adds a child node with the name, "floatArray", with a value consisting of a comma separ...
Definition: ctml.cpp:54
std::vector< XML_Node * > getChildren(const std::string &name) const
Get a vector of pointers to XML_Node containing all of the children of the current node which match t...
Definition: xml.cpp:864
size_t getFloatArray(const XML_Node &node, vector_fp &v, const bool convert, const std::string &unitsString, const std::string &nodeName)
This function reads the current node or a child node of the current node with the default name...
Definition: ctml.cpp:299
virtual void _getInitialSoln(doublereal *x)
Writes some or all initial solution values into the global solution array, beginning at the location ...
Definition: Domain1D.cpp:293
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
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.cpp:214
MultiJac & jacobian()
Return a reference to the Jacobian evaluator.
Definition: OneDim.cpp:101
size_t m_iloc
Starting location within the solution vector for unknowns that correspond to this domain...
Definition: Domain1D.h:572
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:411
void writelog(const std::string &fmt, const Args &... args)
Write a formatted message to the screen.
Definition: global.h:179
virtual doublereal residual(doublereal *x, size_t n, size_t j)
Definition: Domain1D.h:319
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:97
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:54
STL namespace.
vector_int m_td
Definition: Domain1D.h:582
virtual void restore(const XML_Node &dom, doublereal *soln, int loglevel)
Restore the solution for this domain from an XML_Node.
Definition: Domain1D.cpp:173
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:160
void setAge(int age)
Set the Jacobian age.
Definition: MultiJac.h:58
size_t lastPoint() const
The index of the last (i.e., right-most) grid point belonging to this domain.
Definition: Domain1D.h:419
virtual void resize(size_t nv, size_t np)
Definition: Domain1D.cpp:34
virtual void showSolution(const doublereal *x)
Print the solution.
Definition: Domain1D.cpp:244
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
void saveStats()
Save statistics on function and Jacobian evaluation, and reset the counters.
Definition: OneDim.cpp:137
virtual std::string componentName(size_t n) const
Name of the nth component. May be overloaded.
Definition: Domain1D.cpp:58
void addAttribute(const std::string &attrib, const std::string &value)
Add or modify an attribute of the current node.
Definition: xml.cpp:474
size_t componentIndex(const std::string &name) const
index of component with name name.
Definition: Domain1D.cpp:67
double prevSoln(size_t n, size_t j) const
Value of component n at point j in the previous solution.
Definition: Domain1D.h:454
size_t nComponents() const
Number of components at each grid point.
Definition: Domain1D.h:130
void setSteadyTolerances(doublereal rtol, doublereal atol, size_t n=npos)
Set tolerances for steady-state mode.
Definition: Domain1D.cpp:91
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:112
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
int timeDerivativeFlag(size_t n)
Definition: Domain1D.h:325
doublereal atol(size_t n)
Absolute tolerance of the nth component.
Definition: Domain1D.h:223
Refine Domain1D grids so that profiles satisfy adaptation tolerances.
Definition: refine.h:16
doublereal rtol(size_t n)
Relative tolerance of the nth component.
Definition: Domain1D.h:218
void needJacUpdate()
Definition: Domain1D.cpp:104
size_t nPoints() const
Number of grid points in this domain.
Definition: Domain1D.h:152
Namespace for the Cantera kernel.
Definition: application.cpp:29
void setTransientTolerances(doublereal rtol, doublereal atol, size_t n=npos)
Set tolerances for time-stepping mode.
Definition: Domain1D.cpp:78
virtual void setupGrid(size_t n, const doublereal *z)
called to set up initial grid, and after grid refinement
Definition: Domain1D.cpp:234
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:403
virtual doublereal initialValue(size_t n, size_t j)
Initial value of solution component n at grid point j.
Definition: Domain1D.cpp:302