SimulatorReport AdaptiveTimeStepping:: stepImpl( const SimulatorTimer& simulatorTimer, Solver& solver, State& state, WState& well_state, Output* outputWriter ) { SimulatorReport report; const double timestep = simulatorTimer.currentStepLength(); // init last time step as a fraction of the given time step if( suggested_next_timestep_ < 0 ) { suggested_next_timestep_ = restart_factor_ * timestep; } if (full_timestep_initially_) { suggested_next_timestep_ = timestep; } // TODO // take change in well state into account // create adaptive step timer with previously used sub step size AdaptiveSimulatorTimer substepTimer( simulatorTimer, suggested_next_timestep_, max_time_step_ ); // copy states in case solver has to be restarted (to be revised) State last_state( state ); WState last_well_state( well_state ); // counter for solver restarts int restarts = 0; // sub step time loop while( ! substepTimer.done() ) { // get current delta t const double dt = substepTimer.currentStepLength() ; if( timestep_verbose_ ) { std::ostringstream ss; ss <<" Substep " << substepTimer.currentStepNum() << ", stepsize " << unit::convert::to(substepTimer.currentStepLength(), unit::day) << " days."; OpmLog::info(ss.str()); } SimulatorReport substepReport; try { substepReport = solver.step( substepTimer, state, well_state); report += substepReport; if( solver_verbose_ ) { // report number of linear iterations OpmLog::note("Overall linear iterations used: " + std::to_string(substepReport.total_linear_iterations)); } } catch (const Opm::NumericalProblem& e) { detail::logException(e, solver_verbose_); // since linearIterations is < 0 this will restart the solver } catch (const std::runtime_error& e) { detail::logException(e, solver_verbose_); // also catch linear solver not converged } catch (const Dune::ISTLError& e) { detail::logException(e, solver_verbose_); // also catch errors in ISTL AMG that occur when time step is too large } catch (const Dune::MatrixBlockError& e) { detail::logException(e, solver_verbose_); // this can be thrown by ISTL's ILU0 in block mode, yet is not an ISTLError } if( substepReport.converged ) { // advance by current dt ++substepTimer; // create object to compute the time error, simply forwards the call to the model detail::SolutionTimeErrorSolverWrapper< Solver, State > relativeChange( solver, last_state, state ); // compute new time step estimate double dtEstimate = timeStepControl_->computeTimeStepSize( dt, substepReport.total_linear_iterations, relativeChange, substepTimer.simulationTimeElapsed()); // limit the growth of the timestep size by the growth factor dtEstimate = std::min( dtEstimate, double(max_growth_ * dt) ); // further restrict time step size growth after convergence problems if( restarts > 0 ) { dtEstimate = std::min( growth_factor_ * dt, dtEstimate ); // solver converged, reset restarts counter restarts = 0; } if( timestep_verbose_ ) { std::ostringstream ss; ss << " Substep summary: "; if (report.total_well_iterations != 0) { ss << "well iterations = " << report.total_well_iterations << ", "; } ss << "newton iterations = " << report.total_newton_iterations << ", " << "linearizations = " << report.total_linearizations << " (" << report.assemble_time << " sec), " << "linear iterations = " << report.total_linear_iterations << " (" << report.linear_solve_time << " sec)"; OpmLog::info(ss.str()); } // write data if outputWriter was provided // if the time step is done we do not need // to write it as this will be done by the simulator // anyway. if( outputWriter && !substepTimer.done() ) { Opm::time::StopWatch perfTimer; perfTimer.start(); bool substep = true; const auto& physicalModel = solver.model(); outputWriter->writeTimeStep( substepTimer, state, well_state, physicalModel, substep); report.output_write_time += perfTimer.secsSinceStart(); } // set new time step length substepTimer.provideTimeStepEstimate( dtEstimate ); // update states last_state = state ; last_well_state = well_state; report.converged = substepTimer.done(); } else // in case of no convergence (linearIterations < 0) { report.converged = false; // increase restart counter if( restarts >= solver_restart_max_ ) { const auto msg = std::string("Solver failed to converge after ") + std::to_string(restarts) + " restarts."; if (solver_verbose_) { OpmLog::error(msg); } OPM_THROW_NOLOG(Opm::NumericalProblem, msg); } const double newTimeStep = restart_factor_ * dt; // we need to revise this substepTimer.provideTimeStepEstimate( newTimeStep ); if( solver_verbose_ ) { std::string msg; msg = "Solver convergence failed, restarting solver with new time step (" + std::to_string(unit::convert::to( newTimeStep, unit::day )) + " days).\n"; OpmLog::problem(msg); } // reset states state = last_state; well_state = last_well_state; ++restarts; } } // store estimated time step for next reportStep suggested_next_timestep_ = substepTimer.currentStepLength(); if( timestep_verbose_ ) { std::ostringstream ss; substepTimer.report(ss); ss << "Suggested next step size = " << unit::convert::to( suggested_next_timestep_, unit::day ) << " (days)" << std::endl; OpmLog::note(ss.str()); } if( ! std::isfinite( suggested_next_timestep_ ) ) { // check for NaN suggested_next_timestep_ = timestep; } return report; }
int main(void) { float *a = createvect(NUM), *b = createvect(NUM); // incrementing up to 20 setvect(NUM, a, 1); basicIncrement(NUM, a); printf("0: a = "); printvect(NUM, a); printf("\n"); // nested while loop setvect(NUM, a, 1); setvect(NUM, b, 2); nested(NUM, a, b); printf("1: a = "); printvect(NUM, a); printf("\n"); printf(" b = "); printvect(NUM, b); printf("\n"); // nested while loop setvect(NUM, a, 1); setvect(NUM, b, 2); nested2(NUM, a, b); printf("2: a = "); printvect(NUM, a); printf("\n"); printf(" b = "); printvect(NUM, b); printf("\n"); // a and b changing relative to each other setvect(NUM, a, 1); setvect(NUM, b, 2); relativeChange(NUM, a, b); printf("3: a = "); printvect(NUM, a); printf("\n"); printf(" b = "); printvect(NUM, b); printf("\n"); // while with an if loop inside it setvect(NUM, a, 1); setvect(NUM, b, 3); whileIf(NUM, a, b); printf("4: a = "); printvect(NUM, a); printf("\n"); printf(" b = "); printvect(NUM, b); printf("\n"); // if with a while loop inside it setvect(NUM, a, 1); setvect(NUM, b, 0); ifWhile(NUM, a, b); printf("5: a = "); printvect(NUM, a); printf("\n"); printf(" b = "); printvect(NUM, b); printf("\n"); // else in big if else statement setvect(NUM, a, 1); setvect(NUM, b, 4); ifWhile(NUM, a, b); printf("6: a = "); printvect(NUM, a); printf("\n"); printf(" b = "); printvect(NUM, b); printf("\n"); return 0; }