void MultiNewton::step(doublereal* x, doublereal* step, OneDim& r, MultiJac& jac, int loglevel) { size_t iok; size_t sz = r.size(); r.eval(npos, x, step); #undef DEBUG_STEP #ifdef DEBUG_STEP vector_fp ssave(sz, 0.0); for (size_t n = 0; n < sz; n++) { step[n] = -step[n]; ssave[n] = step[n]; } #else for (size_t n = 0; n < sz; n++) { step[n] = -step[n]; } #endif iok = jac.solve(step, step); // if iok is non-zero, then solve failed if (iok != 0) { iok--; size_t nd = r.nDomains(); size_t n; for (n = nd-1; n != npos; n--) if (iok >= r.start(n)) { break; } Domain1D& dom = r.domain(n); size_t offset = iok - r.start(n); size_t pt = offset/dom.nComponents(); size_t comp = offset - pt*dom.nComponents(); throw CanteraError("MultiNewton::step", "Jacobian is singular for domain "+ dom.id() + ", component " +dom.componentName(comp)+" at point " +int2str(pt)+"\n(Matrix row " +int2str(iok)+") \nsee file bandmatrix.csv\n"); } else if (int(iok) < 0) throw CanteraError("MultiNewton::step", "iok = "+int2str(iok)); #ifdef DEBUG_STEP bool ok = false; Domain1D* d; if (!ok) { for (size_t n = 0; n < sz; n++) { d = r.pointDomain(n); int nvd = d->nComponents(); int pt = (n - d->loc())/nvd; cout << "step: " << pt << " " << r.pointDomain(n)->componentName(n - d->loc() - nvd*pt) << " " << x[n] << " " << ssave[n] << " " << step[n] << endl; } } #endif }
/** * Return the factor by which the undamped Newton step 'step0' * must be multiplied in order to keep all solution components in * all domains between their specified lower and upper bounds. */ doublereal MultiNewton::boundStep(const doublereal* x0, const doublereal* step0, const OneDim& r, int loglevel) { doublereal fbound = 1.0; for (size_t i = 0; i < r.nDomains(); i++) { fbound = fminn(fbound, bound_step(x0 + r.start(i), step0 + r.start(i), r.domain(i), loglevel)); } return fbound; }
/** * Compute the weighted 2-norm of 'step'. */ doublereal MultiNewton::norm2(const doublereal* x, const doublereal* step, OneDim& r) const { doublereal f, sum = 0.0;//, fmx = 0.0; size_t nd = r.nDomains(); for (size_t n = 0; n < nd; n++) { f = norm_square(x + r.start(n), step + r.start(n), r.domain(n)); sum += f; } sum /= r.size(); return sqrt(sum); }