27 Indx(
size_t nv,
size_t np) : m_nv(nv), m_np(np) {}
29 size_t operator()(
size_t m,
size_t j) {
39 doublereal bound_step(
const doublereal* x,
const doublereal* step,
40 Domain1D& r,
int loglevel)
43 size_t np = r.nPoints();
44 size_t nv = r.nComponents();
46 doublereal above, below, val, newval;
48 doublereal fbound = 1.0;
49 bool wroteTitle =
false;
50 for (m = 0; m < nv; m++) {
51 above = r.upperBound(m);
52 below = r.lowerBound(m);
54 for (j = 0; j < np; j++) {
57 if (val > above + 1.0e-12 || val < below - 1.0e-12) {
58 sprintf(buf,
"domain %s: %20s(%s) = %10.3e (%10.3e, %10.3e)\n",
59 int2str(r.domainIndex()).c_str(),
60 r.componentName(m).c_str(),
int2str(j).c_str(),
62 writelog(
string(
"\nERROR: solution out of bounds.\n")+buf);
66 newval = val + step[index(m,j)];
69 fbound = std::max(0.0, std::min(fbound,
70 (above - val)/(newval - val)));
71 }
else if (newval < below) {
72 fbound = std::min(fbound, (val - below)/(val - newval));
75 if (loglevel > 1 && (newval > above || newval < below)) {
77 writelog(
"\nNewton step takes solution out of bounds.\n\n");
78 sprintf(buf,
" %12s %12s %4s %10s %10s %10s %10s\n",
79 "domain",
"component",
"pt",
"value",
"step",
"min",
"max");
83 sprintf(buf,
" %4s %12s %4s %10.3e %10.3e %10.3e %10.3e\n",
84 int2str(r.domainIndex()).c_str(),
85 r.componentName(m).c_str(),
int2str(j).c_str(),
86 val, step[index(m,j)], below, above);
117 doublereal norm_square(
const doublereal* x,
118 const doublereal* step, Domain1D& r)
120 doublereal f, ewt, esum, sum = 0.0;
122 doublereal f2max = 0.0;
123 size_t nv = r.nComponents();
124 size_t np = r.nPoints();
126 for (n = 0; n < nv; n++) {
128 for (j = 0; j < np; j++) {
129 esum += fabs(x[nv*j + n]);
131 ewt = r.rtol(n)*esum/np + r.atol(n);
132 for (j = 0; j < np; j++) {
133 f = step[nv*j + n]/ewt;
135 f2max = std::max(f*f, f2max);
148 const size_t NDAMP = 7;
154 MultiNewton::MultiNewton(
int sz)
170 const doublereal* step,
OneDim& r)
const
172 doublereal f, sum = 0.0;
174 for (
size_t n = 0; n < nd; n++) {
175 f = norm_square(x + r.
start(n), step + r.
start(n),
187 size_t sz = r.
size();
192 for (
size_t n = 0; n < sz; n++) {
197 for (
size_t n = 0; n < sz; n++) {
202 iok = jac.
solve(step, step);
209 for (n = nd-1; n !=
npos; n--)
210 if (iok >= r.
start(n)) {
214 size_t offset = iok - r.
start(n);
218 "Jacobian is singular for domain "+
219 dom.id() +
", component "
222 +
int2str(iok)+
") \nsee file bandmatrix.csv\n");
223 }
else if (
int(iok) < 0)
231 for (
size_t n = 0; n < sz; n++) {
234 int pt = (n - d->
loc())/nvd;
235 cout <<
"step: " << pt <<
" " <<
237 <<
" " << x[n] <<
" " << ssave[n] <<
" " << step[n] << endl;
244 const doublereal* step0,
const OneDim& r,
int loglevel)
246 doublereal fbound = 1.0;
247 for (
size_t i = 0; i < r.
nDomains(); i++) {
248 fbound = std::min(fbound,
249 bound_step(x0 + r.
start(i), step0 + r.
start(i),
256 doublereal* x1, doublereal* step1, doublereal& s1,
260 if (loglevel > 0 && writetitle) {
261 writelog(
"\n\nDamped Newton iteration:\n");
262 writeline(
'-', 65,
false);
264 sprintf(m_buf,
"\n%s %9s %9s %9s %9s %9s %5s %5s\n",
265 "m",
"F_damp",
"F_bound",
"log10(ss)",
266 "log10(s0)",
"log10(s1)",
"N_jac",
"Age");
272 doublereal s0 =
norm2(x0, step0, r);
275 doublereal fbound =
boundStep(x0, step0, r, loglevel-1);
281 if (fbound < 1.e-10) {
282 writelog(
"\nAt limits.\n", loglevel);
292 doublereal damp = 1.0;
297 for (m = 0; m <
NDAMP; m++) {
302 for (
size_t j = 0; j <
m_n; j++) {
303 x1[j] = ff*step0[j] + x0[j];
308 step(x1, step1, r, jac, loglevel-1);
311 s1 =
norm2(x1, step1, r);
315 doublereal ss = r.
ssnorm(x1,step1);
316 sprintf(m_buf,
"\n%s %9.5f %9.5f %9.5f %9.5f %9.5f %4d %d/%d",
329 if (s1 < 1.0 || s1 < s0) {
353 clock_t t0 = clock();
355 bool forceNewJac =
false;
358 copy(x0, x0 +
m_n, &
m_x[0]);
361 doublereal rdt = r.
rdt();
367 if (jac.
age() > m_maxAge) {
368 writelog(
"\nMaximum Jacobian age reached ("+
int2str(m_maxAge)+
")\n", loglevel);
374 jac.
eval(&
m_x[0], &m_stp[0], 0.0);
375 jac.updateTransient(rdt,
DATA_PTR(r.transientMask()));
380 step(&
m_x[0], &m_stp[0], r, jac, loglevel-1);
386 m =
dampStep(&
m_x[0], &m_stp[0], x1, &m_stp1[0], s1, r, jac, loglevel-1, frst);
387 if (loglevel == 1 && m >= 0) {
389 sprintf(m_buf,
"\n\n %10s %10s %5s ",
390 "log10(ss)",
"log10(s1)",
"N_jac");
392 sprintf(m_buf,
"\n ------------------------------------");
395 doublereal ss = r.
ssnorm(&
m_x[0], &m_stp[0]);
396 sprintf(m_buf,
"\n %10.4f %10.4f %d ",
397 log10(ss),log10(s1),jac.
nEvals());
405 copy(x1, x1 +
m_n,
m_x.begin());
420 if (nJacReeval > 3) {
424 writelog(
"\nRe-evaluating Jacobian, since no damping "
425 "coefficient\ncould be found with this Jacobian.\n",
434 copy(
m_x.begin(),
m_x.end(), x1);
436 if (m > 0 && jac.
nEvals() == j0) {
439 m_elapsed += (clock() - t0)/(1.0*CLOCKS_PER_SEC);
Container class for multiple-domain 1D problems.
size_t m_n
number of variables
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
int nEvals() const
Number of Jacobian evaluations.
int age() const
Number of times 'incrementAge' has been called since the last evaluation.
doublereal ssnorm(doublereal *x, doublereal *r)
Steady-state max norm (infinity norm) of the residual evaluated using solution x. ...
void eval(size_t j, double *x, double *r, doublereal rdt=-1.0, int count=1)
Evaluate the multi-domain residual function.
const size_t npos
index returned by functions to indicate "no position"
void step(doublereal *x, doublereal *step, OneDim &r, MultiJac &jac, int loglevel)
Compute the undamped Newton step.
virtual std::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,.
int solve(const doublereal *const b, doublereal *const x)
Solve the matrix problem Ax = b.
void incrementAge()
Increment the Jacobian age.
const double DampFactor
Dampfactor is the factor by which the damping factor is reduced by when a reduction in step length is...
size_t m_n
Number of rows and columns of the matrix.
doublereal rdt() const
Reciprocal of the time step.
size_t nComponents() const
Number of components at each grid point.
Base class for one-dimensional domains.
void setAge(int age)
Set the Jacobian age.
int solve(doublereal *x0, doublereal *x1, OneDim &r, MultiJac &jac, int loglevel)
Find the solution to F(X) = 0 by damped Newton iteration.
size_t start(size_t i) const
The index of the start of domain i in the solution vector.
Domain1D & domain(size_t i) const
Return a reference to domain i.
doublereal norm2(const doublereal *x, const doublereal *step, OneDim &r) const
Compute the weighted 2-norm of step.
Base class for exceptions thrown by Cantera classes.
const int NDAMP
Number of damping steps that are carried out before the solution is deemed a failure.
void resize(size_t points)
Change the problem size.
size_t nDomains() const
Number of domains.
void eval(doublereal *x0, doublereal *resid0, double rdt)
Evaluate the Jacobian at x0.
Class MultiJac evaluates the Jacobian of a system of equations defined by a residual function supplie...
doublereal boundStep(const doublereal *x0, const doublereal *step0, const OneDim &r, int loglevel)
Return the factor by which the undamped Newton step 'step0' must be multiplied in order to keep all s...
const doublereal SmallNumber
smallest number to compare to zero.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Templates for operations on vector-like objects.
int dampStep(const doublereal *x0, const doublereal *step0, doublereal *x1, doublereal *step1, doublereal &s1, OneDim &r, MultiJac &jac, int loglevel, bool writetitle)
On entry, step0 must contain an undamped Newton step for the solution x0.
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
void writelog(const std::string &msg)
Write a message to the screen.
size_t size() const
Total solution vector length;.
Domain1D * pointDomain(size_t i)
Return a pointer to the domain global point i belongs to.
vector_fp m_x
Work arrays of size m_n used in solve().