void Multigrid::solve()
{
    smooth();
    computeResidual();
    while (error() > tol() & n < maxIter())
        iterate();
    if (n == maxIter())
        cout << "Multigrid reached maximum number of iterations" << endl;
}
    SimulatorReport
    NonlinearSolver<PhysicalModel>::
    step(const SimulatorTimerInterface& timer,
         const ReservoirState& initial_reservoir_state,
         const WellState& initial_well_state,
         ReservoirState& reservoir_state,
         WellState& well_state)
    {
        SimulatorReport iterReport;
        SimulatorReport report;
        failureReport_ = SimulatorReport();

        // Do model-specific once-per-step calculations.
        model_->prepareStep(timer, initial_reservoir_state, initial_well_state);

        int iteration = 0;

        // Let the model do one nonlinear iteration.

        // Set up for main solver loop.
        bool converged = false;

        // ----------  Main nonlinear solver loop  ----------
        do {
            try {
                // Do the nonlinear step. If we are in a converged state, the
                // model will usually do an early return without an expensive
                // solve, unless the minIter() count has not been reached yet.
                iterReport = model_->nonlinearIteration(iteration, timer, *this, reservoir_state, well_state);

                report += iterReport;
                report.converged = iterReport.converged;

                converged = report.converged;
                iteration += 1;
            }
            catch (...) {
                // if an iteration fails during a time step, all previous iterations
                // count as a failure as well
                failureReport_ += report;
                failureReport_ += model_->failureReport();
                throw;
            }
        } while ( (!converged && (iteration <= maxIter())) || (iteration <= minIter()));

        if (!converged) {
            failureReport_ += report;

            std::string msg = "Solver convergence failure - Failed to complete a time step within " + std::to_string(maxIter()) + " iterations.";
            OPM_THROW_NOLOG(Opm::TooManyIterations, msg);
        }

        // Do model-specific post-step actions.
        model_->afterStep(timer, reservoir_state, well_state);
        report.converged = true;

        return report;
    }
    int
    NonlinearSolver<PhysicalModel>::
    step(const SimulatorTimerInterface& timer,
         const ReservoirState& initial_reservoir_state,
         const WellState& initial_well_state,
         ReservoirState& reservoir_state,
         WellState& well_state)
    {
        // Do model-specific once-per-step calculations.
        model_->prepareStep(timer, initial_reservoir_state, initial_well_state);

        int iteration = 0;

        // Let the model do one nonlinear iteration.

        // Set up for main solver loop.
        int linIters = 0;
        bool converged = false;
        int wellIters = 0;

        // ----------  Main nonlinear solver loop  ----------
        do {
            // Do the nonlinear step. If we are in a converged state, the
            // model will usually do an early return without an expensive
            // solve, unless the minIter() count has not been reached yet.
            IterationReport report = model_->nonlinearIteration(iteration, timer, *this, reservoir_state, well_state);
            if (report.failed) {
                OPM_THROW(Opm::NumericalProblem, "Failed to complete a nonlinear iteration.");
            }
            converged = report.converged;
            linIters += report.linear_iterations;
            wellIters += report.well_iterations;
            ++iteration;
        } while ( (!converged && (iteration <= maxIter())) || (iteration <= minIter()));

        if (!converged) {
            if (model_->terminalOutputEnabled()) {
                std::cerr << "WARNING: Failed to compute converged solution in " << iteration - 1 << " iterations." << std::endl;
            }
            return -1; // -1 indicates that the solver has to be restarted
        }

        linearIterations_ += linIters;
        nonlinearIterations_ += iteration - 1; // Since the last one will always be trivial.
        linearizations_ += iteration;
        wellIterations_ += wellIters;
        linearIterationsLast_ = linIters;
        nonlinearIterationsLast_ = iteration;
        wellIterationsLast_ = wellIters;

        // Do model-specific post-step actions.
        model_->afterStep(timer, reservoir_state, well_state);

        return linIters;
    }
