Merge pull request #4275 from daavid00/flres

FLOWS and FLORES support
This commit is contained in:
Bård Skaflestad 2023-02-02 13:03:57 +01:00 committed by GitHub
commit e6042cdc62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 446 additions and 16 deletions

View File

@ -773,7 +773,7 @@ public:
PackUnpackInterRegFlows(const EclInterRegFlowMap& localInterRegFlows,
EclInterRegFlowMap& globalInterRegFlows,
const bool isIORank)
: localInterRegFlows_ (localInterRegFlows)
: localInterRegFlows_(localInterRegFlows)
, globalInterRegFlows_(globalInterRegFlows)
{
if (! isIORank) { return; }
@ -805,6 +805,68 @@ public:
{ this->globalInterRegFlows_.read(buffer); }
};
class PackUnpackFlows : public P2PCommunicatorType::DataHandleInterface
{
const std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>& localFlows_;
std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>& globalFlows_;
public:
PackUnpackFlows(const std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3> & localFlows,
std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>& globalFlows,
const bool isIORank)
: localFlows_(localFlows)
, globalFlows_(globalFlows)
{
if (! isIORank) { return; }
MessageBufferType buffer;
this->pack(0, buffer);
// pass a dummy_link to satisfy virtual class
const int dummyLink = -1;
this->unpack(dummyLink, buffer);
}
void pack(int link, MessageBufferType& buffer)
{
if (link != 0)
throw std::logic_error("link in method pack is not 0 as expected");
for (int i = 0; i < 3; ++i) {
const auto& name = localFlows_[i].first;
buffer.write(name);
unsigned int size = localFlows_[i].second.first.size();
buffer.write(size);
for (unsigned int j = 0; j < size; ++j) {
const auto& nncIdx = localFlows_[i].second.first[j];
buffer.write(nncIdx);
const auto& flows = localFlows_[i].second.second[j];
buffer.write(flows);
}
}
}
void unpack(int /*link*/, MessageBufferType& buffer)
{
for (int i = 0; i < 3; ++i) {
std::string name;
buffer.read(name);
globalFlows_[i].first = name;
unsigned int size = 0;
buffer.read(size);
for (unsigned int j = 0; j < size; ++j) {
int nncIdx;
double data;
buffer.read(nncIdx);
buffer.read(data);
if (nncIdx < 0)
continue;
// This array is initialized in the collect(...) method below
globalFlows_[i].second.second[nncIdx] = data;
}
}
}
};
template <class Grid, class EquilGrid, class GridView>
CollectDataToIORank<Grid,EquilGrid,GridView>::
CollectDataToIORank(const Grid& grid, const EquilGrid* equilGrid,
@ -937,7 +999,9 @@ collect(const data::Solution& localCellData,
const data::GroupAndNetworkValues& localGroupAndNetworkData,
const data::Aquifers& localAquiferData,
const WellTestState& localWellTestState,
const EclInterRegFlowMap& localInterRegFlows)
const EclInterRegFlowMap& localInterRegFlows,
const std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>& localFlowsn,
const std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>& localFloresn)
{
globalCellData_ = {};
globalBlockData_.clear();
@ -947,6 +1011,8 @@ collect(const data::Solution& localCellData,
globalAquiferData_.clear();
globalWellTestState_.clear();
this->globalInterRegFlows_.clear();
globalFlowsn_ = {};
globalFloresn_ = {};
// index maps only have to be build when reordering is needed
if(!needsReordering && !isParallel())
@ -967,6 +1033,16 @@ collect(const data::Solution& localCellData,
return;
}
// Set the right sizes for Flowsn and Floresn
for (int i = 0; i < 3; ++i) {
unsigned int sizeFlr = localFloresn[i].second.first.size();
globalFloresn_[i].second.first.resize(sizeFlr, 0);
globalFloresn_[i].second.second.resize(sizeFlr, 0.0);
unsigned int sizeFlo = localFlowsn[i].second.first.size();
globalFlowsn_[i].second.first.resize(sizeFlo, 0);
globalFlowsn_[i].second.second.resize(sizeFlo, 0.0);
}
PackUnPackWellData packUnpackWellData {
localWellData,
this->globalWellData_,
@ -1009,6 +1085,18 @@ collect(const data::Solution& localCellData,
this->isIORank()
};
PackUnpackFlows packUnpackFlowsn {
localFlowsn,
this->globalFlowsn_,
this->isIORank()
};
PackUnpackFlows packUnpackFloresn {
localFloresn,
this->globalFloresn_,
this->isIORank()
};
toIORankComm_.exchange(packUnpackCellData);
toIORankComm_.exchange(packUnpackWellData);
toIORankComm_.exchange(packUnpackGroupAndNetworkData);
@ -1017,6 +1105,8 @@ collect(const data::Solution& localCellData,
toIORankComm_.exchange(packUnpackAquiferData);
toIORankComm_.exchange(packUnpackWellTestState);
toIORankComm_.exchange(packUnpackInterRegFlows);
toIORankComm_.exchange(packUnpackFlowsn);
toIORankComm_.exchange(packUnpackFloresn);
#ifndef NDEBUG
// make sure every process is on the same page

View File

@ -74,7 +74,9 @@ public:
const data::GroupAndNetworkValues& localGroupAndNetworkData,
const data::Aquifers& localAquiferData,
const WellTestState& localWellTestState,
const EclInterRegFlowMap& interRegFlows);
const EclInterRegFlowMap& interRegFlows,
const std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>& localFlowsn,
const std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>& localFloresn);
const std::map<std::size_t, double>& globalWBPData() const
{ return this->globalWBPData_; }
@ -103,6 +105,12 @@ public:
const EclInterRegFlowMap& globalInterRegFlows() const
{ return this->globalInterRegFlows_; }
const std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>& globalFlowsn() const
{ return globalFlowsn_; }
const std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>& globalFloresn() const
{ return globalFloresn_; }
bool isIORank() const
{ return toIORankComm_.rank() == ioRank; }
@ -142,6 +150,8 @@ protected:
data::Aquifers globalAquiferData_;
WellTestState globalWellTestState_;
std::vector<int> localIdxToGlobalIdx_;
std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3> globalFlowsn_;
std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3> globalFloresn_;
/// \brief sorted list of cartesian indices present-
///
/// non-empty only when running in parallel

View File

@ -139,6 +139,33 @@ EclGenericOutputBlackoilModule(const EclipseState& eclState,
std::string key_pattern = "R" + EclString(phase) + "*";
this->regionNodes_[phase] = summaryConfig_.keywords(key_pattern);
}
// Check if FLORES/FLOWS is set in any RPTRST in the schedule
anyFlores_ = false; // Used for the initialization of the sparse table
anyFlows_ = false;
enableFlores_ = false; // Used for the output of i+, j+, k+
enableFloresn_ = false; // Used for the special case of nnc
enableFlows_ = false;
enableFlowsn_ = false;
for (const auto& block : this->schedule_) { // Uses Schedule::begin() and Schedule::end()
const auto& rstkw = block.rst_config().keywords;
if (! anyFlores_) {
anyFlores_ = rstkw.find("FLORES") != rstkw.end();
}
if (! anyFlows_) {
anyFlows_ = rstkw.find("FLOWS") != rstkw.end();
}
if (anyFlores_ && anyFlows_) {
// Terminate report step loop early if both FLORES and FLOWS
// have been set at some point as there's no need to search
// any further in that case.
break;
}
}
}
template<class FluidSystem, class Scalar>
@ -669,6 +696,24 @@ assignToSolution(data::Solution& sol)
{"1OVERBW", UnitSystem::measure::water_inverse_formation_volume_factor, data::TargetType::RESTART_AUXILIARY, invB_[waterPhaseIdx]},
{"BIOFILM", UnitSystem::measure::identity, data::TargetType::RESTART_SOLUTION, cBiofilm_},
{"CALCITE", UnitSystem::measure::identity, data::TargetType::RESTART_SOLUTION, cCalcite_},
{"FLOGASI+", UnitSystem::measure::gas_surface_rate, data::TargetType::RESTART_SOLUTION, flowsi_[gasCompIdx]},
{"FLOGASJ+", UnitSystem::measure::gas_surface_rate, data::TargetType::RESTART_SOLUTION, flowsj_[gasCompIdx]},
{"FLOGASK+", UnitSystem::measure::gas_surface_rate, data::TargetType::RESTART_SOLUTION, flowsk_[gasCompIdx]},
{"FLOOILI+", UnitSystem::measure::liquid_surface_rate, data::TargetType::RESTART_SOLUTION, flowsi_[oilCompIdx]},
{"FLOOILJ+", UnitSystem::measure::liquid_surface_rate, data::TargetType::RESTART_SOLUTION, flowsj_[oilCompIdx]},
{"FLOOILK+", UnitSystem::measure::liquid_surface_rate, data::TargetType::RESTART_SOLUTION, flowsk_[oilCompIdx]},
{"FLOWATI+", UnitSystem::measure::liquid_surface_rate, data::TargetType::RESTART_SOLUTION, flowsi_[waterCompIdx]},
{"FLOWATJ+", UnitSystem::measure::liquid_surface_rate, data::TargetType::RESTART_SOLUTION, flowsj_[waterCompIdx]},
{"FLOWATK+", UnitSystem::measure::liquid_surface_rate, data::TargetType::RESTART_SOLUTION, flowsk_[waterCompIdx]},
{"FLRGASI+", UnitSystem::measure::rate, data::TargetType::RESTART_SOLUTION, floresi_[gasCompIdx]},
{"FLRGASJ+", UnitSystem::measure::rate, data::TargetType::RESTART_SOLUTION, floresj_[gasCompIdx]},
{"FLRGASK+", UnitSystem::measure::rate, data::TargetType::RESTART_SOLUTION, floresk_[gasCompIdx]},
{"FLROILI+", UnitSystem::measure::rate, data::TargetType::RESTART_SOLUTION, floresi_[oilCompIdx]},
{"FLROILJ+", UnitSystem::measure::rate, data::TargetType::RESTART_SOLUTION, floresj_[oilCompIdx]},
{"FLROILK+", UnitSystem::measure::rate, data::TargetType::RESTART_SOLUTION, floresk_[oilCompIdx]},
{"FLRWATI+", UnitSystem::measure::rate, data::TargetType::RESTART_SOLUTION, floresi_[waterCompIdx]},
{"FLRWATJ+", UnitSystem::measure::rate, data::TargetType::RESTART_SOLUTION, floresj_[waterCompIdx]},
{"FLRWATK+", UnitSystem::measure::rate, data::TargetType::RESTART_SOLUTION, floresk_[waterCompIdx]},
{"FOAM", UnitSystem::measure::identity, data::TargetType::RESTART_SOLUTION, cFoam_},
{"GASKR", UnitSystem::measure::identity, data::TargetType::RESTART_AUXILIARY, relativePermeability_[gasPhaseIdx]},
{"GAS_DEN", UnitSystem::measure::density, data::TargetType::RESTART_AUXILIARY, density_[gasPhaseIdx]},
@ -818,7 +863,7 @@ setRestart(const data::Solution& sol,
permFact_[elemIdx] = sol.data("PERMFACT")[globalDofIndex];
if (!soMax_.empty() && sol.has("SOMAX"))
soMax_[elemIdx] = sol.data("SOMAX")[globalDofIndex];
if (!pcSwMdcOw_.empty() &&sol.has("PCSWM_OW"))
if (!pcSwMdcOw_.empty() && sol.has("PCSWM_OW"))
pcSwMdcOw_[elemIdx] = sol.data("PCSWM_OW")[globalDofIndex];
if (!krnSwMdcOw_.empty() && sol.has("KRNSW_OW"))
krnSwMdcOw_[elemIdx] = sol.data("KRNSW_OW")[globalDofIndex];
@ -879,7 +924,8 @@ doAllocBuffers(unsigned bufferSize,
const bool isRestart,
const bool vapparsActive,
const bool enableHysteresis,
unsigned numTracers)
unsigned numTracers,
unsigned numOutputNnc)
{
// Only output RESTART_AUXILIARY asked for by the user.
std::map<std::string, int> rstKeywords = schedule_.rst_keywords(reportStepNum);
@ -1076,6 +1122,52 @@ doAllocBuffers(unsigned bufferSize,
invB_[gasPhaseIdx].resize(bufferSize, 0.0);
}
enableFlows_ = false;
enableFlowsn_ = false;
if (rstKeywords["FLOWS"] > 0) {
rstKeywords["FLOWS"] = 0;
enableFlows_ = true;
std::array<int, 3> phaseIdxs = { gasPhaseIdx, oilPhaseIdx, waterPhaseIdx };
std::array<int, 3> compIdxs = { gasCompIdx, oilCompIdx, waterCompIdx };
auto rstName = std::array{ "FLOGASN+", "FLOOILN+", "FLOWATN+" };
for (unsigned ii = 0; ii < phaseIdxs.size(); ++ii) {
if (FluidSystem::phaseIsActive(phaseIdxs[ii])) {
flowsi_[compIdxs[ii]].resize(bufferSize, 0.0);
flowsj_[compIdxs[ii]].resize(bufferSize, 0.0);
flowsk_[compIdxs[ii]].resize(bufferSize, 0.0);
if (numOutputNnc > 0) {
enableFlowsn_ = true;
flowsn_[compIdxs[ii]].first = rstName[ii];
flowsn_[compIdxs[ii]].second.first.resize(numOutputNnc, -1);
flowsn_[compIdxs[ii]].second.second.resize(numOutputNnc, 0.0);
}
}
}
}
enableFlores_ = false;
enableFloresn_ = false;
if (rstKeywords["FLORES"] > 0) {
rstKeywords["FLORES"] = 0;
enableFlores_ = true;
std::array<int, 3> phaseIdxs = { gasPhaseIdx, oilPhaseIdx, waterPhaseIdx };
std::array<int, 3> compIdxs = { gasCompIdx, oilCompIdx, waterCompIdx };
auto rstName = std::array{ "FLRGASN+", "FLROILN+", "FLRWATN+" };
for (unsigned ii = 0; ii < phaseIdxs.size(); ++ii) {
if (FluidSystem::phaseIsActive(phaseIdxs[ii])) {
floresi_[compIdxs[ii]].resize(bufferSize, 0.0);
floresj_[compIdxs[ii]].resize(bufferSize, 0.0);
floresk_[compIdxs[ii]].resize(bufferSize, 0.0);
if (numOutputNnc > 0) {
enableFloresn_ = true;
floresn_[compIdxs[ii]].first = rstName[ii];
floresn_[compIdxs[ii]].second.first.resize(numOutputNnc, -1);
floresn_[compIdxs[ii]].second.second.resize(numOutputNnc, 0.0);
}
}
}
}
if (rstKeywords["DEN"] > 0) {
rstKeywords["DEN"] = 0;
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {

View File

@ -189,6 +189,46 @@ public:
return 0;
}
const std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>& getFlowsn() const
{
return this->flowsn_;
}
bool hasFlowsn() const
{
return enableFlowsn_;
}
bool hasFlows() const
{
return enableFlows_;
}
bool anyFlows() const
{
return anyFlows_;
}
const std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>& getFloresn() const
{
return this->floresn_;
}
bool hasFloresn() const
{
return enableFloresn_;
}
bool hasFlores() const
{
return enableFlores_;
}
bool anyFlores() const
{
return anyFlores_;
}
bool needInterfaceFluxes([[maybe_unused]] const bool isSubStep) const
{
return this->interRegionFlows_.wantInterRegflowSummary();
@ -216,9 +256,13 @@ protected:
using ScalarBuffer = std::vector<Scalar>;
using StringBuffer = std::vector<std::string>;
enum { numPhases = FluidSystem::numPhases };
enum { numComponents = FluidSystem::numComponents };
enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
enum { gasCompIdx = FluidSystem::gasCompIdx };
enum { oilCompIdx = FluidSystem::oilCompIdx };
enum { waterCompIdx = FluidSystem::waterCompIdx };
EclGenericOutputBlackoilModule(const EclipseState& eclState,
const Schedule& schedule,
@ -309,7 +353,8 @@ protected:
const bool isRestart,
const bool vapparsActive,
const bool enableHysteresis,
unsigned numTracers);
unsigned numTracers,
unsigned numOutputNnc);
void fipUnitConvert_(std::unordered_map<Inplace::Phase, Scalar>& fip) const;
@ -401,6 +446,13 @@ protected:
bool outputFipRestart_;
bool computeFip_;
bool anyFlows_;
bool anyFlores_;
bool enableFlows_;
bool enableFlores_;
bool enableFlowsn_;
bool enableFloresn_;
std::unordered_map<Inplace::Phase, ScalarBuffer> fip_;
std::unordered_map<std::string, std::vector<int>> regions_;
std::unordered_map<Inplace::Phase, std::vector<SummaryConfigNode>> regionNodes_;
@ -468,6 +520,16 @@ protected:
std::vector<ScalarBuffer> tracerConcentrations_;
std::array<ScalarBuffer, numPhases> flowsi_;
std::array<ScalarBuffer, numPhases> flowsj_;
std::array<ScalarBuffer, numPhases> flowsk_;
std::array<ScalarBuffer, numPhases> floresi_;
std::array<ScalarBuffer, numPhases> floresj_;
std::array<ScalarBuffer, numPhases> floresk_;
std::array<std::pair<std::string, std::pair<std::vector<int>, ScalarBuffer>>, 3> floresn_;
std::array<std::pair<std::string, std::pair<std::vector<int>, ScalarBuffer>>, 3> flowsn_;
std::map<size_t, Scalar> oilConnectionPressures_;
std::map<size_t, Scalar> waterConnectionSaturations_;
std::map<size_t, Scalar> gasConnectionSaturations_;

View File

@ -263,6 +263,13 @@ writeInit(const std::function<unsigned int(unsigned int)>& map)
auto cartMap = cartesianToCompressed(equilGrid_->size(0), UgGridHelpers::globalCell(*equilGrid_));
eclIO_->writeInitial(computeTrans_(cartMap, map), integerVectors, exportNncStructure_(cartMap, map));
}
#if HAVE_MPI
if (collectToIORank_.isParallel()) {
const auto& comm = grid_.comm();
Opm::EclMpiSerializer ser(comm);
ser.broadcast(outputNnc_);
}
#endif
}
template<class Grid, class EquilGrid, class GridView, class ElementMapper, class Scalar>
@ -342,7 +349,6 @@ exportNncStructure_(const std::unordered_map<int,int>& cartesianToActive, const
std::size_t ny = eclState_.getInputGrid().getNY();
auto nncData = eclState_.getInputNNC().input();
const auto& unitSystem = eclState_.getDeckUnitSystem();
std::vector<NNCdata> outputNnc;
std::size_t index = 0;
for( const auto& entry : nncData ) {
@ -355,7 +361,7 @@ exportNncStructure_(const std::unordered_map<int,int>& cartesianToActive, const
auto tt = unitSystem.from_si(UnitSystem::measure::transmissibility, entry.trans);
// Eclipse ignores NNCs (with EDITNNC applied) that are small. Seems like the threshold is 1.0e-6
if ( tt >= 1.0e-6 )
outputNnc.emplace_back(entry.cell1, entry.cell2, entry.trans);
outputNnc_.emplace_back(entry.cell1, entry.cell2, entry.trans);
}
++index;
}
@ -412,11 +418,11 @@ exportNncStructure_(const std::unordered_map<int,int>& cartesianToActive, const
// to zero when setting up the simulator. These will be ignored here, too.
auto tt = unitSystem.from_si(UnitSystem::measure::transmissibility, std::abs(t));
if ( tt > 1e-12 )
outputNnc.push_back({cc1, cc2, t});
outputNnc_.push_back({cc1, cc2, t});
}
}
}
return outputNnc;
return outputNnc_;
}
template<class Grid, class EquilGrid, class GridView, class ElementMapper, class Scalar>
@ -434,7 +440,11 @@ doWriteOutput(const int reportStepNum,
const std::vector<Scalar>& thresholdPressure,
Scalar curTime,
Scalar nextStepSize,
bool doublePrecision)
bool doublePrecision,
bool isFlowsn,
std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>&& flowsn,
bool isFloresn,
std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>&& floresn)
{
const auto isParallel = this->collectToIORank_.isParallel();
const bool needsReordering = this->collectToIORank_.doesNeedReordering();
@ -463,6 +473,29 @@ doWriteOutput(const int reportStepNum,
restartValue.addExtra("OPMEXTRA", std::vector<double>(1, nextStepSize));
}
// Add nnc flows and flores.
if (isFlowsn) {
const auto flowsn_global = isParallel ? this->collectToIORank_.globalFlowsn() : std::move(flowsn);
for (const auto& flows : flowsn_global) {
if (flows.first.empty())
continue;
if (flows.first == "FLOGASN+") {
restartValue.addExtra(flows.first, UnitSystem::measure::gas_surface_rate, flows.second.second);
}
else {
restartValue.addExtra(flows.first, UnitSystem::measure::liquid_surface_rate, flows.second.second);
}
}
}
if (isFloresn) {
const auto floresn_global = isParallel ? this->collectToIORank_.globalFloresn() : std::move(floresn);
for (const auto& flores : floresn_global) {
if (flores.first.empty())
continue;
restartValue.addExtra(flores.first, UnitSystem::measure::rate, flores.second.second);
}
}
// first, create a tasklet to write the data for the current time
// step to disk
auto eclWriteTasklet = std::make_shared<EclWriteTasklet>(

View File

@ -100,6 +100,11 @@ public:
simulation_report_ = report;
}
const std::vector<NNCdata>& getOutputNnc() const
{
return outputNnc_;
}
protected:
const TransmissibilityType& globalTrans() const;
unsigned int gridEquilIdxToGridIdx(unsigned int elemIndex) const;
@ -117,7 +122,11 @@ protected:
const std::vector<Scalar>& thresholdPressure,
Scalar curTime,
Scalar nextStepSize,
bool doublePrecision);
bool doublePrecision,
bool isFlowsn,
std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>&& flowsn,
bool isFloresn,
std::array<std::pair<std::string, std::pair<std::vector<int>, std::vector<double>>>, 3>&& floresn);
void evalSummary(int reportStepNum,
Scalar curTime,
@ -150,6 +159,7 @@ protected:
std::vector<std::size_t> wbp_index_list_;
SimulatorReportSingle sub_step_report_;
SimulatorReport simulation_report_;
mutable std::vector<NNCdata> outputNnc_;
private:
data::Solution computeTrans_(const std::unordered_map<int,int>& cartesianToActive, const std::function<unsigned int(unsigned int)>& map) const;

View File

@ -118,6 +118,7 @@ class EclOutputBlackOilModule : public EclGenericOutputBlackoilModule<GetPropTyp
using Element = typename GridView::template Codim<0>::Entity;
using ElementIterator = typename GridView::template Codim<0>::Iterator;
using BaseType = EclGenericOutputBlackoilModule<FluidSystem, Scalar>;
using Indices = GetPropType<TypeTag, Properties::Indices>;
enum { numPhases = FluidSystem::numPhases };
enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
@ -125,6 +126,7 @@ class EclOutputBlackOilModule : public EclGenericOutputBlackoilModule<GetPropTyp
enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
enum { gasCompIdx = FluidSystem::gasCompIdx };
enum { oilCompIdx = FluidSystem::oilCompIdx };
enum { waterCompIdx = FluidSystem::waterCompIdx };
enum { enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>() };
public:
@ -203,7 +205,8 @@ public:
isRestart,
simulator_.problem().vapparsActive(std::max(simulator_.episodeIndex(), 0)),
simulator_.problem().materialLawManager()->enableHysteresis(),
simulator_.problem().tracerModel().numTracers());
simulator_.problem().tracerModel().numTracers(),
simulator_.problem().eclWriter()->getOutputNnc().size());
}
/*!
@ -685,6 +688,119 @@ public:
= tracerModel.tracerConcentration(tracerIdx, globalDofIdx);
}
}
// flows
if (!problem.model().linearizer().getFlowsInfo().empty()) {
const auto& flowsInf = problem.model().linearizer().getFlowsInfo();
auto flowsInfos = flowsInf[globalDofIdx];
for (auto& flowsInfo : flowsInfos) {
if (flowsInfo.faceId == 1) {
if (!this->flowsi_[gasCompIdx].empty()) {
this->flowsi_[gasCompIdx][globalDofIdx]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(gasCompIdx)];
}
if (!this->flowsi_[oilCompIdx].empty()) {
this->flowsi_[oilCompIdx][globalDofIdx]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(oilCompIdx)];
}
if (!this->flowsi_[waterCompIdx].empty()) {
this->flowsi_[waterCompIdx][globalDofIdx]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(waterCompIdx)];
}
}
if (flowsInfo.faceId == 3) {
if (!this->flowsj_[gasCompIdx].empty()) {
this->flowsj_[gasCompIdx][globalDofIdx]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(gasCompIdx)];
}
if (!this->flowsj_[oilCompIdx].empty()) {
this->flowsj_[oilCompIdx][globalDofIdx]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(oilCompIdx)];
}
if (!this->flowsj_[waterCompIdx].empty()) {
this->flowsj_[waterCompIdx][globalDofIdx]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(waterCompIdx)];
}
}
if (flowsInfo.faceId == 5) {
if (!this->flowsk_[gasCompIdx].empty()) {
this->flowsk_[gasCompIdx][globalDofIdx]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(gasCompIdx)];
}
if (!this->flowsk_[oilCompIdx].empty()) {
this->flowsk_[oilCompIdx][globalDofIdx]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(oilCompIdx)];
}
if (!this->flowsk_[waterCompIdx].empty()) {
this->flowsk_[waterCompIdx][globalDofIdx]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(waterCompIdx)];
}
}
if (flowsInfo.faceId == -2) {
if (!this->flowsn_[gasCompIdx].second.first.empty()) {
this->flowsn_[gasCompIdx].second.first[flowsInfo.nncId] = flowsInfo.nncId;
this->flowsn_[gasCompIdx].second.second[flowsInfo.nncId]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(gasCompIdx)];
}
if (!this->flowsn_[oilCompIdx].second.first.empty()) {
this->flowsn_[oilCompIdx].second.first[flowsInfo.nncId] = flowsInfo.nncId;
this->flowsn_[oilCompIdx].second.second[flowsInfo.nncId]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(oilCompIdx)];
}
if (!this->flowsn_[waterCompIdx].second.first.empty()) {
this->flowsn_[waterCompIdx].second.first[flowsInfo.nncId] = flowsInfo.nncId;
this->flowsn_[waterCompIdx].second.second[flowsInfo.nncId]
= flowsInfo.flow[Indices::canonicalToActiveComponentIndex(waterCompIdx)];
}
}
}
}
// flores
if (!problem.model().linearizer().getFloresInfo().empty()) {
const auto& floresInf = problem.model().linearizer().getFloresInfo();
auto floresInfos =floresInf[globalDofIdx];
for (auto& floresInfo : floresInfos) {
if (floresInfo.faceId == 1) {
if (!this->floresi_[gasCompIdx].empty())
this->floresi_[gasCompIdx][globalDofIdx] = floresInfo.flow[gasPhaseIdx];
if (!this->floresi_[oilCompIdx].empty())
this->floresi_[oilCompIdx][globalDofIdx] = floresInfo.flow[oilPhaseIdx];
if (!this->floresi_[waterCompIdx].empty())
this->floresi_[waterCompIdx][globalDofIdx] = floresInfo.flow[waterPhaseIdx];
}
if (floresInfo.faceId == 3) {
if (!this->floresj_[gasCompIdx].empty())
this->floresj_[gasCompIdx][globalDofIdx] = floresInfo.flow[gasPhaseIdx];
if (!this->floresj_[oilCompIdx].empty())
this->floresj_[oilCompIdx][globalDofIdx] = floresInfo.flow[oilPhaseIdx];
if (!this->floresj_[waterCompIdx].empty())
this->floresj_[waterCompIdx][globalDofIdx] = floresInfo.flow[waterPhaseIdx];
}
if (floresInfo.faceId == 5) {
if (!this->floresk_[gasCompIdx].empty())
this->floresk_[gasCompIdx][globalDofIdx] = floresInfo.flow[gasPhaseIdx];
if (!this->floresk_[oilCompIdx].empty())
this->floresk_[oilCompIdx][globalDofIdx] = floresInfo.flow[oilPhaseIdx];
if (!this->floresk_[waterCompIdx].empty())
this->floresk_[waterCompIdx][globalDofIdx] = floresInfo.flow[waterPhaseIdx];
}
if (floresInfo.faceId == -2) {
if (!this->floresn_[gasCompIdx].second.first.empty()) {
this->floresn_[gasCompIdx].second.first[floresInfo.nncId] = floresInfo.nncId;
this->floresn_[gasCompIdx].second.second[floresInfo.nncId] = floresInfo.flow[gasPhaseIdx];
}
if (!this->floresn_[oilCompIdx].second.first.empty()) {
this->floresn_[oilCompIdx].second.first[floresInfo.nncId] = floresInfo.nncId;
this->floresn_[oilCompIdx].second.second[floresInfo.nncId] = floresInfo.flow[oilPhaseIdx];
}
if (!this->floresn_[waterCompIdx].second.first.empty()) {
this->floresn_[waterCompIdx].second.first[floresInfo.nncId] = floresInfo.nncId;
this->floresn_[waterCompIdx].second.second[floresInfo.nncId] = floresInfo.flow[waterPhaseIdx];
}
}
}
}
}
}

View File

@ -2043,6 +2043,11 @@ public:
return { free, massratebc_(dir)[globalSpaceIdx] };
}
const std::unique_ptr<EclWriterType>& eclWriter() const
{
return eclWriter_;
}
private:
template<class UpdateFunc>
void updateProperty_(const std::string& failureMsg,

View File

@ -224,7 +224,9 @@ public:
localGroupAndNetworkData,
localAquiferData,
localWellTestState,
this->eclOutputModule_->getInterRegFlows());
this->eclOutputModule_->getInterRegFlows(),
{},
{});
if (this->collectToIORank_.isIORank()) {
auto& iregFlows = this->collectToIORank_.globalInterRegFlows();
@ -336,6 +338,10 @@ public:
auto localAquiferData = simulator_.problem().aquiferModel().aquiferData();
auto localWellTestState = simulator_.problem().wellModel().wellTestState();
auto flowsn = this->eclOutputModule_->getFlowsn();
const bool isFlowsn = this->eclOutputModule_->hasFlowsn();
auto floresn = this->eclOutputModule_->getFloresn();
const bool isFloresn = this->eclOutputModule_->hasFloresn();
data::Solution localCellData = {};
if (! isSubStep) {
@ -353,7 +359,9 @@ public:
localGroupAndNetworkData,
localAquiferData,
localWellTestState,
{});
{},
flowsn,
floresn);
}
if (this->collectToIORank_.isIORank()) {
@ -370,7 +378,11 @@ public:
this->summaryState(),
simulator_.problem().thresholdPressure().data(),
curTime, nextStepSize,
EWOMS_GET_PARAM(TypeTag, bool, EclOutputDoublePrecision));
EWOMS_GET_PARAM(TypeTag, bool, EclOutputDoublePrecision),
isFlowsn,
std::move(flowsn),
isFloresn,
std::move(floresn));
}
}