From 7cf035da804bfc8cf92ba8b5715c51f91b813a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Sat, 27 Jun 2020 16:52:55 +0200 Subject: [PATCH] EclWriter: Refactor Cell Loop out to Helper Function That way we can use the same code for both the 'writeOutput' and the 'evalSummaryState' member functions. While here, also change the declared types of 'wellData' and 'groupData' to 'auto' in preparation of API updates for collecting group- and well level guiderate data. Finally, apply 'const' where possible. --- ebos/eclwriter.hh | 202 +++++++++++++++++++++++++--------------------- 1 file changed, 110 insertions(+), 92 deletions(-) diff --git a/ebos/eclwriter.hh b/ebos/eclwriter.hh index 710b76896..6e87d0775 100644 --- a/ebos/eclwriter.hh +++ b/ebos/eclwriter.hh @@ -233,7 +233,7 @@ public: void evalSummaryState(bool isSubStep) { - int reportStepNum = simulator_.episodeIndex() + 1; + const int reportStepNum = simulator_.episodeIndex() + 1; /* The summary data is not evaluated for timestep 0, that is implemented with a: @@ -254,33 +254,21 @@ public: if (reportStepNum == 0) return; - Scalar curTime = simulator_.time() + simulator_.timeStepSize(); - Scalar totalCpuTime = + const Scalar curTime = simulator_.time() + simulator_.timeStepSize(); + const Scalar totalCpuTime = simulator_.executionTimer().realTimeElapsed() + simulator_.setupTimer().realTimeElapsed() + simulator_.vanguard().externalSetupTime(); - Opm::data::Wells localWellData = simulator_.problem().wellModel().wellData(); + const auto localWellData = simulator_.problem().wellModel().wellData(); + const auto localGroupData = simulator_.problem().wellModel() + .groupData(reportStepNum, simulator_.vanguard().schedule()); - Opm::data::Group localGroupData = simulator_.problem().wellModel().groupData(reportStepNum, simulator_.vanguard().schedule()); - - const auto& gridView = simulator_.vanguard().gridView(); - int numElements = gridView.size(/*codim=*/0); - bool log = collectToIORank_.isIORank(); - eclOutputModule_.allocBuffers(numElements, reportStepNum, isSubStep, log, /*isRestart*/ false); - - ElementContext elemCtx(simulator_); - ElementIterator elemIt = gridView.template begin(); - const ElementIterator& elemEndIt = gridView.template end(); - for (; elemIt != elemEndIt; ++elemIt) { - const Element& elem = *elemIt; - elemCtx.updatePrimaryStencil(elem); - elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0); - eclOutputModule_.processElement(elemCtx); - } + this->prepareLocalCellData(isSubStep, reportStepNum); if (collectToIORank_.isParallel()) - collectToIORank_.collect({}, eclOutputModule_.getBlockData(), localWellData, localGroupData); + collectToIORank_.collect({}, eclOutputModule_.getBlockData(), + localWellData, localGroupData); std::map miscSummaryData; std::map> regionData; @@ -294,21 +282,27 @@ public: eclOutputModule_.outputCumLog(reportStepNum, isSubStep, forceDisableCumOutput); std::vector buffer; - if (collectToIORank_.isIORank()) { + if (this->collectToIORank_.isIORank()) { const auto& summary = eclIO_->summary(); const auto& eclState = simulator_.vanguard().eclState(); // Add TCPU - if (totalCpuTime != 0.0) + if (totalCpuTime != 0.0) { miscSummaryData["TCPU"] = totalCpuTime; + } - const Opm::data::Wells& wellData = collectToIORank_.isParallel() ? collectToIORank_.globalWellData() : localWellData; - const Opm::data::Group& groupData = collectToIORank_.isParallel() ? collectToIORank_.globalGroupData() : localGroupData; + const auto& wellData = this->collectToIORank_.isParallel() + ? this->collectToIORank_.globalWellData() + : localWellData; - const std::map, double>& blockData - = collectToIORank_.isParallel() - ? collectToIORank_.globalBlockData() - : eclOutputModule_.getBlockData(); + const auto& groupData = this->collectToIORank_.isParallel() + ? this->collectToIORank_.globalGroupData() + : localGroupData; + + const auto& blockData + = this->collectToIORank_.isParallel() + ? this->collectToIORank_.globalBlockData() + : this->eclOutputModule_.getBlockData(); summary.eval(summaryState(), reportStepNum, @@ -342,75 +336,33 @@ public: void writeOutput(bool isSubStep) { - int reportStepNum = simulator_.episodeIndex() + 1; - Scalar curTime = simulator_.time() + simulator_.timeStepSize(); - Scalar nextStepSize = simulator_.problem().nextTimeStepSize(); + const int reportStepNum = simulator_.episodeIndex() + 1; + + this->prepareLocalCellData(isSubStep, reportStepNum); + this->eclOutputModule_.outputErrorLog(); // output using eclWriter if enabled - Opm::data::Wells localWellData = simulator_.problem().wellModel().wellData(); - Opm::data::Group localGroupData = simulator_.problem().wellModel().groupData(reportStepNum, simulator_.vanguard().schedule()); + auto localWellData = simulator_.problem().wellModel().wellData(); - const auto& gridView = simulator_.vanguard().gridView(); - int numElements = gridView.size(/*codim=*/0); - bool log = collectToIORank_.isIORank(); - eclOutputModule_.allocBuffers(numElements, reportStepNum, isSubStep, log, /*isRestart*/ false); - - ElementContext elemCtx(simulator_); - ElementIterator elemIt = gridView.template begin(); - const ElementIterator& elemEndIt = gridView.template end(); - for (; elemIt != elemEndIt; ++elemIt) { - const Element& elem = *elemIt; - elemCtx.updatePrimaryStencil(elem); - elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0); - eclOutputModule_.processElement(elemCtx); - } - eclOutputModule_.outputErrorLog(); - - // collect all data to I/O rank and assign to sol Opm::data::Solution localCellData = {}; - if (!isSubStep) - eclOutputModule_.assignToSolution(localCellData); + if (! isSubStep) { + this->eclOutputModule_.assignToSolution(localCellData); - // add cell data to perforations for Rft output - if (!isSubStep) - eclOutputModule_.addRftDataToWells(localWellData, reportStepNum); + // add cell data to perforations for Rft output + this->eclOutputModule_.addRftDataToWells(localWellData, reportStepNum); + } + + if (collectToIORank_.isParallel()) { + const auto localGroupData = simulator_.problem().wellModel() + .groupData(reportStepNum, simulator_.vanguard().schedule()); - if (collectToIORank_.isParallel()) collectToIORank_.collect(localCellData, eclOutputModule_.getBlockData(), localWellData, localGroupData); + } - - if (collectToIORank_.isIORank()) { - const auto& eclState = simulator_.vanguard().eclState(); - const auto& simConfig = eclState.getSimulationConfig(); - - bool enableDoublePrecisionOutput = EWOMS_GET_PARAM(TypeTag, bool, EclOutputDoublePrecision); - const Opm::data::Solution& cellData = collectToIORank_.isParallel() ? collectToIORank_.globalCellData() : localCellData; - const Opm::data::Wells& wellData = collectToIORank_.isParallel() ? collectToIORank_.globalWellData() : localWellData; - Opm::RestartValue restartValue(cellData, wellData); - - if (simConfig.useThresholdPressure()) - restartValue.addExtra("THRESHPR", Opm::UnitSystem::measure::pressure, simulator_.problem().thresholdPressure().data()); - - // Add suggested next timestep to extra data. - if (!isSubStep) - restartValue.addExtra("OPMEXTRA", std::vector(1, nextStepSize)); - - // first, create a tasklet to write the data for the current time step to disk - auto eclWriteTasklet = std::make_shared(actionState(), - summaryState(), - *eclIO_, - reportStepNum, - isSubStep, - curTime, - restartValue, - enableDoublePrecisionOutput); - - // then, make sure that the previous I/O request has been completed and the - // number of incomplete tasklets does not increase between time steps - taskletRunner_->barrier(); - - // finally, start a new output writing job - taskletRunner_->dispatch(eclWriteTasklet); + if (this->collectToIORank_.isIORank()) { + this->writeOutput(reportStepNum, isSubStep, + std::move(localCellData), + std::move(localWellData)); } } @@ -743,14 +695,80 @@ private: const Opm::Schedule& schedule() const { return simulator_.vanguard().schedule(); } + void prepareLocalCellData(const bool isSubStep, + const int reportStepNum) + { + const auto& gridView = simulator_.vanguard().gridView(); + const int numElements = gridView.size(/*codim=*/0); + const bool log = collectToIORank_.isIORank(); + + eclOutputModule_.allocBuffers(numElements, reportStepNum, + isSubStep, log, /*isRestart*/ false); + + ElementContext elemCtx(simulator_); + ElementIterator elemIt = gridView.template begin(); + + const ElementIterator& elemEndIt = gridView.template end(); + for (; elemIt != elemEndIt; ++elemIt) { + const Element& elem = *elemIt; + + elemCtx.updatePrimaryStencil(elem); + elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0); + + eclOutputModule_.processElement(elemCtx); + } + } + + void writeOutput(const int reportStepNum, + const bool isSubStep, + ::Opm::data::Solution&& localCellData, + ::Opm::data::Wells&& localWellData) + { + const Scalar curTime = simulator_.time() + simulator_.timeStepSize(); + const Scalar nextStepSize = simulator_.problem().nextTimeStepSize(); + const auto isParallel = this->collectToIORank_.isParallel(); + + Opm::RestartValue restartValue { + isParallel ? this->collectToIORank_.globalCellData() + : std::move(localCellData), + + isParallel ? this->collectToIORank_.globalWellData() + : std::move(localWellData) + }; + + if (simulator_.vanguard().eclState().getSimulationConfig().useThresholdPressure()) { + restartValue.addExtra("THRESHPR", Opm::UnitSystem::measure::pressure, + simulator_.problem().thresholdPressure().data()); + } + + // Add suggested next timestep to extra data. + if (! isSubStep) { + restartValue.addExtra("OPMEXTRA", std::vector(1, nextStepSize)); + } + + // first, create a tasklet to write the data for the current time + // step to disk + auto eclWriteTasklet = std::make_shared( + this->actionState(), this->summaryState(), *this->eclIO_, + reportStepNum, isSubStep, curTime, std::move(restartValue), + EWOMS_GET_PARAM(TypeTag, bool, EclOutputDoublePrecision) + ); + + // then, make sure that the previous I/O request has been completed + // and the number of incomplete tasklets does not increase between + // time steps + this->taskletRunner_->barrier(); + + // finally, start a new output writing job + this->taskletRunner_->dispatch(std::move(eclWriteTasklet)); + } + Simulator& simulator_; CollectDataToIORankType collectToIORank_; EclOutputBlackOilModule eclOutputModule_; std::unique_ptr eclIO_; std::unique_ptr taskletRunner_; Scalar restartTimeStepSize_; - - }; } // namespace Opm