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