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; }
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; }