29 Indx(
size_t nv,
size_t np) : m_nv(nv), m_np(np) {}
31 size_t operator()(
size_t m,
size_t j) {
41 doublereal bound_step(
const doublereal* x,
const doublereal* step,
42 Domain1D& r,
int loglevel)
45 size_t np = r.nPoints();
46 size_t nv = r.nComponents();
48 doublereal above, below, val, newval;
50 doublereal fbound = 1.0;
51 bool wroteTitle =
false;
52 for (m = 0; m < nv; m++) {
53 above = r.upperBound(m);
54 below = r.lowerBound(m);
56 for (j = 0; j < np; j++) {
59 if (val > above + 1.0e-12 || val < below - 1.0e-12) {
60 sprintf(buf,
"domain %s: %20s(%s) = %10.3e (%10.3e, %10.3e)\n",
61 int2str(r.domainIndex()).c_str(),
62 r.componentName(m).c_str(),
int2str(j).c_str(),
64 writelog(
string(
"\nERROR: solution out of bounds.\n")+buf);
68 newval = val + step[index(m,j)];
71 fbound = std::max(0.0, std::min(fbound,
72 (above - val)/(newval - val)));
73 }
else if (newval < below) {
74 fbound = std::min(fbound, (val - below)/(val - newval));
77 if (loglevel > 1 && (newval > above || newval < below)) {
79 writelog(
"\nNewton step takes solution out of bounds.\n\n");
80 sprintf(buf,
" %12s %12s %4s %10s %10s %10s %10s\n",
81 "domain",
"component",
"pt",
"value",
"step",
"min",
"max");
85 sprintf(buf,
" %4s %12s %4s %10.3e %10.3e %10.3e %10.3e\n",
86 int2str(r.domainIndex()).c_str(),
87 r.componentName(m).c_str(),
int2str(j).c_str(),
88 val, step[index(m,j)], below, above);
119 doublereal norm_square(
const doublereal* x,
120 const doublereal* step, Domain1D& r)
122 doublereal f, ewt, esum, sum = 0.0;
124 doublereal f2max = 0.0;
125 size_t nv = r.nComponents();
126 size_t np = r.nPoints();
128 for (n = 0; n < nv; n++) {
130 for (j = 0; j < np; j++) {
131 esum += fabs(x[nv*j + n]);
133 ewt = r.rtol(n)*esum/np + r.atol(n);
134 for (j = 0; j < np; j++) {
135 f = step[nv*j + n]/ewt;
151 const string dashedline =
152 "-----------------------------------------------------------------";
155 const size_t NDAMP = 7;
161 MultiNewton::MultiNewton(
int sz)
168 MultiNewton::~MultiNewton()
170 for (
size_t i = 0; i < m_workarrays.size(); i++) {
171 delete[] m_workarrays[i];
178 for (
size_t i = 0; i < m_workarrays.size(); i++) {
179 delete[] m_workarrays[i];
181 m_workarrays.clear();
185 const doublereal* step,
OneDim& r)
const
187 doublereal f, sum = 0.0;
189 for (
size_t n = 0; n < nd; n++) {
190 f = norm_square(x + r.
start(n), step + r.
start(n),
202 size_t sz = r.
size();
207 for (
size_t n = 0; n < sz; n++) {
212 for (
size_t n = 0; n < sz; n++) {
217 iok = jac.
solve(step, step);
224 for (n = nd-1; n !=
npos; n--)
225 if (iok >= r.
start(n)) {
229 size_t offset = iok - r.
start(n);
233 "Jacobian is singular for domain "+
234 dom.id() +
", component "
237 +
int2str(iok)+
") \nsee file bandmatrix.csv\n");
238 }
else if (
int(iok) < 0)
246 for (
size_t n = 0; n < sz; n++) {
249 int pt = (n - d->
loc())/nvd;
250 cout <<
"step: " << pt <<
" " <<
252 <<
" " << x[n] <<
" " << ssave[n] <<
" " << step[n] << endl;
259 const doublereal* step0,
const OneDim& r,
int loglevel)
261 doublereal fbound = 1.0;
262 for (
size_t i = 0; i < r.
nDomains(); i++) {
263 fbound = std::min(fbound,
264 bound_step(x0 + r.
start(i), step0 + r.
start(i),
271 doublereal* x1, doublereal* step1, doublereal& s1,
275 if (loglevel > 0 && writetitle) {
276 writelog(
"\n\nDamped Newton iteration:\n");
279 sprintf(m_buf,
"\n%s %9s %9s %9s %9s %9s %5s %5s\n",
280 "m",
"F_damp",
"F_bound",
"log10(ss)",
281 "log10(s0)",
"log10(s1)",
"N_jac",
"Age");
287 doublereal s0 =
norm2(x0, step0, r);
290 doublereal fbound =
boundStep(x0, step0, r, loglevel-1);
296 if (fbound < 1.e-10) {
297 writelog(
"\nAt limits.\n", loglevel);
307 doublereal damp = 1.0;
312 for (m = 0; m <
NDAMP; m++) {
317 for (
size_t j = 0; j < m_n; j++) {
318 x1[j] = ff*step0[j] + x0[j];
323 step(x1, step1, r, jac, loglevel-1);
326 s1 =
norm2(x1, step1, r);
330 doublereal ss = r.
ssnorm(x1,step1);
331 sprintf(m_buf,
"\n%s %9.5f %9.5f %9.5f %9.5f %9.5f %4d %d/%d",
344 if (s1 < 1.0 || s1 < s0) {
368 clock_t t0 = clock();
370 bool forceNewJac =
false;
377 copy(x0, x0 + m_n, x);
380 doublereal rdt = r.
rdt();
387 if (jac.
age() > m_maxAge) {
388 writelog(
"\nMaximum Jacobian age reached ("+
int2str(m_maxAge)+
")\n", loglevel);
394 jac.
eval(x, stp, 0.0);
395 jac.updateTransient(rdt,
DATA_PTR(r.transientMask()));
400 step(x, stp, r, jac, loglevel-1);
406 m =
dampStep(x, stp, x1, stp1, s1, r, jac, loglevel-1, frst);
407 if (loglevel == 1 && m >= 0) {
409 sprintf(m_buf,
"\n\n %10s %10s %5s ",
410 "log10(ss)",
"log10(s1)",
"N_jac");
412 sprintf(m_buf,
"\n ------------------------------------");
415 doublereal ss = r.
ssnorm(x, stp);
416 sprintf(m_buf,
"\n %10.4f %10.4f %d ",
417 log10(ss),log10(s1),jac.
nEvals());
425 copy(x1, x1 + m_n, x);
439 if (nJacReeval > 3) {
443 writelog(
"\nRe-evaluating Jacobian, since no damping "
444 "coefficient\ncould be found with this Jacobian.\n",
453 copy(x, x + m_n, x1);
455 if (m > 0 && jac.
nEvals() == j0) {
461 m_elapsed += (clock() - t0)/(1.0*CLOCKS_PER_SEC);
469 if (!m_workarrays.empty()) {
470 w = m_workarrays.back();
471 m_workarrays.pop_back();
473 w =
new doublereal[m_n];
480 m_workarrays.push_back(work);
Container class for multiple-domain 1D problems.
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.
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.
Contains declarations for string manipulation functions within Cantera.
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 releaseWorkArray(doublereal *work)
Release a work array by pushing its pointer onto the stack of available arrays.
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.
doublereal * getWorkArray()
Get a pointer to an array of length m_n for temporary work space.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...