void Foam::MULES::implicitSolve
(
    const RhoType& rho,
    volScalarField& psi,
    const surfaceScalarField& phi,
    surfaceScalarField& phiPsi,
    const SpType& Sp,
    const SuType& Su,
    const scalar psiMax,
    const scalar psiMin
)
{
    const fvMesh& mesh = psi.mesh();

    const dictionary& MULEScontrols = mesh.solverDict(psi.name());

    label maxIter
    (
        readLabel(MULEScontrols.lookup("maxIter"))
    );

    label nLimiterIter
    (
        readLabel(MULEScontrols.lookup("nLimiterIter"))
    );

    scalar maxUnboundedness
    (
        readScalar(MULEScontrols.lookup("maxUnboundedness"))
    );

    scalar CoCoeff
    (
        readScalar(MULEScontrols.lookup("CoCoeff"))
    );

    scalarField allCoLambda(mesh.nFaces());

    {
        tmp<surfaceScalarField> Cof =
            mesh.time().deltaT()*mesh.surfaceInterpolation::deltaCoeffs()
           *mag(phi)/mesh.magSf();

        slicedSurfaceScalarField CoLambda
        (
            IOobject
            (
                "CoLambda",
                mesh.time().timeName(),
                mesh,
                IOobject::NO_READ,
                IOobject::NO_WRITE,
                false
            ),
            mesh,
            dimless,
            allCoLambda,
            false   // Use slices for the couples
        );

        CoLambda == 1.0/max(CoCoeff*Cof, scalar(1));
    }

    scalarField allLambda(allCoLambda);
    //scalarField allLambda(mesh.nFaces(), 1.0);

    slicedSurfaceScalarField lambda
    (
        IOobject
        (
            "lambda",
            mesh.time().timeName(),
            mesh,
            IOobject::NO_READ,
            IOobject::NO_WRITE,
            false
        ),
        mesh,
        dimless,
        allLambda,
        false   // Use slices for the couples
    );

    linear<scalar> CDs(mesh);
    upwind<scalar> UDs(mesh, phi);
    //fv::uncorrectedSnGrad<scalar> snGrads(mesh);

    fvScalarMatrix psiConvectionDiffusion
    (
        fvm::ddt(rho, psi)
      + fv::gaussConvectionScheme<scalar>(mesh, phi, UDs).fvmDiv(phi, psi)
        //- fv::gaussLaplacianScheme<scalar, scalar>(mesh, CDs, snGrads)
        //.fvmLaplacian(Dpsif, psi)
      - fvm::Sp(Sp, psi)
      - Su
    );

    surfaceScalarField phiBD(psiConvectionDiffusion.flux());

    surfaceScalarField& phiCorr = phiPsi;
    phiCorr -= phiBD;

    for (label i=0; i<maxIter; i++)
    {
        if (i != 0 && i < 4)
        {
            allLambda = allCoLambda;
        }

        limiter
        (
            allLambda,
            rho,
            psi,
            phiBD,
            phiCorr,
            Sp,
            Su,
            psiMax,
            psiMin,
            nLimiterIter
        );

        solve
        (
            psiConvectionDiffusion + fvc::div(lambda*phiCorr),
            MULEScontrols
        );

        scalar maxPsiM1 = gMax(psi.internalField()) - 1.0;
        scalar minPsi = gMin(psi.internalField());

        scalar unboundedness = max(max(maxPsiM1, 0.0), -min(minPsi, 0.0));

        if (unboundedness < maxUnboundedness)
        {
            break;
        }
        else
        {
            Info<< "MULES: max(" << psi.name() << " - 1) = " << maxPsiM1
                << " min(" << psi.name() << ") = " << minPsi << endl;

            phiBD = psiConvectionDiffusion.flux();

            /*
            word gammaScheme("div(phi,gamma)");
            word gammarScheme("div(phirb,gamma)");

            const surfaceScalarField& phir =
                mesh.lookupObject<surfaceScalarField>("phir");

            phiCorr =
                fvc::flux
                (
                    phi,
                    psi,
                    gammaScheme
                )
              + fvc::flux
                (
                    -fvc::flux(-phir, scalar(1) - psi, gammarScheme),
                    psi,
                    gammarScheme
                )
                - phiBD;
            */
        }
    }

    phiPsi = psiConvectionDiffusion.flux() + lambda*phiCorr;
}
    int
    NewtonSolver<PhysicalModel>::
    step(const double dt,
         ReservoirState& reservoir_state,
         WellState& well_state)
    {
        // Do model-specific once-per-step calculations.
        model_->prepareStep(dt, reservoir_state, well_state);

        // For each iteration we store in a vector the norms of the residual of
        // the mass balance for each active phase, the well flux and the well equations.
        std::vector<std::vector<double>> residual_norms_history;

        // Assemble residual and Jacobian, store residual norms.
        model_->assemble(reservoir_state, well_state, true);
        residual_norms_history.push_back(model_->computeResidualNorms());

        // Set up for main Newton loop.
        double omega = 1.0;
        int iteration = 0;
        bool converged = model_->getConvergence(dt, iteration);
        const int sizeNonLinear = model_->sizeNonLinear();
        V dxOld = V::Zero(sizeNonLinear);
        bool isOscillate = false;
        bool isStagnate = false;
        const enum RelaxType relaxtype = relaxType();
        int linearIterations = 0;

        // ----------  Main Newton loop  ----------
        while ( (!converged && (iteration < maxIter())) || (minIter() > iteration)) {
            // Compute the Newton update to the primary variables.
            V dx = model_->solveJacobianSystem();

            // Store number of linear iterations used.
            linearIterations += model_->linearIterationsLastSolve();

            // Stabilize the Newton update.
            detectNewtonOscillations(residual_norms_history, iteration, relaxRelTol(), isOscillate, isStagnate);
            if (isOscillate) {
                omega -= relaxIncrement();
                omega = std::max(omega, relaxMax());
                if (model_->terminalOutputEnabled()) {
                    std::cout << " Oscillating behavior detected: Relaxation set to " << omega << std::endl;
                }
            }
            stabilizeNewton(dx, dxOld, omega, relaxtype);

            // Apply the update, the model may apply model-dependent
            // limitations and chopping of the update.
            model_->updateState(dx, reservoir_state, well_state);

            // Assemble residual and Jacobian, store residual norms.
            model_->assemble(reservoir_state, well_state, false);
            residual_norms_history.push_back(model_->computeResidualNorms());

            // increase iteration counter
            ++iteration;

            converged = model_->getConvergence(dt, iteration);
        }

        if (!converged) {
            if (model_->terminalOutputEnabled()) {
                std::cerr << "WARNING: Failed to compute converged solution in " << iteration << " iterations." << std::endl;
            }
            return -1; // -1 indicates that the solver has to be restarted
        }

        linearIterations_ += linearIterations;
        newtonIterations_ += iteration;
        linearIterationsLast_ = linearIterations;
        newtonIterationsLast_ = iteration;

        // Do model-specific post-step actions.
        model_->afterStep(dt, reservoir_state, well_state);

        return linearIterations;
    }
