cleaing up EclWriter related and DamarisWriter.hpp

This commit is contained in:
Kai Bao
2024-10-17 13:05:39 +02:00
parent 0153da2009
commit 197282ccfc
6 changed files with 220 additions and 272 deletions

View File

@@ -0,0 +1,97 @@
/*
Copyright 2024, SINTEF Digital
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
// this is an empty model that having a lot of empty interfaces.
// it is use for the development when some facility class are not ready
#include <opm/output/data/Aquifer.hpp>
#include <opm/output/data/Wells.hpp>
#include <opm/models/discretization/common/baseauxiliarymodule.hh>
#include <opm/input/eclipse/Schedule/Well/WellTestState.hpp>
namespace Opm {
template<typename TypeTag>
class EmptyModel : public BaseAuxiliaryModule<TypeTag>
{
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
using GridView = GetPropType<TypeTag, Properties::GridView>;
using GlobalEqVector = GetPropType<TypeTag, Properties::GlobalEqVector>;
using SparseMatrixAdapter = GetPropType<TypeTag, Properties::SparseMatrixAdapter>;
public:
using Simulator = GetPropType<TypeTag, Properties::Simulator>;
EmptyModel(Simulator& /*simulator*/)
{
}
void init(){}
template<class Something>
void init(Something /*A*/){}
void prepareTracerBatches(){};
using NeighborSet = std::set<unsigned>;
void linearize(SparseMatrixAdapter& /*matrix*/, GlobalEqVector& /*residual*/){};
unsigned numDofs() const{return 0;};
void addNeighbors(std::vector<NeighborSet>& /*neighbors*/) const{};
//void applyInitial(){};
void initialSolutionApplied(){};
//void initFromRestart(const data::Aquifers& aquiferSoln);
template <class Restarter>
void serialize(Restarter& /*res*/){};
template <class Restarter>
void deserialize(Restarter& /*res*/){};
void beginEpisode(){};
void beginTimeStep(){};
void beginIteration(){};
// add the water rate due to aquifers to the source term.
template<class RateVector, class Context>
void addToSource(RateVector& /*rates*/, const Context& /*context*/,
unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const {}
template<class RateVector>
void addToSource(RateVector& /*rates*/, unsigned /*globalSpaceIdx*/,
unsigned /*timeIdx*/) const {}
void endIteration()const{};
void endTimeStep(){};
void endEpisode(){};
void applyInitial(){};
template<class RateType>
void computeTotalRatesForDof(RateType& /*rate*/, unsigned /*globalIdx*/) const{};
auto wellData() const {
return data::Wells{};
}
auto wellBlockAveragePressures() const {
return data::WellBlockAveragePressures{};
}
auto groupAndNetworkData(const int&) const {
return data::GroupAndNetworkValues{};
}
auto wellTestState() const {
return WellTestState{};
}
auto aquiferData() const {
return data::Aquifers{};
}
};
} // end of namespace Opm

View File

