21 : m_tmin(1.0e-16), m_tmax(1e8), m_tfactor(0.5),
22 m_rdt(0.0), m_jac_ok(false),
24 m_init(false), m_pts(0),
25 m_ss_jac_age(20), m_ts_jac_age(20),
26 m_interrupt(0), m_time_step_callback(0),
27 m_nsteps(0), m_nsteps_max(500),
28 m_nevals(0), m_evaltime(0.0)
30 m_newt.reset(
new MultiNewton(1));
33OneDim::OneDim(vector<Domain1D*> domains) :
34 m_tmin(1.0e-16), m_tmax(1e8), m_tfactor(0.5),
35 m_rdt(0.0), m_jac_ok(false),
38 m_ss_jac_age(20), m_ts_jac_age(20),
39 m_interrupt(0), m_time_step_callback(0),
40 m_nsteps(0), m_nsteps_max(500),
41 m_nevals(0), m_evaltime(0.0)
45 for (
size_t i = 0; i < domains.size(); i++) {
56size_t OneDim::domainIndex(
const std::string& name)
58 for (
size_t n = 0; n < m_dom.size(); n++) {
59 if (
domain(n).
id() == name) {
63 throw CanteraError(
"OneDim::domainIndex",
"no domain named >>"+name+
"<<");
74 size_t offset = i -
start(n);
84 size_t n = m_dom.size();
86 m_dom.back()->append(d);
91 m_connect.push_back(d);
111void OneDim::setJacAge(
int ss_age,
int ts_age)
113 m_ss_jac_age = ss_age;
115 m_ts_jac_age = ts_age;
117 m_ts_jac_age = m_ss_jac_age;
124 writelog(
"\nStatistics:\n\n Grid Timesteps Functions Time Jacobians Time\n");
125 size_t n = m_gridpts.size();
126 for (
size_t i = 0; i < n; i++) {
128 writelog(
"{:5d} {:5d} {:6d} {:9.4f} {:5d} {:9.4f}\n",
129 m_gridpts[i],
m_timeSteps[i], m_funcEvals[i], m_funcElapsed[i],
130 m_jacEvals[i], m_jacElapsed[i]);
132 writelog(
"{:5d} {:5d} {:6d} NA {:5d} NA\n",
133 m_gridpts[i],
m_timeSteps[i], m_funcEvals[i], m_jacEvals[i]);
141 int nev =
m_jac->nEvals();
142 if (nev > 0 && m_nevals > 0) {
143 m_gridpts.push_back(m_pts);
144 m_jacEvals.push_back(
m_jac->nEvals());
145 m_jacElapsed.push_back(
m_jac->elapsedTime());
146 m_funcEvals.push_back(m_nevals);
148 m_funcElapsed.push_back(m_evaltime);
160 m_jacElapsed.clear();
162 m_funcElapsed.clear();
179 for (
size_t i = 0; i <
nDomains(); i++) {
184 for (
size_t n = 0; n < np; n++) {
185 m_nvars.push_back(nv);
203 size_t bw2 = m_dom[i-1]->bandwidth();
205 bw2 = m_dom[i-1]->nComponents();
214 m_mask.resize(
size());
220 for (
size_t i = 0; i <
nDomains(); i++) {
221 m_dom[i]->setJac(
m_jac.get());
229 m_jac->eval(x, xnew, 0.0);
234 return m_newt->solve(x, xnew, *
this, *
m_jac, loglevel);
237void OneDim::evalSSJacobian(doublereal* x, doublereal* xnew)
239 doublereal rdt_save =
m_rdt;
243 m_jac->eval(x, xnew, 0.0);
259void OneDim::eval(
size_t j,
double* x,
double* r, doublereal rdt,
int count)
261 clock_t t0 = clock();
267 fill(m_mask.begin(), m_mask.end(), 0);
274 for (
const auto& d : m_bulk) {
275 d->eval(j, x, r, m_mask.data(),
rdt);
279 for (
const auto& d : m_connect) {
280 d->eval(j, x, r, m_mask.data(),
rdt);
285 clock_t t1 = clock();
286 m_evaltime += double(t1 - t0)/CLOCKS_PER_SEC;
295 for (
size_t i = 0; i <
m_size; i++) {
296 ss = std::max(fabs(r[i]),ss);
303 doublereal rdt_old =
m_rdt;
350 doublereal* r,
int loglevel)
355 debuglog(
"\n\n step size (s) log10(ss) \n", loglevel);
356 debuglog(
"===============================\n", loglevel);
359 int successiveFailures = 0;
363 doublereal ss =
ssnorm(x, r);
364 writelog(
" {:>4d} {:10.4g} {:10.4g}", n, dt, log10(ss));
371 int m =
solve(x, r, loglevel-1);
376 successiveFailures = 0;
387 dt = std::min(dt,
m_tmax);
390 "Took maximum number of timesteps allowed ({}) without "
394 successiveFailures++;
397 debuglog(
"...failure.\n", loglevel);
398 if (successiveFailures > 2) {
401 successiveFailures = 0;
406 "Time integration failed.");
417void OneDim::resetBadValues(
double* x)
419 for (
auto dom : m_dom) {
420 dom->resetBadValues(x);
424void OneDim::save(
const std::string& fname, std::string
id,
425 const std::string& desc, doublereal* sol,
430 struct tm* newtime = localtime(&aclock);
432 XML_Node root(
"ctml");
435 root.build(fin, fname);
437 XML_Node* same_ID = root.findID(
id);
439 same_ID->parent()->removeChild(same_ID);
443 XML_Node& sim = root.addChild(
"simulation");
444 sim.addAttribute(
"id",
id);
445 addString(sim,
"timestamp",asctime(newtime));
450 Domain1D* d =
left();
457 throw CanteraError(
"OneDim::save",
"could not open file "+fname);
461 debuglog(
"Solution saved to file "+fname+
" as solution "+
id+
".\n", loglevel);
464AnyMap OneDim::serialize(
const double* soln)
const
467 for (
size_t i = 0; i < m_dom.size(); i++) {
468 state[m_dom[i]->id()] = m_dom[i]->serialize(soln +
start(i));
Base class for exceptions thrown by Cantera classes.
Base class for one-dimensional domains.
size_t nComponents() const
Number of components at each grid point.
size_t bandwidth()
Set the Jacobian bandwidth for this domain.
Domain1D * left() const
Return a pointer to the left neighbor.
void setContainer(OneDim *c, size_t index)
Specify the container object for this domain, and the position of this domain in the list.
size_t nPoints() const
Number of grid points in this domain.
virtual std::string componentName(size_t n) const
Name of the nth component. May be overloaded.
void initTimeInteg(doublereal dt, const doublereal *x0)
Prepare to do time stepping with time step dt.
Domain1D * right() const
Return a pointer to the right neighbor.
void setSteadyMode()
Prepare to solve the steady-state problem.
virtual size_t loc(size_t j=0) const
Location of the start of the local solution vector in the global solution vector,.
virtual doublereal eval(doublereal t) const
Evaluate the function.
Class MultiJac evaluates the Jacobian of a system of equations defined by a residual function supplie...
Newton iterator for multi-domain, one-dimensional problems.
void setOptions(int maxJacAge=5)
Set options.
size_t start(size_t i) const
The index of the start of domain i in the solution vector.
int m_nsteps
Number of time steps taken in the current call to solve()
vector_int m_timeSteps
Number of time steps taken in each call to solve() (for example, for each successive grid refinement)
doublereal m_rdt
reciprocal of time step
size_t m_size
solution vector size
int m_nsteps_max
Maximum number of timesteps allowed per call to solve()
virtual void resize()
Call after one or more grids has changed size, for example after being refined.
std::unique_ptr< MultiJac > m_jac
Jacobian evaluator.
void saveStats()
Save statistics on function and Jacobian evaluation, and reset the counters.
size_t size() const
Total solution vector length;.
doublereal ssnorm(doublereal *x, doublereal *r)
Steady-state max norm (infinity norm) of the residual evaluated using solution x.
size_t nDomains() const
Number of domains.
Domain1D * right()
Pointer to right-most domain (last added).
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...
doublereal m_tmin
minimum timestep size
double timeStep(int nsteps, double dt, double *x, double *r, int loglevel)
void eval(size_t j, double *x, double *r, doublereal rdt=-1.0, int count=1)
Evaluate the multi-domain residual function.
Func1 * m_interrupt
Function called at the start of every call to eval.
void initTimeInteg(doublereal dt, doublereal *x)
Prepare for time stepping beginning with solution x and timestep dt.
std::unique_ptr< MultiNewton > m_newt
Newton iterator.
size_t m_bw
Jacobian bandwidth.
bool m_jac_ok
if true, Jacobian is current
Domain1D * pointDomain(size_t i)
Return a pointer to the domain global point i belongs to.
doublereal m_tmax
maximum timestep size
void addDomain(Domain1D *d)
Add a domain. Domains are added left-to-right.
MultiJac & jacobian()
Return a reference to the Jacobian evaluator.
void writeStats(int printTime=1)
Write statistics about the number of iterations and Jacobians at each grid level.
void clearStats()
Clear saved statistics.
Func1 * m_time_step_callback
User-supplied function called after each successful timestep.
doublereal m_tfactor
factor time step is multiplied by if time stepping fails ( < 1 )
Domain1D & domain(size_t i) const
Return a reference to domain i.
int solve(doublereal *x0, doublereal *x1, int loglevel)
Solve F(x) = 0, where F(x) is the multi-domain residual function.
Domain1D * left()
Pointer to left-most domain (first added).
MultiNewton & newton()
Return a reference to the Newton iterator.
doublereal rdt() const
Reciprocal of the time step.
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.
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"
const double Tiny
Small number to compare differences of mole fractions against.
void debuglog(const std::string &msg, int loglevel)
Write a message to the log only if loglevel > 0.
void addString(XML_Node &node, const std::string &titleString, const std::string &valueString, const std::string &typeString="")
This function adds a child node with the name string with a string value to the current node.