Example #1
0
Int NonLinearRichardson( VectorEpetra& sol,
                      Fct&        functional,
                      Real        abstol,
                      Real        reltol,
                      UInt&       maxit,
                      Real        eta_max,
                      Int         NonLinearLineSearch,
                      std::ofstream& out_res,
                      const Real& time,
                      UInt iter = UInt(0) )
{
    /*
        */

    /*
      max_increase_res: maximum number of successive increases in residual
      before failure is reported
    */

//    const Int max_increase_res = 5;

    /*
      Parameters for the linear solver, gamma: Default value = 0.9
    */

    const Real gamma   = 0.9;

    //----------------------------------------------------------------------

    bool const verbose(sol.comm().MyPID() == 0);

    //UInt iter = 0;

    VectorEpetra residual ( sol.map() );
    VectorEpetra step     ( sol.map() );

    step *= 0.;

    Real normResOld = 1;

    if (verbose)
    {
        //std::cout << "------------------------------------------------------------------" << std::endl;
        std::cout << std::endl;
        std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << std::endl;
        std::cout << "      Non-Linear Richardson: starting          " << std::endl;
        std::cout << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
        std::cout << std::endl;
        //std::cout << "------------------------------------------------------------------" << std::endl;
    }
    functional.evalResidual( residual, sol, iter );

    Real normRes      = residual.normInf();
    Real stop_tol     = abstol + reltol*normRes;
    Real linearRelTol = std::fabs(eta_max);
    Real eta_old;
    Real eta_new;
    Real ratio;
    Real slope;
    Real linres;
    Real lambda;

    //

    Real solNormInf(sol.normInf());
    Real stepNormInf;
    if (verbose)
    {
        out_res << std::scientific;
        out_res << "# time = ";
        out_res << time << "   " << "initial norm_res " <<  normRes
        << " stop tol = " << stop_tol
        << "initial norm_sol "
        << solNormInf << std::endl;
        out_res << "#iter      disp_norm       step_norm       residual_norm" << std::endl;
    }
    while ( normRes > stop_tol && iter < maxit )
    {
        if (verbose)
        {
            std::cout << std::endl;
            //std::cout << "------------------------------------------------------------------" << std::endl;
            std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << std::endl;
            std::cout << "      Non-Linear Richardson: iteration  =      " << iter << std::endl
                      << "                             residual   =      " << normRes << std::endl
                      << "                             tolerance  =      " << stop_tol << std::endl;
            std::cout << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
            std::cout << std::endl;
            //std::cout << "------------------------------------------------------------------" << std::endl;
            //std::cout << std::endl;
        }

        iter++;

        ratio      = normRes/normResOld;
        normResOld = normRes;
        normRes    = residual.normInf();

        residual *= -1;
        functional.solveJac(step, residual, linearRelTol); // J*step = -R

        solNormInf = sol.normInf();
        stepNormInf = step.normInf();
        if (verbose)
        {
            out_res   << std::setw(5) << iter
            << std::setw(15) << solNormInf
            << std::setw(15) << stepNormInf;
        }
        linres = linearRelTol;

        lambda = 1.;
        slope  = normRes * normRes * ( linres * linres - 1 );

        Int status(EXIT_SUCCESS);
        switch ( NonLinearLineSearch )
        {
        case 0: // no NonLinearLineSearch
            sol += step;
            functional.evalResidual( residual, sol, iter);
//                normRes = residual.NormInf();
            break;
        case 1:
            status = NonLinearLineSearchParabolic( functional, residual, sol, step, normRes, lambda, iter, verbose );
            break;
        case 2:  // recommended
            status = NonLinearLineSearchCubic( functional, residual, sol, step, normRes, lambda, slope, iter, verbose );
            break;
        default:
            std::cout << "Unknown NonLinearLineSearch \n";
            status = EXIT_FAILURE;
        }

        if (status == EXIT_FAILURE)
            return status;



        normRes = residual.normInf();

        if (verbose)
            out_res << std::setw(15) << normRes << std::endl;

        if ( eta_max > 0 )
        {
            eta_old = linearRelTol;
            eta_new = gamma * ratio * ratio;
            if ( gamma * eta_old * eta_old > .1 )
            {
                eta_new = std::max<Real>( eta_new, gamma * eta_old * eta_old );
            }
            linearRelTol = std::min<Real>( eta_new, eta_max );
            linearRelTol = std::min<Real>( eta_max,
                                           std::max<Real>( linearRelTol,
                                                           .5 * stop_tol / normRes ) );
            //if (verbose)
            //    std::cout << "    Newton: forcing term eta = " << linearRelTol << std::endl;
        }

    }

    if ( normRes > stop_tol )
    {
        if (verbose)
            std::cout << "!!! NonLinRichardson: convergence fails" << std::endl;
        maxit = iter;
        return EXIT_FAILURE;
    }

    if (verbose)
    {
        std::cout << std::endl;
        //std::cout << "------------------------------------------------------------------" << std::endl;
        std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << std::endl;
        std::cout << "      Non-Linear Richardson: convergence =     " << normRes << std::endl
                  << "                             iterations  =     " << iter << std::endl;
        std::cout << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
        std::cout << std::endl;
        //std::cout << "------------------------------------------------------------------" << std::endl;
    }
    maxit = iter;

    return EXIT_SUCCESS;
}