Exemple #6
0
void Grnn::Trainer::trainBrent(Grnn& grnn)
{
    double a = tolerance();
    double b = grnn.bandwidth();
    double x = 0.5*(a + b);
    bracket(grnn, a, b, x);
       
    if (a > b)
        SWP(a, b);
        
    double fx = error(grnn, x);
    double w = x, fw = fx;
    double v = x, fv = fx;
    
    double d = 0.0, u, e = 0.0;
    for(unsigned iter = 1; iter <= maxIter(); ++iter) 
    {
        double xm = 0.5*(a + b);
        double tol1 = tolerance()*fabs(x) + ZEPS;
        double tol2 = 2.0*(tol1);
        if (fabs(x - xm) <= (tol2 - 0.5*(b - a))) 
            break;
        if (fabs(e) > tol1)
        {
            double p = (x-v)*(x-v)*(fx-fw) - (x-w)*(x-w)*(fx-fv);
            double q = 2.0*((x-v)*(fx-fw) - (x-w)*(fx-fv));
            
            if (q > 0.0) 
                p = -p;
            q = fabs(q);
            
            double etemp = e;
            e = d;
            if (fabs(p) >= fabs(0.5*q*etemp) || 
                p <= q*(a - x) || 
                p >= q*(b - x))
            {
                if (x >= xm) 
                    e = a - x; 
                else 
                    e = b - x;
                d = CGOLD*(e);
            }   
            else
            {
                d = p/q;
                u = x + d;
                if (u - a < tol2 || b - u < tol2)
                    d = SIGN(tol1, xm - x);
            }
        } 
        else 
        {
            if (x >= xm) 
                    e = a - x; 
                else 
                    e = b - x;
            d = CGOLD *(e);
        }
        
        double u;
        if(fabs(d) >= tol1)
            u = x + d;
        else
            u = x + SIGN(tol1, d);
        double fu = error(grnn, u);
        if (fu <= fx) 
        {
            if (u >= x) 
                a = x; 
            else 
                b = x;
            SHFT(v, w, x, u);
            SHFT(fv, fw, fx, fu);
        } 
        else 
        {
            if (u < x) 
                a = u; 
            else
                b = u;
            if (fu <= fw || w == x)
            {
                v = w;
                w = u;
                fv = fw;
                fw = fu;
            } 
            else if (fu <= fv || v == x || v == w) 
            {
                v = u;
                fv = fu;
            }
        }
    }
    grnn.setBandwidth(x);
}