mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-01 21:39:09 -06:00
commit
e6042cdc62
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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_;
|
||||
|
@ -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>(
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user