00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 namespace Opm
00024 {
00025
00026 template <class GridT>
00027 auto SimulatorFullyImplicitBlackoilMultiSegment<GridT>::
00028 createSolver(const WellModel& well_model)
00029 -> std::unique_ptr<Solver>
00030 {
00031 typedef typename Traits::Model Model;
00032
00033 auto model = std::unique_ptr<Model>(new Model(model_param_,
00034 grid_,
00035 props_,
00036 geo_,
00037 rock_comp_props_,
00038 well_model,
00039 solver_,
00040 eclipse_state_,
00041 has_disgas_,
00042 has_vapoil_,
00043 terminal_output_));
00044
00045 if (!Base::threshold_pressures_by_face_.empty()) {
00046 model->setThresholdPressures(Base::threshold_pressures_by_face_);
00047 }
00048
00049 return std::unique_ptr<ThisType::Solver>(new Solver(Base::solver_param_, std::move(model)));
00050
00051 }
00052
00053 template <class GridT>
00054 SimulatorReport SimulatorFullyImplicitBlackoilMultiSegment<GridT>::run(SimulatorTimer& timer,
00055 ReservoirState& state)
00056 {
00057 WellState prev_well_state;
00058
00059
00060 Opm::time::StopWatch solver_timer;
00061 double stime = 0.0;
00062 Opm::time::StopWatch step_timer;
00063 Opm::time::StopWatch total_timer;
00064 total_timer.start();
00065 std::string tstep_filename = output_writer_.outputDirectory() + "/step_timing.txt";
00066 std::ofstream tstep_os(tstep_filename.c_str());
00067
00068
00069 const auto& events = eclipse_state_->getSchedule().getEvents();
00070 std::unique_ptr< AdaptiveTimeStepping > adaptiveTimeStepping;
00071 if( param_.getDefault("timestep.adaptive", true ) )
00072 {
00073 adaptiveTimeStepping.reset( new AdaptiveTimeStepping( param_, terminal_output_ ) );
00074 }
00075
00076 std::string restorefilename = param_.getDefault("restorefile", std::string("") );
00077 if( ! restorefilename.empty() )
00078 {
00079
00080 const int desiredRestoreStep = param_.getDefault("restorestep", int(-1) );
00081 output_writer_.restore( timer,
00082 state,
00083 prev_well_state,
00084 restorefilename,
00085 desiredRestoreStep );
00086 }
00087
00088 unsigned int totalNonlinearIterations = 0;
00089 unsigned int totalLinearIterations = 0;
00090 DynamicListEconLimited dynamic_list_econ_limited;
00091
00092 bool ooip_computed = false;
00093 std::vector<int> fipnum_global = eclipse_state_->get3DProperties().getIntGridProperty("FIPNUM").getData();
00094
00095 std::vector<int> fipnum(AutoDiffGrid::numCells(grid_));
00096 if (fipnum_global.empty()) {
00097 std::fill(fipnum.begin(), fipnum.end(), 0);
00098 } else {
00099 for (size_t c = 0; c < fipnum.size(); ++c) {
00100 fipnum[c] = fipnum_global[AutoDiffGrid::globalCell(grid_)[c]];
00101 }
00102 }
00103 std::vector<std::vector<double> > OOIP;
00104
00105
00106 while (!timer.done()) {
00107
00108 step_timer.start();
00109 if ( terminal_output_ )
00110 {
00111 timer.report(std::cout);
00112 }
00113
00114
00115 WellsManager wells_manager(*eclipse_state_,
00116 timer.currentStepNum(),
00117 Opm::UgGridHelpers::numCells(grid_),
00118 Opm::UgGridHelpers::globalCell(grid_),
00119 Opm::UgGridHelpers::cartDims(grid_),
00120 Opm::UgGridHelpers::dimensions(grid_),
00121 Opm::UgGridHelpers::cell2Faces(grid_),
00122 Opm::UgGridHelpers::beginFaceCentroids(grid_),
00123 dynamic_list_econ_limited,
00124 is_parallel_run_,
00125
00126
00127
00128
00129 Base::defunct_well_names_);
00130 const Wells* wells = wells_manager.c_wells();
00131 WellState well_state;
00132
00133
00134 const auto wells_ecl = eclipse_state_->getSchedule().getWells(timer.currentStepNum());
00135 const int current_time_step = timer.currentStepNum();
00136
00137 const WellModel well_model(wells, &(wells_manager.wellCollection()), wells_ecl, current_time_step);
00138
00139 well_state.init(well_model, state, prev_well_state, wells);
00140
00141
00142 Base::asImpl().handleAdditionalWellInflow(timer, wells_manager, well_state, wells);
00143
00144
00145 if (timer.initialStep()) {
00146
00147
00148 output_writer_.writeTimeStepWithoutCellProperties( timer, state, well_state, {}, {} );
00149 }
00150
00151
00152 props_.updateSatOilMax(state.saturation());
00153 props_.updateSatHyst(state.saturation(), allcells_);
00154
00155
00156 Base::asImpl().computeRESV(timer.currentStepNum(), wells, state, well_state);
00157
00158
00159 solver_timer.start();
00160
00161 auto solver = createSolver(well_model);
00162
00163
00164 if (!ooip_computed) {
00165 OOIP = solver->computeFluidInPlace(state, fipnum);
00166 Base::FIPUnitConvert(eclipse_state_->getUnits(), OOIP);
00167 ooip_computed = true;
00168 }
00169
00170
00171
00172
00173
00174
00175 if( adaptiveTimeStepping ) {
00176 bool event = events.hasEvent(ScheduleEvents::NEW_WELL, timer.currentStepNum()) ||
00177 events.hasEvent(ScheduleEvents::PRODUCTION_UPDATE, timer.currentStepNum()) ||
00178 events.hasEvent(ScheduleEvents::INJECTION_UPDATE, timer.currentStepNum()) ||
00179 events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE, timer.currentStepNum());
00180 adaptiveTimeStepping->step( timer, *solver, state, well_state, event, output_writer_);
00181 }
00182 else {
00183
00184 solver->step(timer, state, well_state);
00185 }
00186
00187
00188 solver_timer.stop();
00189
00190
00191 totalNonlinearIterations += solver->nonlinearIterations();
00192 totalLinearIterations += solver->linearIterations();
00193
00194
00195 const double st = solver_timer.secsSinceStart();
00196
00197
00198 std::vector<std::vector<double> > COIP;
00199 COIP = solver->computeFluidInPlace(state, fipnum);
00200 std::vector<double> OOIP_totals = Base::FIPTotals(OOIP, state);
00201 std::vector<double> COIP_totals = Base::FIPTotals(COIP, state);
00202
00203
00204 Base::FIPUnitConvert(eclipse_state_->getUnits(), COIP);
00205 Base::FIPUnitConvert(eclipse_state_->getUnits(), OOIP_totals);
00206 Base::FIPUnitConvert(eclipse_state_->getUnits(), COIP_totals);
00207
00208 if ( terminal_output_ )
00209 {
00210 Base::outputFluidInPlace(OOIP_totals, COIP_totals,eclipse_state_->getUnits(), 0);
00211 for (size_t reg = 0; reg < OOIP.size(); ++reg) {
00212 Base::outputFluidInPlace(OOIP[reg], COIP[reg], eclipse_state_->getUnits(), reg+1);
00213 }
00214 }
00215
00216 if ( terminal_output_ )
00217 {
00218 std::cout << "Fully implicit solver took: " << st << " seconds." << std::endl;
00219 }
00220
00221 stime += st;
00222 if ( output_writer_.output() ) {
00223 SimulatorReport step_report;
00224 step_report.solver_time = st;
00225 step_report.total_time = step_timer.secsSinceStart();
00226 step_report.reportParam(tstep_os);
00227 }
00228
00229
00230 ++timer;
00231
00232
00233
00234 const auto& physicalModel = solver->model();
00235 output_writer_.writeTimeStep( timer, state, well_state, physicalModel );
00236
00237 prev_well_state = well_state;
00238 }
00239
00240
00241 total_timer.stop();
00242 SimulatorReport report;
00243 report.total_time = total_timer.secsSinceStart();
00244 report.solver_time = stime;
00245 report.total_newton_iterations = totalNonlinearIterations;
00246 report.total_linear_iterations = totalLinearIterations;
00247 return report;
00248 }
00249
00250 }