@@ -30,6 +30,8 @@
#include <opm/simulators/linalg/parallelbicgstabbackend.hh>
#include <flowexperimental/comp/EmptyModel.hpp>
// // the current code use eclnewtonmethod adding other conditions to proceed_ should do the trick for KA
// // adding linearshe sould be chaning the update_ function in the same class with condition that the error is reduced.
// the trick is to be able to recalculate the residual from here.
@@ -37,55 +39,6 @@
// suggestTimeStep is taken from newton solver in problem.limitTimestep
namespace Opm {
template<typename TypeTag>
class EmptyModel : public BaseAuxiliaryModule<TypeTag>
{
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
using GridView = GetPropType<TypeTag, Properties::GridView>;
using GlobalEqVector = GetPropType<TypeTag, Properties::GlobalEqVector>;
using SparseMatrixAdapter = GetPropType<TypeTag, Properties::SparseMatrixAdapter>;
public:
using Simulator = GetPropType<TypeTag, Properties::Simulator>;
EmptyModel(Simulator& /*simulator*/)
{
}
void init(){}
template<class Something>
void init(Something /*A*/){}
void prepareTracerBatches(){};
using NeighborSet = std::set<unsigned>;
void linearize(SparseMatrixAdapter& /*matrix*/, GlobalEqVector& /*residual*/){};
unsigned numDofs() const{return 0;};
void addNeighbors(std::vector<NeighborSet>& /*neighbors*/) const{};
//void applyInitial(){};
void initialSolutionApplied(){};
//void initFromRestart(const data::Aquifers& aquiferSoln);
template <class Restarter>
void serialize(Restarter& /*res*/){};
template <class Restarter>
void deserialize(Restarter& /*res*/){};
void beginEpisode(){};
void beginTimeStep(){};
void beginIteration(){};
// add the water rate due to aquifers to the source term.
template<class RateVector, class Context>
void addToSource(RateVector& /*rates*/, const Context& /*context*/,
unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const {}
template<class RateVector>
void addToSource(RateVector& /*rates*/, unsigned /*globalSpaceIdx*/,
unsigned /*timeIdx*/) const {}
void endIteration()const{};
void endTimeStep(){};
void endEpisode(){};
void applyInitial(){};
template<class RateType>
void computeTotalRatesForDof(RateType& /*rate*/, unsigned /*globalIdx*/) const{};
};
template<int numComp>
int dispatchFlowExpComp(int argc, char** argv);

View File

@@ -39,7 +39,7 @@
#include <opm/simulators/flow/DamarisParameters.hpp>
#include <opm/simulators/flow/EclGenericWriter.hpp>
#include <opm/simulators/flow/FlowBaseVanguard.hpp>
#include <opm/simulators/flow/OutputCompositionalModule.hpp>
#include <opm/simulators/flow/OutputBlackoilModule.hpp>
#include <opm/simulators/utils/DamarisVar.hpp>
#include <opm/simulators/utils/DamarisKeywords.hpp>
#include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>

View File

@@ -134,13 +134,6 @@ protected:
bool isFloresn,
std::array<FlowsData<double>, 3>&& floresn);
void doWriteOutput(const int reportStepNum,
const std::optional<int> timeStepNum,
const bool isSubStep,
Scalar curTime,
Scalar nextStepSize,
data::Solution&& localCellData);
void evalSummary(int reportStepNum,
Scalar curTime,
const data::Wells& localWellData,

View File

@@ -136,6 +136,10 @@ getInterRegFlowsAsMap(const Opm::InterRegFlowMap& map)
struct EclWriteTasklet : public Opm::TaskletInterface
{
Opm::Action::State actionState_;
Opm::WellTestState wtestState_;
Opm::SummaryState summaryState_;
Opm::UDQState udqState_;
Opm::EclipseIO& eclIO_;
int reportStepNum_;
std::optional<int> timeStepNum_;
@@ -143,48 +147,45 @@ struct EclWriteTasklet : public Opm::TaskletInterface
double secondsElapsed_;
Opm::RestartValue restartValue_;
bool writeDoublePrecision_;
std::optional<Opm::Action::State> actionState_;
std::optional<Opm::WellTestState> wtestState_;
std::optional<Opm::SummaryState> summaryState_;
std::optional<Opm::UDQState> udqState_;
explicit EclWriteTasklet(Opm::EclipseIO& eclIO,
explicit EclWriteTasklet(const Opm::Action::State& actionState,
const Opm::WellTestState& wtestState,
const Opm::SummaryState& summaryState,
const Opm::UDQState& udqState,
Opm::EclipseIO& eclIO,
int reportStepNum,
std::optional<int> timeStepNum,
bool isSubStep,
double secondsElapsed,
Opm::RestartValue restartValue,
bool writeDoublePrecision,
std::optional<Opm::Action::State> actionState = std::nullopt,
std::optional<Opm::WellTestState> wtestState = std::nullopt,
std::optional<Opm::SummaryState> summaryState = std::nullopt,
std::optional<Opm::UDQState> udqState = std::nullopt)
: eclIO_(eclIO)
bool writeDoublePrecision)
: actionState_(actionState)
, wtestState_(wtestState)
, summaryState_(summaryState)
, udqState_(udqState)
, eclIO_(eclIO)
, reportStepNum_(reportStepNum)
, timeStepNum_(timeStepNum)
, isSubStep_(isSubStep)
, secondsElapsed_(secondsElapsed)
, restartValue_(std::move(restartValue))
, writeDoublePrecision_(writeDoublePrecision)
, actionState_(std::move(actionState))
, wtestState_(std::move(wtestState))
, summaryState_(std::move(summaryState))
, udqState_(std::move(udqState))
{}
// callback to eclIO serial writeTimeStep method
void run()
{
this->eclIO_.writeTimeStep(this->reportStepNum_,
this->eclIO_.writeTimeStep(this->actionState_,
this->wtestState_,
this->summaryState_,
this->udqState_,
this->reportStepNum_,
this->isSubStep_,
this->secondsElapsed_,
std::move(this->restartValue_),
this->writeDoublePrecision_,
this->timeStepNum_,
std::move(this->actionState_),
std::move(this->wtestState_),
std::move(this->summaryState_),
std::move(this->udqState_));
this->timeStepNum_
);
}
};
@@ -608,102 +609,16 @@ doWriteOutput(const int reportStepNum,
}
// create a tasklet to write the data for the current time step to disk
auto eclWriteTasklet = std::make_shared<EclWriteTasklet>(/*
auto eclWriteTasklet = std::make_shared<EclWriteTasklet>(
actionState,
isParallel ? this->collectOnIORank_.globalWellTestState() : std::move(localWTestState),
summaryState, udqState, */*this->eclIO_,
summaryState, udqState, *this->eclIO_,
reportStepNum, timeStepNum, isSubStep, curTime, std::move(restartValue), doublePrecision);
// finally, start a new output writing job
this->taskletRunner_->dispatch(std::move(eclWriteTasklet));
}
template<class Grid, class EquilGrid, class GridView, class ElementMapper, class Scalar>
void EclGenericWriter<Grid,EquilGrid,GridView,ElementMapper,Scalar>::
doWriteOutput(const int reportStepNum,
const std::optional<int> timeStepNum,
const bool isSubStep,
Scalar curTime,
Scalar nextStepSize,
data::Solution&& localCellData)
{
const auto isParallel = this->collectOnIORank_.isParallel();
const bool needsReordering = this->collectOnIORank_.doesNeedReordering();
data::Wells localWellData {};
data::WellBlockAveragePressures localWBP{};
data::GroupAndNetworkValues localGroupAndNetworkData{};
std::map<int,data::AquiferData> localAquiferData {};
RestartValue restartValue {
(isParallel || needsReordering)
? this->collectOnIORank_.globalCellData()
: std::move(localCellData),
isParallel ? this->collectOnIORank_.globalWellData()
: std::move(localWellData),
isParallel ? this->collectOnIORank_.globalGroupAndNetworkData()
: std::move(localGroupAndNetworkData),
isParallel ? this->collectOnIORank_.globalAquiferData()
: std::move(localAquiferData)
};
// if (eclState_.getSimulationConfig().useThresholdPressure()) {
// restartValue.addExtra("THRESHPR", UnitSystem::measure::pressure,
// thresholdPressure);
// }
// Add suggested next timestep to extra data.
if (! isSubStep) {
restartValue.addExtra("OPMEXTRA", std::vector<double>(1, nextStepSize));
}
// Add nnc flows and flores.
// if (false/*isFlowsn*/) {
// const auto flowsn_global = isParallel ? this->collectOnIORank_.globalFlowsn() : std::move(flowsn);
// for (const auto& flows : flowsn_global) {
// if (flows.name.empty())
// continue;
// if (flows.name == "FLOGASN+") {
// restartValue.addExtra(flows.name, UnitSystem::measure::gas_surface_rate, flows.values);
// } else {
// restartValue.addExtra(flows.name, UnitSystem::measure::liquid_surface_rate, flows.values);
// }
// }
// }
// if (/*isFloresn*/) {
// const auto floresn_global = isParallel ? this->collectOnIORank_.globalFloresn() : std::move(floresn);
// for (const auto& flores : floresn_global) {
// if (flores.name.empty()) {
// continue;
// }
// restartValue.addExtra(flores.name, UnitSystem::measure::rate, flores.values);
// }
// }
// 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();
// check if there might have been a failure in the TaskletRunner
if (this->taskletRunner_->failure()) {
throw std::runtime_error("Failure in the TaskletRunner while writing output.");
}
// create a tasklet to write the data for the current time step to disk
auto eclWriteTasklet = std::make_shared<EclWriteTasklet>(
/* actionState,
isParallel ? this->collectOnIORank_.globalWellTestState() : std::move(localWTestState),
summaryState, udqState, */ *this->eclIO_,
reportStepNum, timeStepNum, isSubStep, curTime, std::move(restartValue), /* doublePrecision*/ false);
// finally, start a new output writing job
this->taskletRunner_->dispatch(std::move(eclWriteTasklet));
}
template<class Grid, class EquilGrid, class GridView, class ElementMapper, class Scalar>
void EclGenericWriter<Grid,EquilGrid,GridView,ElementMapper,Scalar>::
evalSummary(const int reportStepNum,

View File

@@ -227,49 +227,49 @@ public:
simulator_.setupTimer().realTimeElapsed() +
simulator_.vanguard().setupTime();
// const auto localWellData = simulator_.problem().wellModel().wellData();
// const auto localWBP = simulator_.problem().wellModel().wellBlockAveragePressures();
// const auto localGroupAndNetworkData = simulator_.problem().wellModel()
// .groupAndNetworkData(reportStepNum);
//
// const auto localAquiferData = simulator_.problem().aquiferModel().aquiferData();
// const auto localWellTestState = simulator_.problem().wellModel().wellTestState();
const auto localWellData = simulator_.problem().wellModel().wellData();
const auto localWBP = simulator_.problem().wellModel().wellBlockAveragePressures();
const auto localGroupAndNetworkData = simulator_.problem().wellModel()
.groupAndNetworkData(reportStepNum);
const auto localAquiferData = simulator_.problem().aquiferModel().aquiferData();
const auto localWellTestState = simulator_.problem().wellModel().wellTestState();
this->prepareLocalCellData(isSubStep, reportStepNum);
if (this->outputModule_->needInterfaceFluxes(isSubStep)) {
this->captureLocalFluxData();
}
// if (this->collectOnIORank_.isParallel()) {
// OPM_BEGIN_PARALLEL_TRY_CATCH()
//
// this->collectOnIORank_.collect({},
// outputModule_->getBlockData(),
// localWellData,
// localWBP,
// localGroupAndNetworkData,
// localAquiferData,
// localWellTestState,
// this->outputModule_->getInterRegFlows(),
// {},
// {});
//
// if (this->collectOnIORank_.isIORank()) {
// auto& iregFlows = this->collectOnIORank_.globalInterRegFlows();
//
// if (! iregFlows.readIsConsistent()) {
// throw std::runtime_error {
// "Inconsistent inter-region flow "
// "region set names in parallel"
// };
// }
//
// iregFlows.compress();
// }
//
// OPM_END_PARALLEL_TRY_CATCH("Collect to I/O rank: ",
// this->simulator_.vanguard().grid().comm());
// }
if (this->collectOnIORank_.isParallel()) {
OPM_BEGIN_PARALLEL_TRY_CATCH()
this->collectOnIORank_.collect({},
outputModule_->getBlockData(),
localWellData,
localWBP,
localGroupAndNetworkData,
localAquiferData,
localWellTestState,
this->outputModule_->getInterRegFlows(),
{},
{});
if (this->collectOnIORank_.isIORank()) {
auto& iregFlows = this->collectOnIORank_.globalInterRegFlows();
if (! iregFlows.readIsConsistent()) {
throw std::runtime_error {
"Inconsistent inter-region flow "
"region set names in parallel"
};
}
iregFlows.compress();
}
OPM_END_PARALLEL_TRY_CATCH("Collect to I/O rank: ",
this->simulator_.vanguard().grid().comm());
}
std::map<std::string, double> miscSummaryData;
@@ -323,11 +323,6 @@ public:
? this->collectOnIORank_.globalInterRegFlows()
: this->outputModule_->getInterRegFlows();
const data::Wells& localWellData {};
const data::WellBlockAveragePressures& localWBP{};
const data::GroupAndNetworkValues& localGroupAndNetworkData{};
const std::map<int,data::AquiferData>& localAquiferData {};
this->evalSummary(reportStepNum,
curTime,
localWellData,
@@ -420,20 +415,19 @@ public:
this->outputModule_->outputErrorLog(simulator_.gridView().comm());
// output using eclWriter if enabled
// auto localWellData = simulator_.problem().wellModel().wellData();
// auto localGroupAndNetworkData = simulator_.problem().wellModel()
// .groupAndNetworkData(reportStepNum);
auto localWellData = simulator_.problem().wellModel().wellData();
auto localGroupAndNetworkData = simulator_.problem().wellModel()
.groupAndNetworkData(reportStepNum);
auto localAquiferData = simulator_.problem().aquiferModel().aquiferData();
auto localWellTestState = simulator_.problem().wellModel().wellTestState();
const bool isFlowsn = this->outputModule_->hasFlowsn();
auto flowsn = this->outputModule_->getFlowsn();
const bool isFloresn = this->outputModule_->hasFloresn();
auto floresn = this->outputModule_->getFloresn();
// auto localAquiferData = simulator_.problem().aquiferModel().aquiferData();
// auto localWellTestState = simulator_.problem().wellModel().wellTestState();
//
// const bool isFlowsn = this->outputModule_->hasFlowsn();
// auto flowsn = this->outputModule_->getFlowsn();
//
// const bool isFloresn = this->outputModule_->hasFloresn();
// auto floresn = this->outputModule_->getFloresn();
//
// data::Solution localCellData = {};
if (! isSubStep || Parameters::Get<Parameters::EnableWriteAllSolutions>()) {
if (localCellData.empty()) {
@@ -443,7 +437,7 @@ public:
// Collect RFT data on rank 0
this->outputModule_->accumulateRftDataParallel(simulator_.gridView().comm());
// Add cell data to perforations for RFT output
// this->outputModule_->addRftDataToWells(localWellData, reportStepNum);
this->outputModule_->addRftDataToWells(localWellData, reportStepNum);
}
if (this->collectOnIORank_.isParallel() ||
@@ -454,19 +448,19 @@ public:
// output. There's consequently no need to collect those
// properties on the I/O rank.
// this->collectOnIORank_.collect(localCellData,
// this->outputModule_->getBlockData(),
// localWellData,
// /* wbpData = */ {},
// localGroupAndNetworkData,
// localAquiferData,
// localWellTestState,
// /* interRegFlows = */ {},
// flowsn,
// floresn);
// if (this->collectOnIORank_.isIORank()) {
// this->outputModule_->assignGlobalFieldsToSolution(this->collectOnIORank_.globalCellData());
// }
this->collectOnIORank_.collect(localCellData,
this->outputModule_->getBlockData(),
localWellData,
/* wbpData = */ {},
localGroupAndNetworkData,
localAquiferData,
localWellTestState,
/* interRegFlows = */ {},
flowsn,
floresn);
if (this->collectOnIORank_.isIORank()) {
this->outputModule_->assignGlobalFieldsToSolution(this->collectOnIORank_.globalCellData());
}
} else {
this->outputModule_->assignGlobalFieldsToSolution(localCellData);
}
@@ -478,24 +472,20 @@ public:
if (Parameters::Get<Parameters::EnableWriteAllSolutions>()) {
timeStepIdx = simulator_.timeStepIndex();
}
this->doWriteOutput(reportStepNum,
timeStepIdx,
isSubStep,
curTime,
nextStepSize,
std::move(localCellData) );
// std::move(localWellData),
// std::move(localGroupAndNetworkData),
// std::move(localAquiferData),
// std::move(localWellTestState),
// this->actionState(),
// this->udqState(),
// this->summaryState(),
// this->simulator_.problem().thresholdPressure().getRestartVector(),
// curTime, nextStepSize,
// Parameters::Get<Parameters::EclOutputDoublePrecision>(),
// isFlowsn, std::move(flowsn),
// isFloresn, std::move(floresn));
this->doWriteOutput(reportStepNum, timeStepIdx, isSubStep,
std::move(localCellData),
std::move(localWellData),
std::move(localGroupAndNetworkData),
std::move(localAquiferData),
std::move(localWellTestState),
this->actionState(),
this->udqState(),
this->summaryState(),
{}, // this->simulator_.problem().thresholdPressure().getRestartVector(),
curTime, nextStepSize,
Parameters::Get<Parameters::EclOutputDoublePrecision>(),
isFlowsn, std::move(flowsn),
isFloresn, std::move(floresn));
}
}
@@ -745,26 +735,26 @@ private:
this->outputModule_->accumulateDensityParallel();
}
// if constexpr (enableMech) {
// if (simulator_.vanguard().eclState().runspec().mech()) {
// OPM_TIMEBLOCK(prepareMechData);
// for (const auto& elem : elements(gridView, Dune::Partitions::interior)) {
// elemCtx.updatePrimaryStencil(elem);
// elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
// outputModule_->processElementMech(elemCtx);
// }
// }
// }
if constexpr (enableMech) {
if (simulator_.vanguard().eclState().runspec().mech()) {
OPM_TIMEBLOCK(prepareMechData);
for (const auto& elem : elements(gridView, Dune::Partitions::interior)) {
elemCtx.updatePrimaryStencil(elem);
elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
outputModule_->processElementMech(elemCtx);
}
}
}
// if (! this->simulator_.model().linearizer().getFlowsInfo().empty()) {
// OPM_TIMEBLOCK(prepareFlowsData);
// for (const auto& elem : elements(gridView, Dune::Partitions::interior)) {
// elemCtx.updatePrimaryStencil(elem);
// elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
//
// this->outputModule_->processElementFlows(elemCtx);
// }
// }
if (! this->simulator_.model().linearizer().getFlowsInfo().empty()) {
OPM_TIMEBLOCK(prepareFlowsData);
for (const auto& elem : elements(gridView, Dune::Partitions::interior)) {
elemCtx.updatePrimaryStencil(elem);
elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
this->outputModule_->processElementFlows(elemCtx);
}
}
{
OPM_TIMEBLOCK(prepareBlockData);