示例#1
0
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
}
示例#2
0
    /**
     * 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;
    }
示例#3
0
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;
}