110 GetPropType<TypeTag, Properties::EquilGrid>,
111 GetPropType<TypeTag, Properties::GridView>,
112 GetPropType<TypeTag, Properties::ElementMapper>,
113 GetPropType<TypeTag, Properties::Scalar>>
123 using Element =
typename GridView::template Codim<0>::Entity;
125 using ElementIterator =
typename GridView::template Codim<0>::Iterator;
128 typedef Dune::MultipleCodimMultipleGeomTypeMapper< GridView > VertexMapper;
137 static void registerParameters()
139 OutputModule::registerParameters();
141 Parameters::Register<Parameters::EnableAsyncEclOutput>
142 (
"Write the ECL-formated results in a non-blocking way "
143 "(i.e., using a separate thread).");
144 Parameters::Register<Parameters::EnableEsmry>
145 (
"Write ESMRY file for fast loading of summary data.");
152 :
BaseType(simulator.vanguard().schedule(),
153 simulator.vanguard().eclState(),
154 simulator.vanguard().summaryConfig(),
155 simulator.vanguard().grid(),
156 ((simulator.vanguard().grid().comm().rank() == 0)
157 ? &simulator.vanguard().equilGrid()
159 simulator.vanguard().gridView(),
160 simulator.vanguard().cartesianIndexMapper(),
161 ((simulator.vanguard().grid().comm().rank() == 0)
162 ? &simulator.vanguard().equilCartesianIndexMapper()
164 Parameters::Get<Parameters::EnableAsyncEclOutput>(),
165 Parameters::Get<Parameters::EnableEsmry>())
166 , simulator_(simulator)
169 if (this->simulator_.vanguard().grid().comm().size() > 1) {
170 auto smryCfg = (this->simulator_.vanguard().grid().comm().rank() == 0)
171 ? this->eclIO_->finalSummaryConfig()
174 eclBroadcast(this->simulator_.vanguard().grid().comm(),
smryCfg);
176 this->outputModule_ = std::make_unique<OutputModule>
177 (simulator,
smryCfg, this->collectOnIORank_);
182 this->outputModule_ = std::make_unique<OutputModule>
183 (simulator, this->eclIO_->finalSummaryConfig(),
this->collectOnIORank_);
186 this->rank_ = this->simulator_.vanguard().grid().comm().rank();
188 this->simulator_.vanguard().eclState().computeFipRegionStatistics();
194 const EquilGrid& globalGrid()
const
196 return simulator_.vanguard().equilGrid();
205 const int reportStepNum = simulator_.episodeIndex() + 1;
225 if (reportStepNum == 0)
228 const Scalar
curTime = simulator_.time() + simulator_.timeStepSize();
230 simulator_.executionTimer().realTimeElapsed() +
231 simulator_.setupTimer().realTimeElapsed() +
232 simulator_.vanguard().setupTime();
234 const auto localWellData = simulator_.problem().wellModel().wellData();
235 const auto localWBP = simulator_.problem().wellModel().wellBlockAveragePressures();
237 .groupAndNetworkData(reportStepNum);
239 const auto localAquiferData = simulator_.problem().aquiferModel().aquiferData();
241 this->prepareLocalCellData(
isSubStep, reportStepNum);
243 if (this->outputModule_->needInterfaceFluxes(
isSubStep)) {
244 this->captureLocalFluxData();
247 if (this->collectOnIORank_.isParallel()) {
248 OPM_BEGIN_PARALLEL_TRY_CATCH()
250 std::map<std::pair<std::string,int>,
double>
dummy;
251 this->collectOnIORank_.collect({},
252 outputModule_->getBlockData(),
259 this->outputModule_->getInterRegFlows(),
263 if (this->collectOnIORank_.isIORank()) {
264 auto&
iregFlows = this->collectOnIORank_.globalInterRegFlows();
267 throw std::runtime_error {
268 "Inconsistent inter-region flow "
269 "region set names in parallel"
276 OPM_END_PARALLEL_TRY_CATCH(
"Collect to I/O rank: ",
277 this->simulator_.vanguard().grid().comm());
282 std::map<std::string, std::vector<double>>
regionData;
290 if (this->collectOnIORank_.isIORank()){
299 if (this->sub_step_report_.total_newton_iterations != 0) {
300 miscSummaryData[
"NEWTON"] = this->sub_step_report_.total_newton_iterations;
302 if (this->sub_step_report_.total_linear_iterations != 0) {
303 miscSummaryData[
"MLINEARS"] = this->sub_step_report_.total_linear_iterations;
305 if (this->sub_step_report_.total_newton_iterations != 0) {
306 miscSummaryData[
"NLINEARS"] =
static_cast<float>(this->sub_step_report_.total_linear_iterations) / this->sub_step_report_.total_newton_iterations;
308 if (this->sub_step_report_.min_linear_iterations != std::numeric_limits<unsigned int>::max()) {
309 miscSummaryData[
"NLINSMIN"] = this->sub_step_report_.min_linear_iterations;
311 if (this->sub_step_report_.max_linear_iterations != 0) {
312 miscSummaryData[
"NLINSMAX"] = this->sub_step_report_.max_linear_iterations;
314 if (this->simulation_report_.success.total_linear_iterations != 0) {
315 miscSummaryData[
"MSUMLINS"] = this->simulation_report_.success.total_linear_iterations;
317 if (this->simulation_report_.success.total_newton_iterations != 0) {
318 miscSummaryData[
"MSUMNEWT"] = this->simulation_report_.success.total_newton_iterations;
324 const auto&
blockData = this->collectOnIORank_.isParallel()
325 ? this->collectOnIORank_.globalBlockData()
326 : this->outputModule_->getBlockData();
328 const auto&
interRegFlows = this->collectOnIORank_.isParallel()
329 ? this->collectOnIORank_.globalInterRegFlows()
330 : this->outputModule_->getInterRegFlows();
332 this->evalSummary(reportStepNum,
342 this->outputModule_->initialInplace(),
344 this->summaryState(),
352 const auto& gridView = simulator_.vanguard().gridView();
354 countLocalInteriorCellsGridView(gridView);
356 this->outputModule_->
360#pragma omp parallel for
363 const auto& intQuants = *simulator_.model().cachedIntensiveQuantities(dofIdx, 0);
364 const auto totVolume = simulator_.model().dofTotalVolume(dofIdx);
366 this->outputModule_->updateFluidInPlace(dofIdx, intQuants,
totVolume);
371 outputModule_->calc_initial_inplace(simulator_.gridView().comm());
374 const auto& fip = simulator_.vanguard().eclState().getEclipseConfig().fip();
375 if (fip.output(FIPConfig::OutputField::FIELD) ||
376 fip.output(FIPConfig::OutputField::RESV))
380 boost::posix_time::from_time_t(simulator_.vanguard().schedule().getStartTime());
382 if (this->collectOnIORank_.isIORank()) {
383 inplace_ = outputModule_->initialInplace().value();
384 outputModule_->outputFipAndResvLog(inplace_, 0, 0.0,
start_time,
385 false, simulator_.gridView().comm());
392 if (! this->collectOnIORank_.isIORank()) {
404 const auto firstStep = this->initialStep();
408 const auto&
rpt = this->schedule_[
simStep].rpt_config();
410 if (
rpt.contains(
"WELSPECS") && (
rpt.at(
"WELSPECS") > 0)) {
413 this->writeWellspecReport(timer);
421 if (
rpt.contains(
"WELLS") &&
rpt.at(
"WELLS") > 0) {
422 this->writeWellflowReport(timer,
simStep,
rpt.at(
"WELLS"));
425 this->outputModule_->outputFipAndResvLog(this->inplace_,
430 simulator_.gridView().comm());
439 const int reportStepNum = simulator_.episodeIndex() + 1;
440 this->prepareLocalCellData(
isSubStep, reportStepNum);
441 this->outputModule_->outputErrorLog(simulator_.gridView().comm());
444 auto localWellData = simulator_.problem().wellModel().wellData();
446 .groupAndNetworkData(reportStepNum);
451 const bool isFlowsn = this->outputModule_->getFlows().hasFlowsn();
452 auto flowsn = this->outputModule_->getFlows().getFlowsn();
454 const bool isFloresn = this->outputModule_->getFlows().hasFloresn();
455 auto floresn = this->outputModule_->getFlows().getFloresn();
457 if (!
isSubStep || Parameters::Get<Parameters::EnableWriteAllSolutions>()) {
466 simulator_.gridView().comm());
469 if (this->collectOnIORank_.isParallel() ||
470 this->collectOnIORank_.doesNeedReordering())
478 this->outputModule_->getBlockData(),
479 this->outputModule_->getExtraBlockData(),
488 if (this->collectOnIORank_.isIORank()) {
489 this->outputModule_->assignGlobalFieldsToSolution(this->collectOnIORank_.globalCellData());
492 this->outputModule_->assignGlobalFieldsToSolution(
localCellData);
495 if (this->collectOnIORank_.isIORank()) {
496 const Scalar
curTime = simulator_.time() + simulator_.timeStepSize();
497 const Scalar
nextStepSize = simulator_.problem().nextTimeStepSize();
499 if (Parameters::Get<Parameters::EnableWriteAllSolutions>()) {
510 this->summaryState(),
511 this->simulator_.problem().thresholdPressure().getRestartVector(),
513 Parameters::Get<Parameters::EclOutputDoublePrecision>(),
521 const auto enablePCHysteresis = simulator_.problem().materialLawManager()->enablePCHysteresis();
524 const auto oilActive = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx);
525 const auto gasActive = FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx);
526 const auto waterActive = FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx);
527 const auto enableSwatinit = simulator_.vanguard().eclState().fieldProps().has_double(
"SWATINIT");
530 {
"PRESSURE", UnitSystem::measure::pressure},
531 {
"SWAT", UnitSystem::measure::identity, waterActive},
532 {
"SGAS", UnitSystem::measure::identity, gasActive},
533 {
"TEMP", UnitSystem::measure::temperature, enableEnergy},
534 {
"SSOLVENT", UnitSystem::measure::identity, enableSolvent},
536 {
"RS", UnitSystem::measure::gas_oil_ratio, FluidSystem::enableDissolvedGas()},
537 {
"RV", UnitSystem::measure::oil_gas_ratio, FluidSystem::enableVaporizedOil()},
538 {
"RVW", UnitSystem::measure::oil_gas_ratio, FluidSystem::enableVaporizedWater()},
539 {
"RSW", UnitSystem::measure::gas_oil_ratio, FluidSystem::enableDissolvedGasInWater()},
544 {
"SOMAX", UnitSystem::measure::identity,
546 || simulator_.problem().vapparsActive(simulator_.episodeIndex())},
548 {
"SOMIN", UnitSystem::measure::identity,
enablePCHysteresis && oilActive && gasActive},
549 {
"SWHY1", UnitSystem::measure::identity,
enablePCHysteresis && oilActive && waterActive},
556 const auto&
tracers = simulator_.vanguard().eclState().tracer();
560 ((
tracer.phase == Phase::GAS) && FluidSystem::enableDissolvedGas()) ||
561 ((
tracer.phase == Phase::OIL) && FluidSystem::enableVaporizedOil());
568 const auto&
inputThpres = eclState().getSimulationConfig().getThresholdPressure();
569 const std::vector<RestartKey>
extraKeys {
570 {
"OPMEXTRA", UnitSystem::measure::identity,
false},
571 {
"THRESHPR", UnitSystem::measure::pressure,
inputThpres.active()},
574 const auto& gridView = this->simulator_.vanguard().gridView();
586 loadParallelRestartSolution(this->eclIO_.get(),
591 const auto globalIdx = this->collectOnIORank_.localIdxToGlobalIdx(elemIdx);
595 this->simulator_.problem().readSolutionFromOutputModule(0,
true);
596 ElementContext elemCtx(this->simulator_);
598 elemCtx.updatePrimaryStencil(
elem);
599 elemCtx.updatePrimaryIntensiveQuantities(0);
601 this->outputModule_->updateFluidInPlace(elemCtx);
604 this->outputModule_->calc_initial_inplace(this->simulator_.gridView().comm());
613 .eclState().getInitConfig().getRestartStep();
624 loadParallelRestart(this->eclIO_.get(),
626 this->summaryState(),
630 const auto globalIdx = this->collectOnIORank_.localIdxToGlobalIdx(elemIdx);
631 this->outputModule_->setRestart(
restartValues.solution, elemIdx, globalIdx);
634 auto&
tracer_model = simulator_.problem().tracerModel();
643 const auto globalIdx = this->collectOnIORank_.localIdxToGlobalIdx(elemIdx);
660 const auto globalIdx = this->collectOnIORank_.localIdxToGlobalIdx(elemIdx);
675 const_cast<Simulator&
>(this->simulator_)
676 .problem().thresholdPressure()
680 restartTimeStepSize_ =
restartValues.getExtra(
"OPMEXTRA")[0];
681 if (restartTimeStepSize_ <= 0) {
682 restartTimeStepSize_ = std::numeric_limits<double>::max();
686 this->simulator_.problem().wellModel()
690 this->simulator_.problem().mutableAquiferModel()
701 this->outputModule_->calc_initial_inplace(this->simulator_.gridView().comm());
703 if (this->collectOnIORank_.isIORank()) {
704 if (this->outputModule_->initialInplace().has_value()) {
705 this->inplace_ = this->outputModule_->initialInplace().value();
711 {
return *outputModule_; }
714 {
return *outputModule_; }
716 Scalar restartTimeStepSize()
const
717 {
return restartTimeStepSize_; }
719 template <
class Serializer>
726 static bool enableEclOutput_()
728 static bool enable = Parameters::Get<Parameters::EnableEclOutput>();
732 const EclipseState& eclState()
const
733 {
return simulator_.vanguard().eclState(); }
736 {
return simulator_.vanguard().summaryState(); }
738 Action::State& actionState()
739 {
return simulator_.vanguard().actionState(); }
742 {
return simulator_.vanguard().udqState(); }
745 {
return simulator_.vanguard().schedule(); }
747 void prepareLocalCellData(
const bool isSubStep,
748 const int reportStepNum)
752 if (this->outputModule_->localDataValid()) {
756 const auto& gridView = simulator_.vanguard().gridView();
757 const bool log = this->collectOnIORank_.isIORank();
760 countLocalInteriorCellsGridView(gridView);
761 this->outputModule_->
763 isSubStep && !Parameters::Get<Parameters::EnableWriteAllSolutions>(),
766 ElementContext elemCtx(simulator_);
768 OPM_BEGIN_PARALLEL_TRY_CATCH();
773 this->outputModule_->prepareDensityAccumulation();
774 this->outputModule_->setupExtractors(
isSubStep, reportStepNum);
776 elemCtx.updatePrimaryStencil(
elem);
777 elemCtx.updatePrimaryIntensiveQuantities(0);
779 this->outputModule_->processElement(elemCtx);
780 this->outputModule_->processElementBlockData(elemCtx);
782 this->outputModule_->clearExtractors();
784 this->outputModule_->accumulateDensityParallel();
791#pragma omp parallel for
794 const auto& intQuants = *simulator_.model().cachedIntensiveQuantities(dofIdx, 0);
795 const auto totVolume = simulator_.model().dofTotalVolume(dofIdx);
797 this->outputModule_->updateFluidInPlace(dofIdx, intQuants,
totVolume);
801 this->outputModule_->validateLocalData();
803 OPM_END_PARALLEL_TRY_CATCH(
"EclWriter::prepareLocalCellData() failed: ",
804 this->simulator_.vanguard().grid().comm());
807 void captureLocalFluxData()
811 const auto& gridView = this->simulator_.vanguard().gridView();
814 auto elemCtx = ElementContext { this->simulator_ };
816 const auto elemMapper = ElementMapper { gridView, Dune::mcmgElementLayout() };
817 const auto activeIndex = [&
elemMapper](
const Element&
e)
822 const auto cartesianIndex = [
this](
const int elemIndex)
824 return this->cartMapper_.cartesianIndex(
elemIndex);
827 this->outputModule_->initializeFluxData();
829 OPM_BEGIN_PARALLEL_TRY_CATCH();
832 elemCtx.updateStencil(
elem);
833 elemCtx.updateIntensiveQuantities(
timeIdx);
834 elemCtx.updateExtensiveQuantities(
timeIdx);
836 this->outputModule_->processFluxes(elemCtx, activeIndex, cartesianIndex);
839 OPM_END_PARALLEL_TRY_CATCH(
"EclWriter::captureLocalFluxData() failed: ",
840 this->simulator_.vanguard().grid().comm())
842 this->outputModule_->finalizeFluxData();
845 void writeWellspecReport(
const SimulatorTimer& timer)
const
848 .changed_wells(timer.reportStepNum(),
this->initialStep());
855 timer.reportStepNum(),
856 timer.simulationTimeElapsed(),
857 timer.currentDateTime());
860 void writeWellflowReport(
const SimulatorTimer& timer,
864 this->outputModule_->outputTimeStamp(
"WELLS",
865 timer.simulationTimeElapsed(),
866 timer.reportStepNum(),
867 timer.currentDateTime());
874 this->outputModule_->outputMSWLog(
simStep);
877 int initialStep()
const
879 const auto&
initConfig = this->eclState().cfg().init();
886 Simulator& simulator_;
887 std::unique_ptr<OutputModule> outputModule_;
888 Scalar restartTimeStepSize_;