/** * Find the solution to F(X) = 0 by damped Newton iteration. On * entry, x0 contains an initial estimate of the solution. On * successful return, x1 contains the converged solution. */ int MultiNewton::solve(doublereal* x0, doublereal* x1, OneDim& r, MultiJac& jac, int loglevel) { clock_t t0 = clock(); int m = 0; bool forceNewJac = false; doublereal s1=1.e30; doublereal* x = getWorkArray(); doublereal* stp = getWorkArray(); doublereal* stp1 = getWorkArray(); copy(x0, x0 + m_n, x); bool frst = true; doublereal rdt = r.rdt(); int j0 = jac.nEvals(); while (1 > 0) { // Check whether the Jacobian should be re-evaluated. if (jac.age() > m_maxAge) { if (loglevel > 0) writelog("\nMaximum Jacobian age reached ("+int2str(m_maxAge)+")\n"); forceNewJac = true; } if (forceNewJac) { r.eval(-1, x, stp, 0.0, 0); jac.eval(x, stp, 0.0); jac.updateTransient(rdt, DATA_PTR(r.transientMask())); forceNewJac = false; } // compute the undamped Newton step step(x, stp, r, jac, loglevel-1); // increment the Jacobian age jac.incrementAge(); // damp the Newton step m = dampStep(x, stp, x1, stp1, s1, r, jac, loglevel-1, frst); if (loglevel == 1 && m >= 0) { if (frst) { sprintf(m_buf,"\n\n %10s %10s %5s ", "log10(ss)","log10(s1)","N_jac"); writelog(m_buf); sprintf(m_buf,"\n ------------------------------------"); writelog(m_buf); } doublereal ss = r.ssnorm(x, stp); sprintf(m_buf,"\n %10.4f %10.4f %d ", log10(ss),log10(s1),jac.nEvals()); writelog(m_buf); } frst = false; // Successful step, but not converged yet. Take the damped // step, and try again. if (m == 0) { copy(x1, x1 + m_n, x); } // convergence else if (m == 1) goto done; // If dampStep fails, first try a new Jacobian if an old // one was being used. If it was a new Jacobian, then // return -1 to signify failure. else if (m < 0) { if (jac.age() > 1) { forceNewJac = true; if (loglevel > 0) writelog("\nRe-evaluating Jacobian, since no damping " "coefficient\ncould be found with this Jacobian.\n"); } else goto done; } } done: if (m < 0) { copy(x, x + m_n, x1); } if (m > 0 && jac.nEvals() == j0) m = 100; releaseWorkArray(x); releaseWorkArray(stp); releaseWorkArray(stp1); m_elapsed += (clock() - t0)/(1.0*CLOCKS_PER_SEC); return m; }
int MultiNewton::solve(doublereal* x0, doublereal* x1, OneDim& r, MultiJac& jac, int loglevel) { clock_t t0 = clock(); int m = 0; bool forceNewJac = false; doublereal s1=1.e30; copy(x0, x0 + m_n, &m_x[0]); bool frst = true; doublereal rdt = r.rdt(); int j0 = jac.nEvals(); int nJacReeval = 0; while (1 > 0) { // Check whether the Jacobian should be re-evaluated. if (jac.age() > m_maxAge) { writelog("\nMaximum Jacobian age reached ("+int2str(m_maxAge)+")\n", loglevel); forceNewJac = true; } if (forceNewJac) { r.eval(npos, &m_x[0], &m_stp[0], 0.0, 0); jac.eval(&m_x[0], &m_stp[0], 0.0); jac.updateTransient(rdt, DATA_PTR(r.transientMask())); forceNewJac = false; } // compute the undamped Newton step step(&m_x[0], &m_stp[0], r, jac, loglevel-1); // increment the Jacobian age jac.incrementAge(); // damp the Newton step m = dampStep(&m_x[0], &m_stp[0], x1, &m_stp1[0], s1, r, jac, loglevel-1, frst); if (loglevel == 1 && m >= 0) { if (frst) { sprintf(m_buf,"\n\n %10s %10s %5s ", "log10(ss)","log10(s1)","N_jac"); writelog(m_buf); sprintf(m_buf,"\n ------------------------------------"); writelog(m_buf); } doublereal ss = r.ssnorm(&m_x[0], &m_stp[0]); sprintf(m_buf,"\n %10.4f %10.4f %d ", log10(ss),log10(s1),jac.nEvals()); writelog(m_buf); } frst = false; // Successful step, but not converged yet. Take the damped // step, and try again. if (m == 0) { copy(x1, x1 + m_n, m_x.begin()); } // convergence else if (m == 1) { jac.setAge(0); // for efficient sensitivity analysis break; } // If dampStep fails, first try a new Jacobian if an old // one was being used. If it was a new Jacobian, then // return -1 to signify failure. else if (m < 0) { if (jac.age() > 1) { forceNewJac = true; if (nJacReeval > 3) { break; } nJacReeval++; writelog("\nRe-evaluating Jacobian, since no damping " "coefficient\ncould be found with this Jacobian.\n", loglevel); } else { break; } } } if (m < 0) { copy(m_x.begin(), m_x.end(), x1); } if (m > 0 && jac.nEvals() == j0) { m = 100; } m_elapsed += (clock() - t0)/(1.0*CLOCKS_PER_SEC); return m; }