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;
    }
Foam::coupledSolverPerformance Foam::coupledSmoothSolver::solve
(
    FieldField<Field, scalar>& x,
    const FieldField<Field, scalar>& b,
    const direction cmpt
) const
{
    // Prepare solver performance
    coupledSolverPerformance solverPerf(typeName, fieldName());

    // Do a minimum number of sweeps
    // HJ, 19/Jan/2009
    if (minIter() > 0)
    {
        autoPtr<coupledLduSmoother> smootherPtr = coupledLduSmoother::New
        (
            matrix_,
            bouCoeffs_,
            intCoeffs_,
            interfaces_,
            dict()
        );

        smootherPtr->smooth
        (
            x,
            b,
            cmpt,
            minIter()
        );

        solverPerf.nIterations() += minIter();
    }

    // Now do normal sweeps.  HJ, 19/Jan/2009

    FieldField<Field, scalar> Ax(x.size());
    FieldField<Field, scalar> temp(x.size());

    forAll (x, rowI)
    {
        Ax.set(rowI, new scalarField(x[rowI].size(), 0));
        temp.set(rowI, new scalarField(x[rowI].size(), 0));
    }
    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;
    }
示例#4
0
    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;
    }