23 Indx(
size_t nv,
size_t np) : m_nv(nv), m_np(np) {}
25 size_t operator()(
size_t m,
size_t j) {
35 double bound_step(
const double* x,
const double* step, Domain1D& r,
int loglevel)
37 size_t np = r.nPoints();
38 size_t nv = r.nComponents();
41 bool wroteTitle =
false;
42 for (
size_t m = 0; m < nv; m++) {
43 double above = r.upperBound(m);
44 double below = r.lowerBound(m);
46 for (
size_t j = 0; j < np; j++) {
47 double val = x[index(m,j)];
48 if (loglevel > 0 && (val > above + 1.0e-12 || val < below - 1.0e-12)) {
49 writelog(
"\nERROR: solution out of bounds.\n");
50 writelog(
"domain {:d}: {:>20s}({:d}) = {:10.3e} ({:10.3e}, {:10.3e})\n",
51 r.domainIndex(), r.componentName(m), j, val, below, above);
54 double newval = val + step[index(m,j)];
57 fbound = std::max(0.0, std::min(fbound,
58 (above - val)/(newval - val)));
59 }
else if (newval < below) {
60 fbound = std::min(fbound, (val - below)/(val - newval));
63 if (loglevel > 1 && (newval > above || newval < below)) {
65 writelog(
"\nNewton step takes solution out of bounds.\n\n");
66 writelog(
" {:>12s} {:>12s} {:>4s} {:>10s} {:>10s} {:>10s} {:>10s}\n",
67 "domain",
"component",
"pt",
"value",
"step",
"min",
"max");
70 writelog(
" {:4d} {:>12s} {:4d} {:10.3e} {:10.3e} {:10.3e} {:10.3e}\n",
71 r.domainIndex(), r.componentName(m), j,
72 val, step[index(m,j)], below, above);
101 double norm_square(
const double* x,
const double* step, Domain1D& r)
105 size_t nv = r.nComponents();
106 size_t np = r.nPoints();
108 for (
size_t n = 0; n < nv; n++) {
110 for (
size_t j = 0; j < np; j++) {
111 esum += fabs(x[nv*j + n]);
113 double ewt = r.rtol(n)*esum/np + r.atol(n);
114 for (
size_t j = 0; j < np; j++) {
115 double f = step[nv*j + n]/ewt;
117 f2max = std::max(f*f, f2max);
127 const double DampFactor = sqrt(2.0);
128 const size_t NDAMP = 7;
132 MultiNewton::MultiNewton(
int sz)
137 void MultiNewton::resize(
size_t sz)
145 double MultiNewton::norm2(
const double* x,
const double* step,
OneDim& r)
const
149 for (
size_t n = 0; n < nd; n++) {
157 void MultiNewton::step(
double* x,
double* step,
OneDim& r,
MultiJac& jac,
int loglevel)
160 for (
size_t n = 0; n < r.
size(); n++) {
165 jac.
solve(step, step);
167 if (jac.
info() > 0) {
169 size_t row =
static_cast<size_t>(jac.
info() - 1);
172 for (
size_t n = 0; n < r.
nDomains(); n++) {
175 if (row >= dom.
loc() && row < dom.
loc() + nComp * dom.
nPoints()) {
177 size_t pt =
offset / nComp;
178 size_t comp =
offset - pt * nComp;
180 "Jacobian is singular for domain {}, component {} at point {}\n"
190 double MultiNewton::boundStep(
const double* x0,
const double* step0,
const OneDim& r,
194 for (
size_t i = 0; i < r.
nDomains(); i++) {
195 fbound = std::min(fbound,
196 bound_step(x0 + r.
start(i), step0 + r.
start(i),
202 int MultiNewton::dampStep(
const double* x0,
const double* step0,
203 double* x1,
double* step1,
double& s1,
207 if (loglevel > 0 && writetitle) {
208 writelog(
"\n\nDamped Newton iteration:\n");
209 writeline(
'-', 65,
false);
211 writelog(
"\n{} {:>9s} {:>9s} {:>9s} {:>9s} {:>9s} {:>5s} {:>5s}\n",
212 "m",
"F_damp",
"F_bound",
"log10(ss)",
213 "log10(s0)",
"log10(s1)",
"N_jac",
"Age");
218 double s0 = norm2(x0, step0, r);
221 double fbound = boundStep(x0, step0, r, loglevel-1);
226 if (fbound < 1.e-10) {
227 debuglog(
"\nAt limits.\n", loglevel);
236 for (m = 0; m < NDAMP; m++) {
237 double ff = fbound*damp;
240 for (
size_t j = 0; j < m_n; j++) {
241 x1[j] = ff*step0[j] + x0[j];
245 step(x1, step1, r, jac, loglevel-1);
248 s1 = norm2(x1, step1, r);
252 double ss = r.
ssnorm(x1,step1);
253 writelog(
"\n{:d} {:9.5f} {:9.5f} {:9.5f} {:9.5f} {:9.5f} {:4d} {:d}/{:d}",
263 if (s1 < 1.0 || s1 < s0) {
285 clock_t t0 = clock();
287 bool forceNewJac =
false;
290 copy(x0, x0 + m_n, &m_x[0]);
293 double rdt = r.
rdt();
299 if (jac.
age() > m_maxAge) {
301 writelog(
"\nMaximum Jacobian age reached ({})\n", m_maxAge);
307 r.
eval(
npos, &m_x[0], &m_stp[0], 0.0, 0);
308 jac.
eval(&m_x[0], &m_stp[0], 0.0);
309 jac.updateTransient(rdt, r.transientMask().data());
314 step(&m_x[0], &m_stp[0], r, jac, loglevel-1);
320 m = dampStep(&m_x[0], &m_stp[0], x1, &m_stp1[0], s1, r, jac, loglevel-1, frst);
321 if (loglevel == 1 && m >= 0) {
323 writelog(
"\n\n {:>10s} {:>10s} {:>5s}",
324 "log10(ss)",
"log10(s1)",
"N_jac");
325 writelog(
"\n ------------------------------------");
327 double ss = r.
ssnorm(&m_x[0], &m_stp[0]);
328 writelog(
"\n {:10.4f} {:10.4f} {:d}",
329 log10(ss),log10(s1),jac.
nEvals());
336 copy(x1, x1 + m_n, m_x.begin());
349 if (nJacReeval > 3) {
353 debuglog(
"\nRe-evaluating Jacobian, since no damping "
354 "coefficient\ncould be found with this Jacobian.\n",
363 copy(m_x.begin(), m_x.end(), x1);
365 if (m > 0 && jac.
nEvals() == j0) {
368 m_elapsed += (clock() - t0)/(1.0*CLOCKS_PER_SEC);
int info() const
LAPACK "info" flag after last factor/solve operation.
int solve(const double *const b, double *const x)
Solve the matrix problem Ax = b.
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 nPoints() const
Number of grid points in this domain.
virtual string componentName(size_t n) const
Name of the nth component. May be overloaded.
virtual size_t loc(size_t j=0) const
Location of the start of the local solution vector in the global solution vector,.
Class MultiJac evaluates the Jacobian of a system of equations defined by a residual function supplie...
int nEvals() const
Number of Jacobian evaluations.
void setAge(int age)
Set the Jacobian age.
void eval(double *x0, double *resid0, double rdt)
Evaluate the Jacobian at x0.
void incrementAge()
Increment the Jacobian age.
int age() const
Number of times 'incrementAge' has been called since the last evaluation.
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.
size_t size() const
Total solution vector length;.
void eval(size_t j, double *x, double *r, double rdt=-1.0, int count=1)
Evaluate the multi-domain residual function.
double ssnorm(double *x, double *r)
Steady-state max norm (infinity norm) of the residual evaluated using solution x.
double rdt() const
Reciprocal of the time step.
size_t nDomains() const
Number of domains.
Domain1D & domain(size_t i) const
Return a reference to domain i.
void debuglog(const string &msg, int loglevel)
Write a message to the log only if loglevel > 0.
void writelog(const 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 SmallNumber
smallest number to compare to zero.
offset
Offsets of solution components in the 1D solution array.
int solve(DenseMatrix &A, double *b, size_t nrhs, size_t ldb)
Solve Ax = b. Array b is overwritten on exit with x.
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...