Go to the documentation of this file.
22 Sim1D::Sim1D(vector<Domain1D*>& domains) :
29 for (
size_t n = 0; n <
nDomains(); n++) {
40 for (
size_t dom=0; dom<
nDomains(); dom++) {
43 for (
size_t comp=0; comp<ncomp; comp++) {
51 void Sim1D::setValue(
size_t dom,
size_t comp,
size_t localPoint, doublereal value)
55 "Index out of bounds: {} > {}", iloc,
m_x.size());
59 doublereal
Sim1D::value(
size_t dom,
size_t comp,
size_t localPoint)
const
63 "Index out of bounds: {} > {}", iloc,
m_x.size());
67 doublereal Sim1D::workValue(
size_t dom,
size_t comp,
size_t localPoint)
const
71 "Index out of bounds: {} > {}", iloc,
m_x.size());
78 if (pos.front() != 0.0 || pos.back() != 1.0) {
80 "`pos` vector must span the range [0, 1]. Got a vector spanning "
81 "[{}, {}] instead.", pos.front(), pos.back());
84 doublereal z0 = d.zmin();
85 doublereal z1 = d.zmax();
86 for (
size_t n = 0; n < d.
nPoints(); n++) {
88 double frac = (zpt - z0)/(z1 - z0);
94 void Sim1D::save(
const std::string& fname,
const std::string&
id,
95 const std::string& desc,
int loglevel)
97 OneDim::save(fname,
id, desc,
m_x.data(), loglevel);
100 void Sim1D::saveResidual(
const std::string& fname,
const std::string&
id,
101 const std::string& desc,
int loglevel)
105 OneDim::save(fname,
id, desc, &res[0], loglevel);
116 throw CanteraError(
"Sim1D::restore",
"No solution with id = "+
id);
121 throw CanteraError(
"Sim1D::restore",
"Solution does not contain the "
122 " correct number of domains. Found {} expected {}.\n",
125 for (
size_t m = 0; m <
nDomains(); m++) {
127 if (loglevel > 0 && xd[m]->attrib(
"id") != dom.id()) {
128 warn_user(
"Sim1D::restore",
"Domain names do not match: "
129 "'{} and '{}'", (*xd[m])[
"id"], dom.id());
135 for (
size_t m = 0; m <
nDomains(); m++) {
144 for (
size_t n = 0; n < np; n++) {
149 void Sim1D::showSolution(ostream& s)
151 for (
size_t n = 0; n <
nDomains(); n++) {
158 void Sim1D::showSolution()
160 for (
size_t n = 0; n <
nDomains(); n++) {
163 +
" <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
172 throw CanteraError(
"Sim1D::restoreTimeSteppingSolution",
173 "No successful time steps taken on this grid.");
182 "No successful steady state solution");
185 for (
size_t n = 0; n <
nDomains(); n++) {
191 void Sim1D::getInitialSoln()
193 for (
size_t n = 0; n <
nDomains(); n++) {
200 for (
size_t n = 0; n <
nDomains(); n++) {
205 void Sim1D::setTimeStep(
double stepsize,
size_t n,
const int* tsteps)
209 for (
size_t i = 0; i < n; i++) {
220 }
else if (m > -10) {
224 "ERROR: OneDim::solve returned m = {}", m);
228 void Sim1D::solve(
int loglevel,
bool refine_grid)
233 int soln_number = -1;
236 while (new_points > 0) {
242 writeline(
'.', 78,
true,
true);
248 debuglog(
"Attempt Newton solution of steady-state problem...", loglevel);
255 for (
size_t mm = 1; mm <
nDomains(); mm+=2) {
268 save(
"debug_sim1d.xml",
"debug",
269 "After successful Newton solve");
272 saveResidual(
"debug_sim1d.xml",
"residual",
273 "After successful Newton solve");
280 save(
"debug_sim1d.xml",
"debug",
281 "After unsuccessful Newton solve");
284 saveResidual(
"debug_sim1d.xml",
"residual",
285 "After unsuccessful Newton solve");
288 writelog(
"Take {} timesteps ", nsteps);
294 save(
"debug_sim1d.xml",
"debug",
"After timestepping");
297 saveResidual(
"debug_sim1d.xml",
"residual",
298 "After timestepping");
302 writelog(
" {:10.4g} {:10.4g}\n", dt,
311 dt = std::min(dt,
m_tmax);
315 writeline(
'.', 78,
true,
true);
322 new_points =
refine(loglevel);
328 if (new_points && loglevel > 6) {
329 save(
"debug_sim1d.xml",
"debug",
"After regridding");
331 if (new_points && loglevel > 7) {
332 saveResidual(
"debug_sim1d.xml",
"residual",
336 debuglog(
"grid refinement disabled.\n", loglevel);
344 int ianalyze, np = 0;
346 std::vector<size_t> dsize;
351 for (
size_t n = 0; n <
nDomains(); n++) {
359 ianalyze = r.analyze(d.grid().size(), d.grid().data(), &
m_x[
start(n)]);
368 np += r.nNewPoints();
373 size_t nstart = znew.size();
374 for (
size_t m = 0; m < npnow; m++) {
375 if (r.keepPoint(m)) {
377 znew.push_back(d.grid(m));
380 for (
size_t i = 0; i < comp; i++) {
381 xnew.push_back(
value(n, i, m));
387 if (r.newPointNeeded(m) && m + 1 < npnow) {
389 double zmid = 0.5*(d.grid(m) + d.grid(m+1));
390 znew.push_back(zmid);
395 for (
size_t i = 0; i < comp; i++) {
396 double xmid = 0.5*(
value(n, i, m) +
value(n, i, m+1));
397 xnew.push_back(xmid);
402 writelog(
"refine: discarding point at {}\n", d.grid(m));
406 dsize.push_back(znew.size() - nstart);
413 size_t gridstart = 0, gridsize;
414 for (
size_t n = 0; n <
nDomains(); n++) {
418 gridstart += gridsize;
433 double z1 = 0.0, z2 = 0.0;
434 std::vector<size_t> dsize;
436 for (
size_t n = 0; n <
nDomains(); n++) {
439 size_t mfixed =
npos;
444 size_t nstart = znew.size();
445 if (d_free && d_free->
domainType() == cFreeFlow) {
446 for (
size_t m = 0; m < npnow - 1; m++) {
447 bool fixedpt =
false;
448 double t1 =
value(n, 2, m);
449 double t2 =
value(n, 2, m + 1);
451 double thresh = min(1., 1.e-1 * (t2 - t1));
454 if (fabs(t - t1) <= thresh) {
457 }
else if (fabs(t2 - t) <= thresh) {
460 }
else if ((t1 < t) && (t < t2)) {
462 zfixed = (z1 - z2) / (t1 - t2) * (t - t2) + z2;
475 for (
size_t m = 0; m < npnow; m++) {
477 znew.push_back(d.grid(m));
480 for (
size_t i = 0; i < comp; i++) {
481 xnew.push_back(
value(n, i, m));
485 znew.push_back(zfixed);
487 double interp_factor = (zfixed - z2) / (z1 - z2);
490 for (
size_t i = 0; i < comp; i++) {
491 double xmid = interp_factor*(
value(n, i, m) -
value(n, i, m+1)) +
value(n,i,m+1);
492 xnew.push_back(xmid);
496 dsize.push_back(znew.size() - nstart);
502 size_t gridstart = 0;
503 for (
size_t n = 0; n <
nDomains(); n++) {
505 size_t gridsize = dsize[n];
507 gridstart += gridsize;
520 double t_fixed = std::numeric_limits<double>::quiet_NaN();
521 for (
size_t n = 0; n <
nDomains(); n++) {
533 double z_fixed = std::numeric_limits<double>::quiet_NaN();
534 for (
size_t n = 0; n <
nDomains(); n++) {
545 double slope,
double curve,
double prune)
551 for (
size_t n = 0; n <
nDomains(); n++) {
565 "Must specify domain to get criteria from");
575 for (
size_t n = 0; n <
nDomains(); n++) {
588 for (
size_t n = 0; n <
nDomains(); n++) {
606 void Sim1D::evalSSJacobian()
608 OneDim::evalSSJacobian(
m_x.data(),
m_xnew.data());
613 for (
auto& D : m_dom) {
614 D->forceFullUpdate(
true);
617 for (
auto& D : m_dom) {
618 D->forceFullUpdate(
false);
624 for (
size_t i = 0; i <
size(); i++) {
625 size_t j1 = (i > bw) ? i - bw : 0;
626 size_t j2 = (i + bw >=
size()) ?
size() - 1: i + bw;
627 for (
size_t j = j1; j <= j2; j++) {
628 Jt(j,i) =
m_jac->value(i,j);
void finalize()
Calls method _finalize in each domain.
int setFixedTemperature(double t)
Add node for fixed temperature point of freely propagating flame.
virtual void resize()
Call after one or more grids has changed size, e.g. after being refined.
void setFlatProfile(size_t dom, size_t comp, doublereal v)
Set component 'comp' of domain 'dom' to value 'v' at all points.
void setGridMin(double gridmin)
Set the minimum allowable spacing between adjacent grid points [m].
Container class for multiple-domain 1D problems.
doublereal m_tstep
timestep
vector_fp m_xnew
a work array used to hold the residual or the new solution
void writelog(const std::string &fmt, const Args &... args)
Write a formatted message to the screen.
virtual void resize()
Call after one or more grids has changed size, e.g. after being refined.
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
double fixedTemperatureLocation()
Return location of the point where temperature is fixed.
Refine Domain1D grids so that profiles satisfy adaptation tolerances.
doublereal value(size_t dom, size_t comp, size_t localPoint) const
Get one entry in the solution vector.
MultiJac & jacobian()
Return a reference to the Jacobian evaluator.
size_t nDomains() const
Number of domains.
virtual size_t loc(size_t j=0) const
Location of the start of the local solution vector in the global solution vector,.
std::unique_ptr< MultiJac > m_jac
Jacobian evaluator.
void restoreSteadySolution()
Set the current solution vector and grid to the last successful steady- state solution.
doublereal linearInterp(doublereal x, const vector_fp &xpts, const vector_fp &fpts)
Linearly interpolate a function defined on a discrete grid.
virtual void restore(const XML_Node &dom, doublereal *soln, int loglevel)
Restore the solution for this domain from an XML_Node.
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.
double fixedTemperature()
Return temperature at the point used to fix the flame location.
void build(const std::string &filename)
Populate the XML tree from an input file.
doublereal ssnorm(doublereal *x, doublereal *r)
Steady-state max norm (infinity norm) of the residual evaluated using solution x.
void setCriteria(doublereal ratio=10.0, doublereal slope=0.8, doublereal curve=0.8, doublereal prune=-0.1)
Set grid refinement criteria.
size_t size() const
Total solution vector length;.
int refine(int loglevel=0)
Refine the grid in all domains.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
void setMaxGridPoints(int dom, int npoints)
Set the maximum number of grid points in the domain.
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.
size_t nPoints() const
Number of grid points in this domain.
void setGridMin(int dom, double gridmin)
Set the minimum grid spacing in the specified domain(s).
vector_fp getCriteria()
Get the grid refinement criteria.
size_t start(size_t i) const
The index of the start of domain i in the solution vector.
virtual void setupGrid(size_t n, const doublereal *z)
called to set up initial grid, and after grid refinement
MultiNewton & newton()
Return a reference to the Newton iterator.
virtual void _finalize(const doublereal *x)
In some cases, a domain may need to set parameters that depend on the initial solution estimate.
void showSolution(std::ostream &s)
Print to stream s the current solution for all domains.
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 setRefineCriteria(int dom=-1, double ratio=10.0, double slope=0.8, double curve=0.8, double prune=-0.1)
Set grid refinement criteria.
virtual std::string componentName(size_t n) const
Name of the nth component. May be overloaded.
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...
Refiner & refiner()
Return a reference to the grid refiner.
void restore(const std::string &fname, const std::string &id, int loglevel=2)
Initialize the solution with a previously-saved solution.
vector_fp m_xlast_ts
the solution vector after the last successful timestepping
double m_tfixed
Temperature at the point used to fix the flame location.
Class XML_Node is a tree-based representation of the contents of an XML file.
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...
virtual void showSolution(const doublereal *x)
Print the solution.
void setMaxPoints(int npmax)
Set the maximum number of points allowed in the domain.
size_t maxGridPoints(size_t dom)
Get the maximum number of grid points in this domain.
int domainType()
Domain type flag.
vector_fp m_x
the solution vector
int intValue(const std::string &val)
Translate a string into one integer value.
size_t bandwidth() const
Jacobian bandwidth.
void setInitialGuess(const std::string &component, vector_fp &locs, vector_fp &vals)
Set initial guess for one component for all domains.
vector_fp m_xlast_ss
the solution vector after the last successful steady-state solve (stored before grid refinement)
virtual doublereal eval(doublereal t) const
Evaluate the function.
virtual void _getInitialSoln(doublereal *x)
Writes some or all initial solution values into the global solution array, beginning at the location ...
void setValue(size_t dom, size_t comp, size_t localPoint, doublereal value)
Set a single value in the solution vector.
size_t maxPoints() const
Returns the maximum number of points allowed in the domain.
vector_int m_steps
array of number of steps to take before re-attempting the steady-state solution
int newtonSolve(int loglevel)
Wrapper around the Newton solver.
size_t nComponents() const
Number of components at each grid point.
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".
This class represents 1D flow domains that satisfy the one-dimensional similarity solution for chemic...
void solveAdjoint(const double *b, double *lambda)
Solve the equation .
A class for banded matrices, involving matrix inversion processes.
vector_fp getRefineCriteria(int dom)
Get the grid refinement criteria.
virtual void resize(size_t nv, size_t np)
Base class for exceptions thrown by Cantera classes.
void setOptions(int maxJacAge=5)
Set options.
int m_nsteps
Number of time steps taken in the current call to solve()
const size_t npos
index returned by functions to indicate "no position"
Base class for one-dimensional domains.
double timeStep(int nsteps, double dt, double *x, double *r, int loglevel)
Namespace for the Cantera kernel.
doublereal & value(size_t i, size_t j)
Return a changeable reference to element (i,j).
void restoreTimeSteppingSolution()
Set the current solution vector to the last successful time-stepping solution.
double m_zfixed
Location of the point where temperature is fixed.
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
Func1 * m_steady_callback
User-supplied function called after a successful steady-state solve.
int solve(const doublereal *const b, doublereal *const x)
Solve the matrix problem Ax = b.