12#include "cantera/oneD/refine.h"
32 for (
size_t n = 0; n <
nDomains(); n++) {
43 for (
size_t dom=0; dom<
nDomains(); dom++) {
46 for (
size_t comp=0; comp<ncomp; comp++) {
58 "Index out of bounds: {} > {}", iloc,
m_x.size());
62doublereal
Sim1D::value(
size_t dom,
size_t comp,
size_t localPoint)
const
66 "Index out of bounds: {} > {}", iloc,
m_x.size());
70doublereal Sim1D::workValue(
size_t dom,
size_t comp,
size_t localPoint)
const
74 "Index out of bounds: {} > {}", iloc,
m_x.size());
81 if (pos.front() != 0.0 || pos.back() != 1.0) {
83 "`pos` vector must span the range [0, 1]. Got a vector spanning "
84 "[{}, {}] instead.", pos.front(), pos.back());
87 doublereal z0 = d.zmin();
88 doublereal z1 = d.zmax();
89 for (
size_t n = 0; n < d.
nPoints(); n++) {
91 double frac = (zpt - z0)/(z1 - z0);
97void Sim1D::save(
const std::string& fname,
const std::string&
id,
98 const std::string& desc,
int loglevel)
100 size_t dot = fname.find_last_of(
".");
102 if (extension !=
"yml" && extension !=
"yaml") {
103 OneDim::save(fname,
id, desc,
m_x.data(), loglevel);
109 if (ifstream(fname).good()) {
112 bool preexisting = data.hasKey(
id);
115 data[id] = serialize(
m_x.data());
118 data[id][
"description"] = desc;
119 data[id][
"generator"] =
"Cantera Sim1D";
120 data[id][
"cantera-version"] = CANTERA_VERSION;
126 struct tm* newtime = localtime(&aclock);
130 data[id][
"description"].setLoc(-6, 0);
131 data[id][
"generator"].setLoc(-5, 0);
132 data[id][
"cantera-version"].setLoc(-4, 0);
133 data[id][
"git-commit"].setLoc(-3, 0);
134 data[id][
"date"].setLoc(-2, 0);
138 data[id].setLoc(INT_MAX, 0);
142 std::ofstream out(fname);
143 out << data.toYamlString();
146 writelog(
"Solution saved to file {} as solution '{}'.\n", fname,
id);
150void Sim1D::saveResidual(
const std::string& fname,
const std::string&
id,
151 const std::string& desc,
int loglevel)
158 save(fname,
id, desc, loglevel);
165 size_t dot = fname.find_last_of(
".");
167 if (extension ==
"yml" || extension ==
"yaml") {
171 "No solution with id '{}'",
id);
173 const auto& state = root[id];
174 for (
auto dom : m_dom) {
175 if (!state.hasKey(dom->id())) {
177 "Saved state '{}' does not contain a domain named '{}'.",
180 dom->resize(dom->nComponents(), state[dom->id()][
"points"].asInt());
184 for (
auto dom : m_dom) {
185 dom->restore(state[dom->id()].as<
AnyMap>(),
m_x.data() + dom->loc(),
194 throw CanteraError(
"Sim1D::restore",
"No solution with id = "+
id);
199 throw CanteraError(
"Sim1D::restore",
"Solution does not contain the "
200 " correct number of domains. Found {} expected {}.\n",
203 for (
size_t m = 0; m <
nDomains(); m++) {
205 if (loglevel > 0 && xd[m]->attrib(
"id") != dom.id()) {
206 warn_user(
"Sim1D::restore",
"Domain names do not match: "
207 "'{} and '{}'", (*xd[m])[
"id"], dom.id());
213 for (
size_t m = 0; m <
nDomains(); m++) {
223 for (
size_t n = 0; n < np; n++) {
228void Sim1D::showSolution(ostream& s)
230 for (
size_t n = 0; n <
nDomains(); n++) {
237void Sim1D::showSolution()
239 for (
size_t n = 0; n <
nDomains(); n++) {
242 +
" <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
251 throw CanteraError(
"Sim1D::restoreTimeSteppingSolution",
252 "No successful time steps taken on this grid.");
261 "No successful steady state solution");
264 for (
size_t n = 0; n <
nDomains(); n++) {
270void Sim1D::getInitialSoln()
272 for (
size_t n = 0; n <
nDomains(); n++) {
279 for (
size_t n = 0; n <
nDomains(); n++) {
284void Sim1D::setTimeStep(
double stepsize,
size_t n,
const int* tsteps)
288 for (
size_t i = 0; i < n; i++) {
299 }
else if (m > -10) {
303 "ERROR: OneDim::solve returned m = {}", m);
312 int soln_number = -1;
315 while (new_points > 0) {
321 writeline(
'.', 78,
true,
true);
327 debuglog(
"Attempt Newton solution of steady-state problem...", loglevel);
334 for (
size_t mm = 1; mm <
nDomains(); mm+=2) {
347 save(
"debug_sim1d.yaml",
"debug",
348 "After successful Newton solve");
351 saveResidual(
"debug_sim1d.yaml",
"residual",
352 "After successful Newton solve");
359 save(
"debug_sim1d.yaml",
"debug",
360 "After unsuccessful Newton solve");
363 saveResidual(
"debug_sim1d.yaml",
"residual",
364 "After unsuccessful Newton solve");
367 writelog(
"Take {} timesteps ", nsteps);
373 save(
"debug_sim1d.yaml",
"debug",
"After timestepping");
376 saveResidual(
"debug_sim1d.yaml",
"residual",
377 "After timestepping");
381 writelog(
" {:10.4g} {:10.4g}\n", dt,
390 dt = std::min(dt,
m_tmax);
394 writeline(
'.', 78,
true,
true);
401 new_points =
refine(loglevel);
407 if (new_points && loglevel > 6) {
408 save(
"debug_sim1d.yaml",
"debug",
"After regridding");
410 if (new_points && loglevel > 7) {
411 saveResidual(
"debug_sim1d.yaml",
"residual",
415 debuglog(
"grid refinement disabled.\n", loglevel);
423 int ianalyze, np = 0;
425 std::vector<size_t> dsize;
430 for (
size_t n = 0; n <
nDomains(); n++) {
438 ianalyze = r.analyze(d.grid().size(), d.grid().data(), &
m_x[
start(n)]);
447 np += r.nNewPoints();
452 size_t nstart = znew.size();
453 for (
size_t m = 0; m < npnow; m++) {
454 if (r.keepPoint(m)) {
456 znew.push_back(d.grid(m));
459 for (
size_t i = 0; i < comp; i++) {
460 xnew.push_back(
value(n, i, m));
466 if (r.newPointNeeded(m) && m + 1 < npnow) {
468 double zmid = 0.5*(d.grid(m) + d.grid(m+1));
469 znew.push_back(zmid);
474 for (
size_t i = 0; i < comp; i++) {
475 double xmid = 0.5*(
value(n, i, m) +
value(n, i, m+1));
476 xnew.push_back(xmid);
481 writelog(
"refine: discarding point at {}\n", d.grid(m));
485 dsize.push_back(znew.size() - nstart);
492 size_t gridstart = 0, gridsize;
493 for (
size_t n = 0; n <
nDomains(); n++) {
497 gridstart += gridsize;
512 double z1 = 0.0, z2 = 0.0;
513 std::vector<size_t> dsize;
515 for (
size_t n = 0; n <
nDomains(); n++) {
518 size_t mfixed =
npos;
523 size_t nstart = znew.size();
524 if (d_free && d_free->
domainType() == cFreeFlow) {
525 for (
size_t m = 0; m < npnow - 1; m++) {
526 bool fixedpt =
false;
527 double t1 =
value(n, 2, m);
528 double t2 =
value(n, 2, m + 1);
530 double thresh = min(1., 1.e-1 * (t2 - t1));
533 if (fabs(t - t1) <= thresh) {
536 }
else if (fabs(t2 - t) <= thresh) {
539 }
else if ((t1 < t) && (t < t2)) {
541 zfixed = (z1 - z2) / (t1 - t2) * (t - t2) + z2;
554 for (
size_t m = 0; m < npnow; m++) {
556 znew.push_back(d.grid(m));
559 for (
size_t i = 0; i < comp; i++) {
560 xnew.push_back(
value(n, i, m));
564 znew.push_back(zfixed);
566 double interp_factor = (zfixed - z2) / (z1 - z2);
569 for (
size_t i = 0; i < comp; i++) {
570 double xmid = interp_factor*(
value(n, i, m) -
value(n, i, m+1)) +
value(n,i,m+1);
571 xnew.push_back(xmid);
575 dsize.push_back(znew.size() - nstart);
581 size_t gridstart = 0;
582 for (
size_t n = 0; n <
nDomains(); n++) {
584 size_t gridsize = dsize[n];
586 gridstart += gridsize;
599 double t_fixed = std::numeric_limits<double>::quiet_NaN();
600 for (
size_t n = 0; n <
nDomains(); n++) {
612 double z_fixed = std::numeric_limits<double>::quiet_NaN();
613 for (
size_t n = 0; n <
nDomains(); n++) {
624 double slope,
double curve,
double prune)
630 for (
size_t n = 0; n <
nDomains(); n++) {
644 "Must specify domain to get criteria from");
654 for (
size_t n = 0; n <
nDomains(); n++) {
667 for (
size_t n = 0; n <
nDomains(); n++) {
685void Sim1D::evalSSJacobian()
687 OneDim::evalSSJacobian(
m_x.data(),
m_xnew.data());
692 for (
auto& D : m_dom) {
693 D->forceFullUpdate(
true);
696 for (
auto& D : m_dom) {
697 D->forceFullUpdate(
false);
703 for (
size_t i = 0; i <
size(); i++) {
704 size_t j1 = (i > bw) ? i - bw : 0;
705 size_t j2 = (i + bw >=
size()) ?
size() - 1: i + bw;
706 for (
size_t j = j1; j <= j2; j++) {
707 Jt(j,i) =
m_jac->value(i,j);
A map of string keys to values whose type can vary at runtime.
static void clearCachedFile(const std::string &filename)
Remove the specified file from the input cache if it is present.
static AnyMap fromYamlFile(const std::string &name, const std::string &parent_name="")
Create an AnyMap from a YAML file.
bool hasKey(const std::string &key) const
Returns true if the map contains an item named key.
A class for banded matrices, involving matrix inversion processes.
int solve(const doublereal *const b, doublereal *const x)
Solve the matrix problem Ax = b.
doublereal & value(size_t i, size_t j)
Return a changeable reference to element (i,j).
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.
virtual void showSolution(const doublereal *x)
Print the solution.
virtual void _finalize(const doublereal *x)
In some cases, a domain may need to set parameters that depend on the initial solution estimate.
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.
virtual void resize(size_t nv, size_t np)
Refiner & refiner()
Return a reference to the grid refiner.
virtual void restore(const XML_Node &dom, doublereal *soln, int loglevel)
Restore the solution for this domain from an XML_Node.
virtual void _getInitialSoln(doublereal *x)
Writes some or all initial solution values into the global solution array, beginning at the location ...
int domainType()
Domain type flag.
virtual void setupGrid(size_t n, const doublereal *z)
called to set up initial grid, and after grid refinement
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.
void setOptions(int maxJacAge=5)
Set options.
Container class for multiple-domain 1D problems.
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()
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.
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.
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...
size_t bandwidth() const
Jacobian bandwidth.
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.
doublereal m_tmax
maximum timestep size
MultiJac & jacobian()
Return a reference to the Jacobian evaluator.
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.
MultiNewton & newton()
Return a reference to the Newton iterator.
Refine Domain1D grids so that profiles satisfy adaptation tolerances.
size_t maxPoints() const
Returns the maximum number of points allowed in the domain.
vector_fp getCriteria()
Get the grid refinement criteria.
void setMaxPoints(int npmax)
Set the maximum number of points allowed in the domain.
void setCriteria(doublereal ratio=10.0, doublereal slope=0.8, doublereal curve=0.8, doublereal prune=-0.1)
Set grid refinement criteria.
void setGridMin(double gridmin)
Set the minimum allowable spacing between adjacent grid points [m].
vector_fp m_xlast_ss
the solution vector after the last successful steady-state solve (stored before grid refinement)
virtual void resize()
Call after one or more grids has changed size, for example after being refined.
void restoreTimeSteppingSolution()
Set the current solution vector to the last successful time-stepping solution.
vector_fp m_x
the solution vector
double fixedTemperatureLocation()
Return location of the point where temperature is fixed.
void finalize()
Calls method _finalize in each domain.
vector_int m_steps
array of number of steps to take before re-attempting the steady-state solution
int refine(int loglevel=0)
Refine the grid in all domains.
double fixedTemperature()
Return temperature at the point used to fix the flame location.
vector_fp m_xlast_ts
the solution vector after the last successful timestepping
vector_fp m_xnew
a work array used to hold the residual or the new solution
void setProfile(size_t dom, size_t comp, const vector_fp &pos, const vector_fp &values)
Specify a profile for one component of one domain.
vector_fp getRefineCriteria(int dom)
Get the grid refinement criteria.
void setMaxGridPoints(int dom, int npoints)
Set the maximum number of grid points in the domain.
int setFixedTemperature(double t)
Add node for fixed temperature point of freely propagating flame.
int newtonSolve(int loglevel)
Wrapper around the Newton solver.
std::vector< vector_fp > m_grid_last_ss
the grids for each domain after the last successful steady-state solve (stored before grid refinement...
void restore(const std::string &fname, const std::string &id, int loglevel=2)
Initialize the solution with a previously-saved solution.
void solveAdjoint(const double *b, double *lambda)
Solve the equation .
Func1 * m_steady_callback
User-supplied function called after a successful steady-state solve.
void restoreSteadySolution()
Set the current solution vector and grid to the last successful steady- state solution.
size_t maxGridPoints(size_t dom)
Get the maximum number of grid points in this domain.
void showSolution(std::ostream &s)
Print to stream s the current solution for all domains.
doublereal value(size_t dom, size_t comp, size_t localPoint) const
Get one entry in the solution vector.
void setValue(size_t dom, size_t comp, size_t localPoint, doublereal value)
Set a single value in the solution vector.
Sim1D()
Default constructor.
void setGridMin(int dom, double gridmin)
Set the minimum grid spacing in the specified domain(s).
void setRefineCriteria(int dom=-1, double ratio=10.0, double slope=0.8, double curve=0.8, double prune=-0.1)
Set grid refinement criteria.
void setFlatProfile(size_t dom, size_t comp, doublereal v)
Set component 'comp' of domain 'dom' to value 'v' at all points.
doublereal m_tstep
timestep
void setInitialGuess(const std::string &component, vector_fp &locs, vector_fp &vals)
Set initial guess for one component for all domains.
This class represents 1D flow domains that satisfy the one-dimensional similarity solution for chemic...
double m_tfixed
Temperature at the point used to fix the flame location.
double m_zfixed
Location of the point where temperature is fixed.
Class XML_Node is a tree-based representation of the contents of an XML file.
void build(const std::string &filename)
Populate the XML tree from an input file.
XML_Node * findID(const std::string &id, const int depth=100) const
This routine carries out a recursive search for an XML node based on the XML element attribute "id".
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...
Header for a file containing miscellaneous numerical functions.
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
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"
doublereal linearInterp(doublereal x, const vector_fp &xpts, const vector_fp &fpts)
Linearly interpolate a function defined on a discrete grid.
int intValue(const std::string &val)
Translate a string into one integer value.
doublereal dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
void debuglog(const std::string &msg, int loglevel)
Write a message to the log only if loglevel > 0.
std::string toLowerCopy(const std::string &input)
Convert to lower case.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
std::string gitCommit()
Returns the hash of the git commit from which Cantera was compiled, if known.
void warn_user(const std::string &method, const std::string &msg, const Args &... args)
Print a user warning raised from method as CanteraWarning.
int solve(DenseMatrix &A, double *b, size_t nrhs=1, size_t ldb=0)
Solve Ax = b. Array b is overwritten on exit with x.
std::string stripnonprint(const std::string &s)
Strip non-printing characters wherever they are.
Contains declarations for string manipulation functions within Cantera.
Classes providing support for XML data files.