00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef OPM_SIMULATORFULLYIMPLICITBLACKOILOUTPUT_HEADER_INCLUDED
00021 #define OPM_SIMULATORFULLYIMPLICITBLACKOILOUTPUT_HEADER_INCLUDED
00022 #include <opm/core/grid.h>
00023 #include <opm/simulators/timestepping/SimulatorTimerInterface.hpp>
00024 #include <opm/core/simulator/WellState.hpp>
00025 #include <opm/autodiff/Compat.hpp>
00026 #include <opm/core/utility/DataMap.hpp>
00027 #include <opm/common/ErrorMacros.hpp>
00028 #include <opm/common/OpmLog/OpmLog.hpp>
00029 #include <opm/core/utility/miscUtilities.hpp>
00030 #include <opm/core/utility/parameters/ParameterGroup.hpp>
00031 #include <opm/core/wells/DynamicListEconLimited.hpp>
00032 #include <opm/core/simulator/BlackoilState.hpp>
00033 #include <opm/core/simulator/SimulatorReport.hpp>
00034
00035 #include <opm/output/data/Cells.hpp>
00036 #include <opm/output/data/Solution.hpp>
00037 #include <opm/output/eclipse/EclipseIO.hpp>
00038
00039 #include <opm/autodiff/GridHelpers.hpp>
00040 #include <opm/autodiff/ParallelDebugOutput.hpp>
00041
00042 #include <opm/autodiff/WellStateFullyImplicitBlackoil.hpp>
00043 #include <opm/autodiff/ThreadHandle.hpp>
00044 #include <opm/autodiff/AutoDiffBlock.hpp>
00045
00046 #include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
00047 #include <opm/parser/eclipse/EclipseState/InitConfig/InitConfig.hpp>
00048 #include <opm/simulators/ensureDirectoryExists.hpp>
00049
00050 #include <string>
00051 #include <sstream>
00052 #include <iomanip>
00053 #include <fstream>
00054 #include <thread>
00055 #include <map>
00056
00057 #include <boost/filesystem.hpp>
00058
00059 #ifdef HAVE_OPM_GRID
00060 #include <dune/grid/CpGrid.hpp>
00061 #endif
00062 namespace Opm
00063 {
00064
00065 class SimulationDataContainer;
00066 class BlackoilState;
00067
00068 void outputStateVtk(const UnstructuredGrid& grid,
00069 const Opm::SimulationDataContainer& state,
00070 const int step,
00071 const std::string& output_dir);
00072
00073 void outputWellStateMatlab(const Opm::WellState& well_state,
00074 const int step,
00075 const std::string& output_dir);
00076 #ifdef HAVE_OPM_GRID
00077 void outputStateVtk(const Dune::CpGrid& grid,
00078 const Opm::SimulationDataContainer& state,
00079 const int step,
00080 const std::string& output_dir);
00081 #endif
00082
00083 template<class Grid>
00084 void outputStateMatlab(const Grid& grid,
00085 const Opm::SimulationDataContainer& state,
00086 const int step,
00087 const std::string& output_dir)
00088 {
00089 Opm::DataMap dm;
00090 dm["saturation"] = &state.saturation();
00091 dm["pressure"] = &state.pressure();
00092 for (const auto& pair : state.cellData())
00093 {
00094 const std::string& name = pair.first;
00095 std::string key;
00096 if( name == "SURFACEVOL" ) {
00097 key = "surfvolume";
00098 }
00099 else if( name == "RV" ) {
00100 key = "rv";
00101 }
00102 else if( name == "GASOILRATIO" ) {
00103 key = "rs";
00104 }
00105 else {
00106 continue;
00107 }
00108
00109 dm[ key ] = &pair.second;
00110 }
00111
00112 std::vector<double> cell_velocity;
00113 Opm::estimateCellVelocity(AutoDiffGrid::numCells(grid),
00114 AutoDiffGrid::numFaces(grid),
00115 AutoDiffGrid::beginFaceCentroids(grid),
00116 UgGridHelpers::faceCells(grid),
00117 AutoDiffGrid::beginCellCentroids(grid),
00118 AutoDiffGrid::beginCellVolumes(grid),
00119 AutoDiffGrid::dimensions(grid),
00120 state.faceflux(), cell_velocity);
00121 dm["velocity"] = &cell_velocity;
00122
00123
00124 for (Opm::DataMap::const_iterator it = dm.begin(); it != dm.end(); ++it) {
00125 std::ostringstream fname;
00126 fname << output_dir << "/" << it->first;
00127 ensureDirectoryExists(fname.str());
00128 fname << "/" << std::setw(3) << std::setfill('0') << step << ".txt";
00129 std::ofstream file(fname.str().c_str());
00130 if (!file) {
00131 OPM_THROW(std::runtime_error, "Failed to open " << fname.str());
00132 }
00133 file.precision(15);
00134 const std::vector<double>& d = *(it->second);
00135 std::copy(d.begin(), d.end(), std::ostream_iterator<double>(file, "\n"));
00136 }
00137 }
00138
00139 class BlackoilSubWriter {
00140 public:
00141 BlackoilSubWriter( const std::string& outputDir )
00142 : outputDir_( outputDir )
00143 {}
00144
00145 virtual void writeTimeStep(const SimulatorTimerInterface& timer,
00146 const SimulationDataContainer& state,
00147 const WellStateFullyImplicitBlackoil&,
00148 bool = false) = 0;
00149 protected:
00150 const std::string outputDir_;
00151 };
00152
00153 template< class Grid >
00154 class BlackoilVTKWriter : public BlackoilSubWriter {
00155 public:
00156 BlackoilVTKWriter( const Grid& grid,
00157 const std::string& outputDir )
00158 : BlackoilSubWriter( outputDir )
00159 , grid_( grid )
00160 {}
00161
00162 void writeTimeStep(const SimulatorTimerInterface& timer,
00163 const SimulationDataContainer& state,
00164 const WellStateFullyImplicitBlackoil&,
00165 bool = false) override
00166 {
00167 outputStateVtk(grid_, state, timer.currentStepNum(), outputDir_);
00168 }
00169
00170 protected:
00171 const Grid& grid_;
00172 };
00173
00174 template< typename Grid >
00175 class BlackoilMatlabWriter : public BlackoilSubWriter
00176 {
00177 public:
00178 BlackoilMatlabWriter( const Grid& grid,
00179 const std::string& outputDir )
00180 : BlackoilSubWriter( outputDir )
00181 , grid_( grid )
00182 {}
00183
00184 void writeTimeStep(const SimulatorTimerInterface& timer,
00185 const SimulationDataContainer& reservoirState,
00186 const WellStateFullyImplicitBlackoil& wellState,
00187 bool = false) override
00188 {
00189 outputStateMatlab(grid_, reservoirState, timer.currentStepNum(), outputDir_);
00190 outputWellStateMatlab(wellState, timer.currentStepNum(), outputDir_);
00191 }
00192
00193 protected:
00194 const Grid& grid_;
00195 };
00196
00197
00199 struct ExtraData
00200 {
00201 double suggested_step = -1.0;
00202 };
00203
00204
00206 class BlackoilOutputWriter
00207 {
00208
00209 public:
00210
00211 template <class Grid>
00212 BlackoilOutputWriter(const Grid& grid,
00213 const ParameterGroup& param,
00214 const Opm::EclipseState& eclipseState,
00215 std::unique_ptr<EclipseIO>&& eclIO,
00216 const Opm::PhaseUsage &phaseUsage);
00217
00219 void writeInit(const data::Solution& simProps, const NNC& nnc);
00220
00227 template<class Model>
00228 void writeTimeStep(const SimulatorTimerInterface& timer,
00229 const SimulationDataContainer& reservoirState,
00230 const Opm::WellStateFullyImplicitBlackoil& wellState,
00231 const Model& physicalModel,
00232 const bool substep = false,
00233 const double nextstep = -1.0,
00234 const SimulatorReport& simulatorReport = SimulatorReport());
00235
00236
00242 void writeTimeStepWithCellProperties(
00243 const SimulatorTimerInterface& timer,
00244 const SimulationDataContainer& reservoirState,
00245 const data::Solution& cellData,
00246 const Opm::WellStateFullyImplicitBlackoil& wellState,
00247 const std::map<std::string, double>& miscSummaryData,
00248 const std::map<std::string, std::vector<double>>& extraRestartData,
00249 bool substep = false);
00250
00256 void writeTimeStepWithoutCellProperties(
00257 const SimulatorTimerInterface& timer,
00258 const SimulationDataContainer& reservoirState,
00259 const Opm::WellStateFullyImplicitBlackoil& wellState,
00260 const std::map<std::string, double>& miscSummaryData,
00261 const std::map<std::string, std::vector<double>>& extraRestartData,
00262 bool substep = false);
00263
00269 void writeTimeStepSerial(const SimulatorTimerInterface& timer,
00270 const SimulationDataContainer& reservoirState,
00271 const Opm::WellStateFullyImplicitBlackoil& wellState,
00272 const data::Solution& simProps,
00273 const std::map<std::string, double>& miscSummaryData,
00274 const std::map<std::string, std::vector<double>>& extraRestartData,
00275 bool substep );
00276
00278 const std::string& outputDirectory() const { return outputDir_; }
00279
00281 bool output () const { return output_; }
00282
00284 bool isIORank () const
00285 {
00286 return parallelOutput_->isIORank();
00287 }
00288
00289 void restore(SimulatorTimerInterface& timer,
00290 BlackoilState& state,
00291 WellStateFullyImplicitBlackoil& wellState,
00292 const std::string& filename,
00293 const int desiredReportStep);
00294
00295
00296 template <class Grid, class WellState>
00297 void initFromRestartFile(const PhaseUsage& phaseUsage,
00298 const Grid& grid,
00299 SimulationDataContainer& simulatorstate,
00300 WellState& wellstate,
00301 ExtraData& extra);
00302
00303 bool isRestart() const;
00304
00305 bool requireFIPNUM() const;
00306
00307 protected:
00308 const bool output_;
00309 std::unique_ptr< ParallelDebugOutputInterface > parallelOutput_;
00310
00311
00312 const std::string outputDir_;
00313 const bool restart_double_si_;
00314
00315 int lastBackupReportStep_;
00316
00317 std::ofstream backupfile_;
00318 Opm::PhaseUsage phaseUsage_;
00319 std::unique_ptr< BlackoilSubWriter > vtkWriter_;
00320 std::unique_ptr< BlackoilSubWriter > matlabWriter_;
00321 std::unique_ptr< EclipseIO > eclIO_;
00322 const EclipseState& eclipseState_;
00323
00324 std::unique_ptr< ThreadHandle > asyncOutput_;
00325 };
00326
00327
00329
00330
00331
00333 template <class Grid>
00334 inline
00335 BlackoilOutputWriter::
00336 BlackoilOutputWriter(const Grid& grid,
00337 const ParameterGroup& param,
00338 const Opm::EclipseState& eclipseState,
00339 std::unique_ptr<EclipseIO>&& eclIO,
00340 const Opm::PhaseUsage &phaseUsage)
00341 : output_( [ ¶m ] () -> bool {
00342
00343 const std::string outputString = param.getDefault("output", std::string("all"));
00344 return ( outputString == "all" || outputString == "true" );
00345 }()
00346 ),
00347 parallelOutput_( output_ ? new ParallelDebugOutput< Grid >( grid, eclipseState, phaseUsage.num_phases, phaseUsage ) : 0 ),
00348 outputDir_( eclipseState.getIOConfig().getOutputDir() ),
00349 restart_double_si_( output_ ? param.getDefault("restart_double_si", false) : false ),
00350 lastBackupReportStep_( -1 ),
00351 phaseUsage_( phaseUsage ),
00352 eclipseState_(eclipseState),
00353 asyncOutput_()
00354 {
00355
00356 if ( output_ )
00357 {
00358 if ( param.getDefault("output_vtk",false) )
00359 {
00360 vtkWriter_
00361 .reset(new BlackoilVTKWriter< Grid >( grid, outputDir_ ));
00362 }
00363
00364 auto output_matlab = param.getDefault("output_matlab", false );
00365
00366 if ( parallelOutput_->isParallel() && output_matlab )
00367 {
00368 Opm::OpmLog::warning("Parallel Output Config",
00369 "Velocity output for matlab is broken in parallel.");
00370 }
00371
00372 if( parallelOutput_->isIORank() ) {
00373
00374 if ( output_matlab )
00375 {
00376 matlabWriter_
00377 .reset(new BlackoilMatlabWriter< Grid >( grid, outputDir_ ));
00378 }
00379
00380 eclIO_ = std::move(eclIO);
00381
00382
00383 ensureDirectoryExists(outputDir_);
00384
00385 std::string backupfilename = param.getDefault("backupfile", std::string("") );
00386 if( ! backupfilename.empty() )
00387 {
00388 backupfile_.open( backupfilename.c_str() );
00389 }
00390 }
00391
00392
00393
00394 #if HAVE_PTHREAD
00395 const bool asyncOutputDefault = true;
00396 #else
00397 const bool asyncOutputDefault = false;
00398 #endif
00399 if( param.getDefault("async_output", asyncOutputDefault ) )
00400 {
00401 const bool isIORank = parallelOutput_ ? parallelOutput_->isIORank() : true;
00402 #if HAVE_PTHREAD
00403 asyncOutput_.reset( new ThreadHandle( isIORank ) );
00404 #else
00405 OPM_THROW(std::runtime_error,"Pthreads were not found, cannot enable async_output");
00406 #endif
00407 }
00408 }
00409 }
00410
00411
00412 template <class Grid, class WellState>
00413 inline void
00414 BlackoilOutputWriter::
00415 initFromRestartFile( const PhaseUsage& phaseUsage,
00416 const Grid& grid,
00417 SimulationDataContainer& simulatorstate,
00418 WellState& wellstate,
00419 ExtraData& extra )
00420 {
00421 std::map<std::string, RestartKey> solution_keys {{"PRESSURE" , RestartKey(UnitSystem::measure::pressure)},
00422 {"SWAT" , RestartKey(UnitSystem::measure::identity)},
00423 {"SGAS" , RestartKey(UnitSystem::measure::identity)},
00424 {"TEMP" , RestartKey(UnitSystem::measure::temperature)},
00425 {"RS" , RestartKey(UnitSystem::measure::gas_oil_ratio)},
00426 {"RV" , RestartKey(UnitSystem::measure::oil_gas_ratio)},
00427 {"SOMAX", {UnitSystem::measure::identity, false}},
00428 {"PCSWM_OW", {UnitSystem::measure::identity, false}},
00429 {"KRNSW_OW", {UnitSystem::measure::identity, false}},
00430 {"PCSWM_GO", {UnitSystem::measure::identity, false}},
00431 {"KRNSW_GO", {UnitSystem::measure::identity, false}}};
00432
00433 std::map<std::string, bool> extra_keys {
00434 {"OPMEXTRA" , false}
00435 };
00436
00437 if (restart_double_si_) {
00438
00439 for (auto& elem : solution_keys) {
00440 elem.second = RestartKey(UnitSystem::measure::identity);
00441 }
00442 }
00443
00444
00445 DynamicListEconLimited dummy_list_econ_limited;
00446 WellsManager wellsmanager(eclipseState_,
00447 eclipseState_.getInitConfig().getRestartStep(),
00448 Opm::UgGridHelpers::numCells(grid),
00449 Opm::UgGridHelpers::globalCell(grid),
00450 Opm::UgGridHelpers::cartDims(grid),
00451 Opm::UgGridHelpers::dimensions(grid),
00452 Opm::UgGridHelpers::cell2Faces(grid),
00453 Opm::UgGridHelpers::beginFaceCentroids(grid),
00454 dummy_list_econ_limited
00455
00456
00457
00458
00459 , false,
00460 std::unordered_set<std::string>());
00461
00462 const Wells* wells = wellsmanager.c_wells();
00463 wellstate.resize(wells, simulatorstate, phaseUsage );
00464 auto restart_values = eclIO_->loadRestart(solution_keys, extra_keys);
00465
00466 solutionToSim( restart_values.solution, restart_values.extra, phaseUsage, simulatorstate );
00467 wellsToState( restart_values.wells, phaseUsage, wellstate );
00468
00469 const auto opmextra_iter = restart_values.extra.find("OPMEXTRA");
00470 if (opmextra_iter != restart_values.extra.end()) {
00471 std::vector<double> opmextra = opmextra_iter->second;
00472 assert(opmextra.size() == 1);
00473 extra.suggested_step = opmextra[0];
00474 } else {
00475 OpmLog::warning("Restart data is missing OPMEXTRA field, restart run may deviate from original run.");
00476 extra.suggested_step = -1.0;
00477 }
00478 }
00479
00480
00481
00482
00483
00484 namespace detail {
00485
00486
00487 template <class V>
00488 void addToSimData( SimulationDataContainer& simData,
00489 const std::string& name,
00490 const V& vec )
00491 {
00492 if (vec.size() == 0) {
00493 return;
00494 }
00495
00496 typedef std::vector< double > OutputVectorType;
00497
00498
00499 auto& dataMap = simData.cellData();
00500
00501
00502 dataMap.insert( std::make_pair( name, OutputVectorType( vec.data(), vec.data() + vec.size() ) ) );
00503 }
00504
00505 template <class Scalar>
00506 void addToSimData( SimulationDataContainer& simData,
00507 const std::string& name,
00508 const AutoDiffBlock<Scalar>& adb )
00509 {
00510
00511 addToSimData( simData, name, adb.value() );
00512 }
00513
00514
00515
00516
00517 template <class SimulatorData>
00518 SimulationDataContainer
00519 convertToSimulationDataContainer( const SimulatorData& sd,
00520 const SimulationDataContainer& localState,
00521 const Opm::PhaseUsage& phaseUsage )
00522 {
00523
00524 SimulationDataContainer simData( localState );
00525
00526
00527 const int aqua_active = phaseUsage.phase_used[Opm::PhaseUsage::Aqua];
00528 const int liquid_active = phaseUsage.phase_used[Opm::PhaseUsage::Liquid];
00529 const int vapour_active = phaseUsage.phase_used[Opm::PhaseUsage::Vapour];
00530
00531 const int aqua_idx = phaseUsage.phase_pos[Opm::PhaseUsage::Aqua];
00532 const int liquid_idx = phaseUsage.phase_pos[Opm::PhaseUsage::Liquid];
00533 const int vapour_idx = phaseUsage.phase_pos[Opm::PhaseUsage::Vapour];
00534
00535
00536 if( aqua_active ) {
00537 addToSimData( simData, "1OVERBW", sd.rq[aqua_idx].b );
00538 addToSimData( simData, "WAT_DEN", sd.rq[aqua_idx].rho );
00539 addToSimData( simData, "WAT_VISC", sd.rq[aqua_idx].mu );
00540 addToSimData( simData, "WATKR", sd.rq[aqua_idx].kr );
00541 }
00542
00543
00544 if( liquid_active ) {
00545 addToSimData( simData, "1OVERBO", sd.rq[liquid_idx].b );
00546 addToSimData( simData, "OIL_DEN", sd.rq[liquid_idx].rho );
00547 addToSimData( simData, "OIL_VISC", sd.rq[liquid_idx].mu );
00548 addToSimData( simData, "OILKR", sd.rq[liquid_idx].kr );
00549 }
00550
00551
00552 if( vapour_active ) {
00553 addToSimData( simData, "1OVERBG", sd.rq[vapour_idx].b );
00554 addToSimData( simData, "GAS_DEN", sd.rq[vapour_idx].rho );
00555 addToSimData( simData, "GAS_VISC", sd.rq[vapour_idx].mu );
00556 addToSimData( simData, "GASKR", sd.rq[vapour_idx].kr );
00557 }
00558
00559
00560 addToSimData( simData, "RSSAT", sd.rsSat );
00561 addToSimData( simData, "RVSAT", sd.rvSat );
00562
00563 addToSimData( simData, "SOMAX", sd.soMax );
00564 addToSimData( simData, "PBUB", sd.Pb );
00565 addToSimData( simData, "PDEW", sd.Pd );
00566 addToSimData( simData, "PCSWMDC_OW", sd.pcswmdc_ow );
00567 addToSimData( simData, "KRNSWMDC_OW", sd.krnswdc_ow );
00568 addToSimData( simData, "PCSWMDC_GO", sd.pcswmdc_go );
00569 addToSimData( simData, "KRNSWMDC_GO", sd.krnswdc_go );
00570
00571 return simData;
00572 }
00573
00574
00575
00576 inline
00577 SimulationDataContainer&&
00578 convertToSimulationDataContainer( SimulationDataContainer&& sd,
00579 const SimulationDataContainer& ,
00580 const Opm::PhaseUsage& )
00581 {
00582 return std::move( sd );
00583 }
00584
00590 template<class Model>
00591 void getRestartData(data::Solution& output,
00592 SimulationDataContainer&& sd,
00593 const Opm::PhaseUsage& ,
00594 const Model& ,
00595 const RestartConfig& restartConfig,
00596 const int reportStepNum,
00597 const bool log)
00598 {
00599
00600 std::map<std::string, int> rstKeywords = restartConfig.getRestartKeywords(reportStepNum);
00601 for (auto& keyValue : rstKeywords) {
00602 keyValue.second = restartConfig.getKeyword(keyValue.first, reportStepNum);
00603 }
00604
00605 const bool aqua_active = sd.hasCellData("1OVERBW");
00606 const bool liquid_active = sd.hasCellData("1OVERBO");
00607 const bool vapour_active = sd.hasCellData("1OVERBG");
00608
00609 assert( aqua_active == (sd.hasCellData("WAT_DEN") &&
00610 sd.hasCellData("WAT_VISC") &&
00611 sd.hasCellData("WATKR")
00612 )
00613 );
00614 assert( liquid_active == (sd.hasCellData("OIL_DEN") &&
00615 sd.hasCellData("OIL_VISC") &&
00616 sd.hasCellData("OILKR")
00617 )
00618 );
00619 assert( vapour_active == (sd.hasCellData("GAS_DEN") &&
00620 sd.hasCellData("GAS_VISC") &&
00621 sd.hasCellData("GASKR")
00622 )
00623 );
00624
00628 if (aqua_active && rstKeywords["BW"] > 0) {
00629 rstKeywords["BW"] = 0;
00630 output.insert("1OVERBW",
00631 Opm::UnitSystem::measure::water_inverse_formation_volume_factor,
00632 std::move( sd.getCellData("1OVERBW") ),
00633 data::TargetType::RESTART_AUXILIARY);
00634 }
00635 if (liquid_active && rstKeywords["BO"] > 0) {
00636 rstKeywords["BO"] = 0;
00637 output.insert("1OVERBO",
00638 Opm::UnitSystem::measure::oil_inverse_formation_volume_factor,
00639 std::move( sd.getCellData("1OVERBO") ),
00640 data::TargetType::RESTART_AUXILIARY);
00641 }
00642 if (vapour_active && rstKeywords["BG"] > 0) {
00643 rstKeywords["BG"] = 0;
00644 output.insert("1OVERBG",
00645 Opm::UnitSystem::measure::gas_inverse_formation_volume_factor,
00646 std::move( sd.getCellData("1OVERBG") ),
00647 data::TargetType::RESTART_AUXILIARY);
00648 }
00649
00653 if (rstKeywords["DEN"] > 0) {
00654 rstKeywords["DEN"] = 0;
00655 if (aqua_active) {
00656 output.insert("WAT_DEN",
00657 Opm::UnitSystem::measure::density,
00658 std::move( sd.getCellData("WAT_DEN") ),
00659 data::TargetType::RESTART_AUXILIARY);
00660 }
00661 if (liquid_active) {
00662 output.insert("OIL_DEN",
00663 Opm::UnitSystem::measure::density,
00664 std::move( sd.getCellData("OIL_DEN") ),
00665 data::TargetType::RESTART_AUXILIARY);
00666 }
00667 if (vapour_active) {
00668 output.insert("GAS_DEN",
00669 Opm::UnitSystem::measure::density,
00670 std::move( sd.getCellData("GAS_DEN") ),
00671 data::TargetType::RESTART_AUXILIARY);
00672 }
00673 }
00674
00678 {
00679 const bool has_vwat = (rstKeywords["VISC"] > 0) || (rstKeywords["VWAT"] > 0);
00680 const bool has_voil = (rstKeywords["VISC"] > 0) || (rstKeywords["VOIL"] > 0);
00681 const bool has_vgas = (rstKeywords["VISC"] > 0) || (rstKeywords["VGAS"] > 0);
00682 rstKeywords["VISC"] = 0;
00683 if (aqua_active && has_vwat) {
00684 output.insert("WAT_VISC",
00685 Opm::UnitSystem::measure::viscosity,
00686 std::move( sd.getCellData("WAT_VISC") ),
00687 data::TargetType::RESTART_AUXILIARY);
00688 rstKeywords["VWAT"] = 0;
00689 }
00690 if (liquid_active && has_voil) {
00691 output.insert("OIL_VISC",
00692 Opm::UnitSystem::measure::viscosity,
00693 std::move( sd.getCellData("OIL_VISC") ),
00694 data::TargetType::RESTART_AUXILIARY);
00695 rstKeywords["VOIL"] = 0;
00696 }
00697 if (vapour_active && has_vgas) {
00698 output.insert("GAS_VISC",
00699 Opm::UnitSystem::measure::viscosity,
00700 std::move( sd.getCellData("GAS_VISC") ),
00701 data::TargetType::RESTART_AUXILIARY);
00702 rstKeywords["VGAS"] = 0;
00703 }
00704 }
00705
00709 if (aqua_active && rstKeywords["KRW"] > 0) {
00710 auto& krWater = sd.getCellData("WATKR");
00711 if (krWater.size() > 0) {
00712 rstKeywords["KRW"] = 0;
00713 output.insert("WATKR",
00714 Opm::UnitSystem::measure::identity,
00715 std::move( krWater ),
00716 data::TargetType::RESTART_AUXILIARY);
00717 }
00718 else {
00719 if ( log )
00720 {
00721 Opm::OpmLog::warning("Empty:WATKR",
00722 "Not emitting empty Water Rel-Perm");
00723 }
00724 }
00725 }
00726 if (liquid_active && rstKeywords["KRO"] > 0) {
00727 auto& krOil = sd.getCellData("OILKR");
00728 if (krOil.size() > 0) {
00729 rstKeywords["KRO"] = 0;
00730 output.insert("OILKR",
00731 Opm::UnitSystem::measure::identity,
00732 std::move( krOil ),
00733 data::TargetType::RESTART_AUXILIARY);
00734 }
00735 else {
00736 if ( log )
00737 {
00738 Opm::OpmLog::warning("Empty:OILKR",
00739 "Not emitting empty Oil Rel-Perm");
00740 }
00741 }
00742 }
00743 if (vapour_active && rstKeywords["KRG"] > 0) {
00744 auto& krGas = sd.getCellData("GASKR");
00745 if (krGas.size() > 0) {
00746 rstKeywords["KRG"] = 0;
00747 output.insert("GASKR",
00748 Opm::UnitSystem::measure::identity,
00749 std::move( krGas ),
00750 data::TargetType::RESTART_AUXILIARY);
00751 }
00752 else {
00753 if ( log )
00754 {
00755 Opm::OpmLog::warning("Empty:GASKR",
00756 "Not emitting empty Gas Rel-Perm");
00757 }
00758 }
00759 }
00760
00764 if (vapour_active && liquid_active && rstKeywords["RSSAT"] > 0) {
00765 rstKeywords["RSSAT"] = 0;
00766 output.insert("RSSAT",
00767 Opm::UnitSystem::measure::gas_oil_ratio,
00768 std::move( sd.getCellData("RSSAT") ),
00769 data::TargetType::RESTART_AUXILIARY);
00770 }
00771 if (vapour_active && liquid_active && rstKeywords["RVSAT"] > 0) {
00772 rstKeywords["RVSAT"] = 0;
00773 output.insert("RVSAT",
00774 Opm::UnitSystem::measure::oil_gas_ratio,
00775 std::move( sd.getCellData("RVSAT") ),
00776 data::TargetType::RESTART_AUXILIARY);
00777 }
00778
00779
00783 if (vapour_active && liquid_active && rstKeywords["PBPD"] > 0) {
00784 rstKeywords["PBPD"] = 0;
00785 if (sd.hasCellData("PBUB")) {
00786 output.insert("PBUB",
00787 Opm::UnitSystem::measure::pressure,
00788 std::move( sd.getCellData("PBUB") ),
00789 data::TargetType::RESTART_AUXILIARY);
00790 }
00791 else if (log) {
00792 Opm::OpmLog::warning("Bubble point pressure unavailable", "Output of bubble point pressure requested but not available in this simulator. Ignoring.");
00793 }
00794
00795 if (sd.hasCellData("PDEW")) {
00796 output.insert("PDEW",
00797 Opm::UnitSystem::measure::pressure,
00798 std::move( sd.getCellData("PDEW") ),
00799 data::TargetType::RESTART_AUXILIARY);
00800 }
00801 else if (log) {
00802 Opm::OpmLog::warning("Dew point pressure unavailable", "Output of dew point pressure requested but not available in this simulator. Ignoring.");
00803 }
00804
00805 }
00806
00807 if (sd.hasCellData("SOMAX")) {
00808 output.insert("SOMAX",
00809 Opm::UnitSystem::measure::identity,
00810 std::move( sd.getCellData("SOMAX") ),
00811 data::TargetType::RESTART_AUXILIARY);
00812 }
00813
00814 if (sd.hasCellData("PCSWMDC_OW")) {
00815 output.insert("PCSWM_OW",
00816 Opm::UnitSystem::measure::identity,
00817 std::move( sd.getCellData("PCSWMDC_OW") ),
00818 data::TargetType::RESTART_AUXILIARY);
00819 }
00820 if (sd.hasCellData("KRNSWMDC_OW")) {
00821 output.insert("KRNSW_OW",
00822 Opm::UnitSystem::measure::identity,
00823 std::move( sd.getCellData("KRNSWMDC_OW") ),
00824 data::TargetType::RESTART_AUXILIARY);
00825 }
00826
00827 if (sd.hasCellData("PCSWMDC_GO")) {
00828 output.insert("PCSWM_GO",
00829 Opm::UnitSystem::measure::identity,
00830 std::move( sd.getCellData("PCSWMDC_GO") ),
00831 data::TargetType::RESTART_AUXILIARY);
00832 }
00833 if (sd.hasCellData("KRNSWMDC_GO")) {
00834 output.insert("KRNSW_GO",
00835 Opm::UnitSystem::measure::identity,
00836 std::move( sd.getCellData("KRNSWMDC_GO") ),
00837 data::TargetType::RESTART_AUXILIARY);
00838 }
00839
00840
00841 if (log) {
00842 for (auto& keyValue : rstKeywords) {
00843 if (keyValue.second > 0) {
00844 std::string logstring = "Keyword '";
00845 logstring.append(keyValue.first);
00846 logstring.append("' is unhandled for output to file.");
00847 Opm::OpmLog::warning("Unhandled output keyword", logstring);
00848 }
00849 }
00850 }
00851 }
00852
00853
00854
00855
00859 inline bool hasFRBKeyword(const SummaryConfig& summaryConfig, const std::string keyword) {
00860 std::string field_kw = "F" + keyword;
00861 std::string region_kw = "R" + keyword;
00862 std::string block_kw = "B" + keyword;
00863 return summaryConfig.hasKeyword(field_kw)
00864 || summaryConfig.hasKeyword(region_kw)
00865 || summaryConfig.hasKeyword(block_kw);
00866 }
00867
00868
00872 template<class Model>
00873 void getSummaryData(data::Solution& output,
00874 const Opm::PhaseUsage& phaseUsage,
00875 const Model& physicalModel,
00876 const SummaryConfig& summaryConfig) {
00877
00878 typedef typename Model::FIPDataType FIPDataType;
00879 typedef typename FIPDataType::VectorType VectorType;
00880
00881 FIPDataType fd = physicalModel.getFIPData();
00882
00883
00884 const int aqua_active = phaseUsage.phase_used[Opm::PhaseUsage::Aqua];
00885 const int liquid_active = phaseUsage.phase_used[Opm::PhaseUsage::Liquid];
00886 const int vapour_active = phaseUsage.phase_used[Opm::PhaseUsage::Vapour];
00887
00891
00892 if (aqua_active && hasFRBKeyword(summaryConfig, "WIP")) {
00893 output.insert("WIP",
00894 Opm::UnitSystem::measure::volume,
00895 std::move( fd.fip[ FIPDataType::FIP_AQUA ] ),
00896 data::TargetType::SUMMARY );
00897 }
00898 if (liquid_active) {
00899 const VectorType& oipl = fd.fip[FIPDataType::FIP_LIQUID];
00900 VectorType oip ( oipl );
00901 const size_t size = oip.size();
00902
00903 const VectorType& oipg = vapour_active ? fd.fip[FIPDataType::FIP_VAPORIZED_OIL] : VectorType(size, 0.0);
00904 if( vapour_active )
00905 {
00906
00907 for( size_t i=0; i<size; ++ i ) {
00908 oip[ i ] += oipg[ i ];
00909 }
00910 }
00911
00912
00913 if (hasFRBKeyword(summaryConfig, "OIPL")) {
00914 output.insert("OIPL",
00915 Opm::UnitSystem::measure::volume,
00916 std::move( oipl ),
00917 data::TargetType::SUMMARY );
00918 }
00919
00920 if (hasFRBKeyword(summaryConfig, "OIPG")) {
00921 output.insert("OIPG",
00922 Opm::UnitSystem::measure::volume,
00923 std::move( oipg ),
00924 data::TargetType::SUMMARY );
00925 }
00926
00927 if (hasFRBKeyword(summaryConfig, "OIP") || hasFRBKeyword(summaryConfig, "OE")) {
00928 output.insert("OIP",
00929 Opm::UnitSystem::measure::volume,
00930 std::move( oip ),
00931 data::TargetType::SUMMARY );
00932 }
00933 }
00934 if (vapour_active) {
00935 const VectorType& gipg = fd.fip[ FIPDataType::FIP_VAPOUR];
00936 VectorType gip( gipg );
00937 const size_t size = gip.size();
00938
00939 const VectorType& gipl = liquid_active ? fd.fip[ FIPDataType::FIP_DISSOLVED_GAS ] : VectorType(size,0.0);
00940 if( liquid_active )
00941 {
00942
00943 for( size_t i=0; i<size; ++ i ) {
00944 gip[ i ] += gipl[ i ];
00945 }
00946 }
00947
00948
00949 if (hasFRBKeyword(summaryConfig, "GIPG")) {
00950 output.insert("GIPG",
00951 Opm::UnitSystem::measure::volume,
00952 std::move( gipg ),
00953 data::TargetType::SUMMARY );
00954 }
00955
00956
00957 if (hasFRBKeyword(summaryConfig, "GIPL")) {
00958 output.insert("GIPL",
00959 Opm::UnitSystem::measure::volume,
00960 std::move( gipl ),
00961 data::TargetType::SUMMARY );
00962 }
00963
00964 if (hasFRBKeyword(summaryConfig, "GIP")) {
00965 output.insert("GIP",
00966 Opm::UnitSystem::measure::volume,
00967 std::move( gip ),
00968 data::TargetType::SUMMARY );
00969 }
00970 }
00971
00972 if (hasFRBKeyword(summaryConfig, "RPV")) {
00973 output.insert("RPV",
00974 Opm::UnitSystem::measure::volume,
00975 std::move( fd.fip[FIPDataType::FIP_PV]),
00976 data::TargetType::SUMMARY );
00977 }
00978
00979 if (summaryConfig.hasKeyword("FPRH") || summaryConfig.hasKeyword("RPRH")) {
00980 output.insert("PRH",
00981 Opm::UnitSystem::measure::pressure,
00982 std::move(fd.fip[FIPDataType::FIP_WEIGHTED_PRESSURE]),
00983 data::TargetType::SUMMARY );
00984 }
00985 }
00986
00987 }
00988
00989
00990
00991
00992 template<class Model>
00993 inline void
00994 BlackoilOutputWriter::
00995 writeTimeStep(const SimulatorTimerInterface& timer,
00996 const SimulationDataContainer& localState,
00997 const WellStateFullyImplicitBlackoil& localWellState,
00998 const Model& physicalModel,
00999 const bool substep,
01000 const double nextstep,
01001 const SimulatorReport& simulatorReport)
01002 {
01003 data::Solution localCellData{};
01004 const RestartConfig& restartConfig = eclipseState_.getRestartConfig();
01005 const SummaryConfig& summaryConfig = eclipseState_.getSummaryConfig();
01006 const int reportStepNum = timer.reportStepNum();
01007 bool logMessages = output_ && parallelOutput_->isIORank();
01008 std::map<std::string, std::vector<double>> extraRestartData;
01009 std::map<std::string, double> miscSummaryData;
01010
01011 if( output_ )
01012 {
01013 {
01014
01015
01016
01017
01018 SimulationDataContainer sd =
01019 detail::convertToSimulationDataContainer( physicalModel.getSimulatorData(localState), localState, phaseUsage_ );
01020
01021 localCellData = simToSolution( sd, restart_double_si_, phaseUsage_);
01022
01023 detail::getRestartData( localCellData, std::move(sd), phaseUsage_, physicalModel,
01024 restartConfig, reportStepNum, logMessages );
01025
01026 }
01027 detail::getSummaryData( localCellData, phaseUsage_, physicalModel, summaryConfig );
01028 assert(!localCellData.empty());
01029
01030
01031 extraRestartData["OPMEXTRA"] = std::vector<double>(1, nextstep);
01032
01033
01034 const double totalSolverTime = simulatorReport.solver_time;
01035 if (totalSolverTime != 0.0) {
01036 miscSummaryData["TCPU"] = totalSolverTime;
01037 }
01038 }
01039
01040 writeTimeStepWithCellProperties(timer, localState, localCellData, localWellState, miscSummaryData, extraRestartData, substep);
01041 }
01042 }
01043 #endif