mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #5742 from akva2/more_code_generic_well_model
More some more code to generic well model
This commit is contained in:
@@ -815,7 +815,7 @@ private:
|
||||
const SimulatorTimerInterface& timer,
|
||||
const Domain& domain)
|
||||
{
|
||||
auto initial_local_well_primary_vars = model_.wellModel().getPrimaryVarsDomain(domain);
|
||||
auto initial_local_well_primary_vars = model_.wellModel().getPrimaryVarsDomain(domain.index);
|
||||
auto initial_local_solution = Details::extractVector(solution, domain.cells);
|
||||
auto res = solveDomain(domain, timer, logger, iteration, false);
|
||||
local_report = res.first;
|
||||
@@ -825,7 +825,7 @@ private:
|
||||
Details::setGlobal(initial_local_solution, domain.cells, solution);
|
||||
model_.simulator().model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0, domain);
|
||||
} else {
|
||||
model_.wellModel().setPrimaryVarsDomain(domain, initial_local_well_primary_vars);
|
||||
model_.wellModel().setPrimaryVarsDomain(domain.index, initial_local_well_primary_vars);
|
||||
Details::setGlobal(initial_local_solution, domain.cells, solution);
|
||||
model_.simulator().model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0, domain);
|
||||
}
|
||||
@@ -840,7 +840,7 @@ private:
|
||||
const SimulatorTimerInterface& timer,
|
||||
const Domain& domain)
|
||||
{
|
||||
auto initial_local_well_primary_vars = model_.wellModel().getPrimaryVarsDomain(domain);
|
||||
auto initial_local_well_primary_vars = model_.wellModel().getPrimaryVarsDomain(domain.index);
|
||||
auto initial_local_solution = Details::extractVector(solution, domain.cells);
|
||||
auto res = solveDomain(domain, timer, logger, iteration, true);
|
||||
local_report = res.first;
|
||||
@@ -881,7 +881,7 @@ private:
|
||||
auto local_solution = Details::extractVector(solution, domain.cells);
|
||||
Details::setGlobal(local_solution, domain.cells, locally_solved);
|
||||
} else {
|
||||
model_.wellModel().setPrimaryVarsDomain(domain, initial_local_well_primary_vars);
|
||||
model_.wellModel().setPrimaryVarsDomain(domain.index, initial_local_well_primary_vars);
|
||||
Details::setGlobal(initial_local_solution, domain.cells, solution);
|
||||
model_.simulator().model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0, domain);
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ template<class Scalar> class WellContributions;
|
||||
|
||||
data::WellBlockAveragePressures wellBlockAveragePressures() const
|
||||
{
|
||||
return this->computeWellBlockAveragePressures();
|
||||
return this->computeWellBlockAveragePressures(this->gravity_);
|
||||
}
|
||||
|
||||
// subtract B*inv(D)*C * x from A*x
|
||||
@@ -387,10 +387,6 @@ template<class Scalar> class WellContributions;
|
||||
const Domain& domain);
|
||||
void updateWellControlsDomain(DeferredLogger& deferred_logger, const Domain& domain);
|
||||
|
||||
void logPrimaryVars() const;
|
||||
std::vector<Scalar> getPrimaryVarsDomain(const Domain& domain) const;
|
||||
void setPrimaryVarsDomain(const Domain& domain, const std::vector<Scalar>& vars);
|
||||
|
||||
void setupDomains(const std::vector<Domain>& domains);
|
||||
|
||||
protected:
|
||||
@@ -429,14 +425,6 @@ template<class Scalar> class WellContributions;
|
||||
std::unique_ptr<RateConverterType> rateConverter_{};
|
||||
std::map<std::string, std::unique_ptr<AverageRegionalPressureType>> regionalAveragePressureCalculator_{};
|
||||
|
||||
struct WBPCalcID
|
||||
{
|
||||
std::optional<typename std::vector<WellInterfacePtr>::size_type> openWellIdx_{};
|
||||
std::size_t wbpCalcIdx_{};
|
||||
};
|
||||
|
||||
std::vector<WBPCalcID> wbpCalcMap_{};
|
||||
|
||||
SimulatorReportSingle last_report_{};
|
||||
|
||||
// Pre-step network solve at static reservoir conditions (group and well states might be updated)
|
||||
@@ -447,9 +435,6 @@ template<class Scalar> class WellContributions;
|
||||
|
||||
std::vector<Scalar> B_avg_{};
|
||||
|
||||
// Keep track of the domain of each well, if using subdomains.
|
||||
std::map<std::string, int> well_domain_;
|
||||
|
||||
// Store the local index of the wells perforated cells in the domain, if using subdomains
|
||||
SparseTable<int> well_local_cells_;
|
||||
|
||||
@@ -515,16 +500,6 @@ template<class Scalar> class WellContributions;
|
||||
// setting the well_solutions_ based on well_state.
|
||||
void updatePrimaryVariables(DeferredLogger& deferred_logger);
|
||||
|
||||
void initializeWBPCalculationService();
|
||||
|
||||
data::WellBlockAveragePressures
|
||||
computeWellBlockAveragePressures() const;
|
||||
|
||||
typename ParallelWBPCalculation<Scalar>::EvaluatorFactory
|
||||
makeWellSourceEvaluatorFactory(const std::vector<Well>::size_type wellIdx) const;
|
||||
|
||||
void registerOpenWellsForWBPCalculation();
|
||||
|
||||
void updateAverageFormationFactor();
|
||||
|
||||
void computePotentials(const std::size_t widx,
|
||||
|
||||
@@ -69,9 +69,8 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <stack>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
#include <sstream>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
@@ -2041,6 +2040,182 @@ updateFiltrationModelsPreStep(DeferredLogger& deferred_logger)
|
||||
}
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
void BlackoilWellModelGeneric<Scalar>::
|
||||
logPrimaryVars() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
for (const auto& w : this->well_container_generic_) {
|
||||
os << w->name() << ":";
|
||||
auto pv = w->getPrimaryVars();
|
||||
for (const Scalar v : pv) {
|
||||
os << ' ' << v;
|
||||
}
|
||||
os << '\n';
|
||||
}
|
||||
OpmLog::debug(os.str());
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
std::vector<Scalar>
|
||||
BlackoilWellModelGeneric<Scalar>::
|
||||
getPrimaryVarsDomain(const int domainIdx) const
|
||||
{
|
||||
std::vector<Scalar> ret;
|
||||
for (const auto& well : this->well_container_generic_) {
|
||||
if (this->well_domain_.at(well->name()) == domainIdx) {
|
||||
const auto& pv = well->getPrimaryVars();
|
||||
ret.insert(ret.end(), pv.begin(), pv.end());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
void BlackoilWellModelGeneric<Scalar>::
|
||||
setPrimaryVarsDomain(const int domainIdx, const std::vector<Scalar>& vars)
|
||||
{
|
||||
std::size_t offset = 0;
|
||||
for (auto& well : this->well_container_generic_) {
|
||||
if (this->well_domain_.at(well->name()) == domainIdx) {
|
||||
int num_pri_vars = well->setPrimaryVars(vars.begin() + offset);
|
||||
offset += num_pri_vars;
|
||||
}
|
||||
}
|
||||
assert(offset == vars.size());
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
void BlackoilWellModelGeneric<Scalar>::
|
||||
registerOpenWellsForWBPCalculation()
|
||||
{
|
||||
assert (this->wbpCalcMap_.size() == this->wells_ecl_.size());
|
||||
|
||||
for (auto& wbpCalc : this->wbpCalcMap_) {
|
||||
wbpCalc.openWellIdx_.reset();
|
||||
}
|
||||
|
||||
auto openWellIdx = typename std::vector<WellInterfaceGeneric<Scalar>*>::size_type{0};
|
||||
for (const auto* openWell : this->well_container_generic_) {
|
||||
this->wbpCalcMap_[openWell->indexOfWell()].openWellIdx_ = openWellIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
typename ParallelWBPCalculation<Scalar>::EvaluatorFactory
|
||||
BlackoilWellModelGeneric<Scalar>::
|
||||
makeWellSourceEvaluatorFactory(const std::vector<Well>::size_type wellIdx) const
|
||||
{
|
||||
using Span = typename PAvgDynamicSourceData<Scalar>::template SourceDataSpan<Scalar>;
|
||||
using Item = typename Span::Item;
|
||||
|
||||
return [wellIdx, this]() -> typename ParallelWBPCalculation<Scalar>::Evaluator
|
||||
{
|
||||
if (! this->wbpCalcMap_[wellIdx].openWellIdx_.has_value()) {
|
||||
// Well is stopped/shut. Return evaluator for stopped wells.
|
||||
return []([[maybe_unused]] const int connIdx, Span sourceTerm)
|
||||
{
|
||||
// Well/connection is stopped/shut. Set all items to
|
||||
// zero.
|
||||
|
||||
sourceTerm
|
||||
.set(Item::Pressure , 0.0)
|
||||
.set(Item::PoreVol , 0.0)
|
||||
.set(Item::MixtureDensity, 0.0)
|
||||
.set(Item::Depth , 0.0)
|
||||
;
|
||||
};
|
||||
}
|
||||
|
||||
// Well is open. Return an evaluator for open wells/open connections.
|
||||
return [this, wellPtr = this->well_container_generic_[*this->wbpCalcMap_[wellIdx].openWellIdx_]]
|
||||
(const int connIdx, Span sourceTerm)
|
||||
{
|
||||
// Note: The only item which actually matters for the WBP
|
||||
// calculation at the well reservoir connection level is the
|
||||
// mixture density. Set other items to zero.
|
||||
|
||||
const auto& connIdxMap =
|
||||
this->conn_idx_map_[wellPtr->indexOfWell()];
|
||||
|
||||
const auto rho = wellPtr->
|
||||
connectionDensity(connIdxMap.global(connIdx),
|
||||
connIdxMap.open(connIdx));
|
||||
|
||||
sourceTerm
|
||||
.set(Item::Pressure , 0.0)
|
||||
.set(Item::PoreVol , 0.0)
|
||||
.set(Item::MixtureDensity, rho)
|
||||
.set(Item::Depth , 0.0)
|
||||
;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
void BlackoilWellModelGeneric<Scalar>::
|
||||
initializeWBPCalculationService()
|
||||
{
|
||||
this->wbpCalcMap_.clear();
|
||||
this->wbpCalcMap_.resize(this->wells_ecl_.size());
|
||||
|
||||
this->registerOpenWellsForWBPCalculation();
|
||||
|
||||
auto wellID = std::size_t{0};
|
||||
for (const auto& well : this->wells_ecl_) {
|
||||
this->wbpCalcMap_[wellID].wbpCalcIdx_ = this->wbpCalculationService_
|
||||
.createCalculator(well,
|
||||
this->local_parallel_well_info_[wellID],
|
||||
this->conn_idx_map_[wellID].local(),
|
||||
this->makeWellSourceEvaluatorFactory(wellID));
|
||||
|
||||
++wellID;
|
||||
}
|
||||
|
||||
this->wbpCalculationService_.defineCommunication();
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
data::WellBlockAveragePressures
|
||||
BlackoilWellModelGeneric<Scalar>::
|
||||
computeWellBlockAveragePressures(const Scalar gravity) const
|
||||
{
|
||||
auto wbpResult = data::WellBlockAveragePressures{};
|
||||
|
||||
using Calculated = typename PAvgCalculatorResult<Scalar>::WBPMode;
|
||||
using Output = data::WellBlockAvgPress::Quantity;
|
||||
|
||||
this->wbpCalculationService_.collectDynamicValues();
|
||||
|
||||
const auto numWells = this->wells_ecl_.size();
|
||||
for (auto wellID = 0*numWells; wellID < numWells; ++wellID) {
|
||||
const auto calcIdx = this->wbpCalcMap_[wellID].wbpCalcIdx_;
|
||||
const auto& well = this->wells_ecl_[wellID];
|
||||
|
||||
if (! well.hasRefDepth()) {
|
||||
// Can't perform depth correction without at least a
|
||||
// fall-back datum depth.
|
||||
continue;
|
||||
}
|
||||
|
||||
this->wbpCalculationService_
|
||||
.inferBlockAveragePressures(calcIdx, well.pavg(),
|
||||
gravity,
|
||||
well.getWPaveRefDepth());
|
||||
|
||||
const auto& result = this->wbpCalculationService_
|
||||
.averagePressures(calcIdx);
|
||||
|
||||
auto& reported = wbpResult.values[well.name()];
|
||||
|
||||
reported[Output::WBP] = result.value(Calculated::WBP);
|
||||
reported[Output::WBP4] = result.value(Calculated::WBP4);
|
||||
reported[Output::WBP5] = result.value(Calculated::WBP5);
|
||||
reported[Output::WBP9] = result.value(Calculated::WBP9);
|
||||
}
|
||||
|
||||
return wbpResult;
|
||||
}
|
||||
|
||||
template class BlackoilWellModelGeneric<double>;
|
||||
|
||||
|
||||
@@ -219,6 +219,10 @@ public:
|
||||
}
|
||||
bool wasDynamicallyShutThisTimeStep(const std::string& well_name) const;
|
||||
|
||||
void logPrimaryVars() const;
|
||||
std::vector<Scalar> getPrimaryVarsDomain(const int domainIdx) const;
|
||||
void setPrimaryVarsDomain(const int domainIdx, const std::vector<Scalar>& vars);
|
||||
|
||||
template<class Serializer>
|
||||
void serializeOp(Serializer& serializer)
|
||||
{
|
||||
@@ -454,6 +458,16 @@ protected:
|
||||
void assignMassGasRate(data::Wells& wsrpt,
|
||||
const Scalar& gasDensity) const;
|
||||
|
||||
void registerOpenWellsForWBPCalculation();
|
||||
|
||||
typename ParallelWBPCalculation<Scalar>::EvaluatorFactory
|
||||
makeWellSourceEvaluatorFactory(const std::vector<Well>::size_type wellIdx) const;
|
||||
|
||||
void initializeWBPCalculationService();
|
||||
|
||||
data::WellBlockAveragePressures
|
||||
computeWellBlockAveragePressures(const Scalar gravity) const;
|
||||
|
||||
Schedule& schedule_;
|
||||
const SummaryState& summaryState_;
|
||||
const EclipseState& eclState_;
|
||||
@@ -577,6 +591,14 @@ protected:
|
||||
std::vector<WellProdIndexCalculator<Scalar>> prod_index_calc_;
|
||||
mutable ParallelWBPCalculation<Scalar> wbpCalculationService_;
|
||||
|
||||
struct WBPCalcID
|
||||
{
|
||||
std::optional<typename std::vector<WellInterfaceGeneric<Scalar>*>::size_type> openWellIdx_{};
|
||||
std::size_t wbpCalcIdx_{};
|
||||
};
|
||||
|
||||
std::vector<WBPCalcID> wbpCalcMap_{};
|
||||
|
||||
std::vector<int> pvt_region_idx_;
|
||||
|
||||
mutable std::unordered_set<std::string> closed_this_step_;
|
||||
@@ -613,6 +635,9 @@ protected:
|
||||
// Store map of group name and close offending well for output
|
||||
std::map<std::string, std::pair<std::string, std::string>> closed_offending_wells_;
|
||||
|
||||
// Keep track of the domain of each well, if using subdomains.
|
||||
std::map<std::string, int> well_domain_;
|
||||
|
||||
private:
|
||||
WellInterfaceGeneric<Scalar>* getGenWell(const std::string& well_name);
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ namespace Opm {
|
||||
// try/catch here, as this function is not called in
|
||||
// parallel but for each individual domain of each rank.
|
||||
for (const auto& well: well_container_) {
|
||||
if (well_domain_.at(well->name()) == domain.index) {
|
||||
if (this->well_domain_.at(well->name()) == domain.index) {
|
||||
// Modifiy the Jacobian with explicit Schur complement
|
||||
// contributions if requested.
|
||||
if (param_.matrix_add_well_contributions_) {
|
||||
@@ -1187,7 +1187,8 @@ namespace Opm {
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
doPreStepNetworkRebalance(DeferredLogger& deferred_logger) {
|
||||
doPreStepNetworkRebalance(DeferredLogger& deferred_logger)
|
||||
{
|
||||
const double dt = this->simulator_.timeStepSize();
|
||||
// TODO: should we also have the group and network backed-up here in case the solution did not get converged?
|
||||
auto& well_state = this->wellState();
|
||||
@@ -1288,7 +1289,9 @@ namespace Opm {
|
||||
template<typename TypeTag>
|
||||
bool
|
||||
BlackoilWellModel<TypeTag>::
|
||||
updateWellControlsAndNetwork(const bool mandatory_network_balance, const double dt, DeferredLogger& local_deferredLogger)
|
||||
updateWellControlsAndNetwork(const bool mandatory_network_balance,
|
||||
const double dt,
|
||||
DeferredLogger& local_deferredLogger)
|
||||
{
|
||||
// not necessarily that we always need to update once of the network solutions
|
||||
bool do_network_update = true;
|
||||
@@ -1772,7 +1775,7 @@ namespace Opm {
|
||||
assembleWellEqDomain(const double dt, const Domain& domain, DeferredLogger& deferred_logger)
|
||||
{
|
||||
for (auto& well : well_container_) {
|
||||
if (well_domain_.at(well->name()) == domain.index) {
|
||||
if (this->well_domain_.at(well->name()) == domain.index) {
|
||||
well->assembleWellEq(simulator_, dt, this->wellState(), this->groupState(), deferred_logger);
|
||||
}
|
||||
}
|
||||
@@ -1842,7 +1845,7 @@ namespace Opm {
|
||||
{
|
||||
for (size_t well_index = 0; well_index < well_container_.size(); ++well_index) {
|
||||
auto& well = well_container_[well_index];
|
||||
if (well_domain_.at(well->name()) == domainIndex) {
|
||||
if (this->well_domain_.at(well->name()) == domainIndex) {
|
||||
// Well equations B and C uses only the perforated cells, so need to apply on local vectors
|
||||
// transfer global cells index to local subdomain cells index
|
||||
const auto& local_cells = well_local_cells_[well_index];
|
||||
@@ -2082,7 +2085,7 @@ namespace Opm {
|
||||
// parallel but for each individual domain of each rank.
|
||||
DeferredLogger local_deferredLogger;
|
||||
for (auto& well : well_container_) {
|
||||
if (well_domain_.at(well->name()) == domain.index) {
|
||||
if (this->well_domain_.at(well->name()) == domain.index) {
|
||||
const auto& cells = well->cells();
|
||||
x_local_.resize(cells.size());
|
||||
|
||||
@@ -2119,7 +2122,7 @@ namespace Opm {
|
||||
initPrimaryVariablesEvaluationDomain(const Domain& domain) const
|
||||
{
|
||||
for (auto& well : well_container_) {
|
||||
if (well_domain_.at(well->name()) == domain.index) {
|
||||
if (this->well_domain_.at(well->name()) == domain.index) {
|
||||
well->initPrimaryVariablesEvaluation();
|
||||
}
|
||||
}
|
||||
@@ -2142,7 +2145,7 @@ namespace Opm {
|
||||
|
||||
ConvergenceReport report;
|
||||
for (const auto& well : well_container_) {
|
||||
if ((well_domain_.at(well->name()) == domain.index)) {
|
||||
if ((this->well_domain_.at(well->name()) == domain.index)) {
|
||||
if (well->isOperableAndSolvable() || well->wellIsStopped()) {
|
||||
report += well->getWellConvergence(simulator_,
|
||||
this->wellState(),
|
||||
@@ -2245,7 +2248,9 @@ namespace Opm {
|
||||
template<typename TypeTag>
|
||||
std::pair<bool, bool>
|
||||
BlackoilWellModel<TypeTag>::
|
||||
updateWellControls(const bool mandatory_network_balance, DeferredLogger& deferred_logger, const bool relax_network_tolerance)
|
||||
updateWellControls(const bool mandatory_network_balance,
|
||||
DeferredLogger& deferred_logger,
|
||||
const bool relax_network_tolerance)
|
||||
{
|
||||
const int episodeIdx = simulator_.episodeIndex();
|
||||
const auto& network = this->schedule()[episodeIdx].network();
|
||||
@@ -2346,7 +2351,7 @@ namespace Opm {
|
||||
|
||||
// Check only individual well constraints and communicate.
|
||||
for (const auto& well : well_container_) {
|
||||
if (well_domain_.at(well->name()) == domain.index) {
|
||||
if (this->well_domain_.at(well->name()) == domain.index) {
|
||||
const auto mode = WellInterface<TypeTag>::IndividualOrGroup::Individual;
|
||||
well->updateWellControl(simulator_, mode, this->wellState(), this->groupState(), deferred_logger);
|
||||
}
|
||||
@@ -2357,156 +2362,6 @@ namespace Opm {
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
initializeWBPCalculationService()
|
||||
{
|
||||
this->wbpCalcMap_.clear();
|
||||
this->wbpCalcMap_.resize(this->wells_ecl_.size());
|
||||
|
||||
this->registerOpenWellsForWBPCalculation();
|
||||
|
||||
auto wellID = std::size_t{0};
|
||||
for (const auto& well : this->wells_ecl_) {
|
||||
this->wbpCalcMap_[wellID].wbpCalcIdx_ = this->wbpCalculationService_
|
||||
.createCalculator(well,
|
||||
this->local_parallel_well_info_[wellID],
|
||||
this->conn_idx_map_[wellID].local(),
|
||||
this->makeWellSourceEvaluatorFactory(wellID));
|
||||
|
||||
++wellID;
|
||||
}
|
||||
|
||||
this->wbpCalculationService_.defineCommunication();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
data::WellBlockAveragePressures
|
||||
BlackoilWellModel<TypeTag>::
|
||||
computeWellBlockAveragePressures() const
|
||||
{
|
||||
auto wbpResult = data::WellBlockAveragePressures{};
|
||||
|
||||
using Calculated = typename PAvgCalculatorResult<Scalar>::WBPMode;
|
||||
using Output = data::WellBlockAvgPress::Quantity;
|
||||
|
||||
this->wbpCalculationService_.collectDynamicValues();
|
||||
|
||||
const auto numWells = this->wells_ecl_.size();
|
||||
for (auto wellID = 0*numWells; wellID < numWells; ++wellID) {
|
||||
const auto calcIdx = this->wbpCalcMap_[wellID].wbpCalcIdx_;
|
||||
const auto& well = this->wells_ecl_[wellID];
|
||||
|
||||
if (! well.hasRefDepth()) {
|
||||
// Can't perform depth correction without at least a
|
||||
// fall-back datum depth.
|
||||
continue;
|
||||
}
|
||||
|
||||
this->wbpCalculationService_
|
||||
.inferBlockAveragePressures(calcIdx, well.pavg(),
|
||||
this->gravity_,
|
||||
well.getWPaveRefDepth());
|
||||
|
||||
const auto& result = this->wbpCalculationService_
|
||||
.averagePressures(calcIdx);
|
||||
|
||||
auto& reported = wbpResult.values[well.name()];
|
||||
|
||||
reported[Output::WBP] = result.value(Calculated::WBP);
|
||||
reported[Output::WBP4] = result.value(Calculated::WBP4);
|
||||
reported[Output::WBP5] = result.value(Calculated::WBP5);
|
||||
reported[Output::WBP9] = result.value(Calculated::WBP9);
|
||||
}
|
||||
|
||||
return wbpResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
typename ParallelWBPCalculation<typename BlackoilWellModel<TypeTag>::Scalar>::EvaluatorFactory
|
||||
BlackoilWellModel<TypeTag>::
|
||||
makeWellSourceEvaluatorFactory(const std::vector<Well>::size_type wellIdx) const
|
||||
{
|
||||
using Span = typename PAvgDynamicSourceData<Scalar>::template SourceDataSpan<Scalar>;
|
||||
using Item = typename Span::Item;
|
||||
|
||||
return [wellIdx, this]() -> typename ParallelWBPCalculation<Scalar>::Evaluator
|
||||
{
|
||||
if (! this->wbpCalcMap_[wellIdx].openWellIdx_.has_value()) {
|
||||
// Well is stopped/shut. Return evaluator for stopped wells.
|
||||
return []([[maybe_unused]] const int connIdx, Span sourceTerm)
|
||||
{
|
||||
// Well/connection is stopped/shut. Set all items to
|
||||
// zero.
|
||||
|
||||
sourceTerm
|
||||
.set(Item::Pressure , 0.0)
|
||||
.set(Item::PoreVol , 0.0)
|
||||
.set(Item::MixtureDensity, 0.0)
|
||||
.set(Item::Depth , 0.0)
|
||||
;
|
||||
};
|
||||
}
|
||||
|
||||
// Well is open. Return an evaluator for open wells/open connections.
|
||||
return [this, wellPtr = this->well_container_[*this->wbpCalcMap_[wellIdx].openWellIdx_].get()]
|
||||
(const int connIdx, Span sourceTerm)
|
||||
{
|
||||
// Note: The only item which actually matters for the WBP
|
||||
// calculation at the well reservoir connection level is the
|
||||
// mixture density. Set other items to zero.
|
||||
|
||||
const auto& connIdxMap =
|
||||
this->conn_idx_map_[wellPtr->indexOfWell()];
|
||||
|
||||
const auto rho = wellPtr->
|
||||
connectionDensity(connIdxMap.global(connIdx),
|
||||
connIdxMap.open(connIdx));
|
||||
|
||||
sourceTerm
|
||||
.set(Item::Pressure , 0.0)
|
||||
.set(Item::PoreVol , 0.0)
|
||||
.set(Item::MixtureDensity, rho)
|
||||
.set(Item::Depth , 0.0)
|
||||
;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
registerOpenWellsForWBPCalculation()
|
||||
{
|
||||
assert (this->wbpCalcMap_.size() == this->wells_ecl_.size());
|
||||
|
||||
for (auto& wbpCalc : this->wbpCalcMap_) {
|
||||
wbpCalc.openWellIdx_.reset();
|
||||
}
|
||||
|
||||
auto openWellIdx = typename std::vector<WellInterfacePtr>::size_type{0};
|
||||
for (const auto* openWell : this->well_container_generic_) {
|
||||
this->wbpCalcMap_[openWell->indexOfWell()].openWellIdx_ = openWellIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
@@ -2985,59 +2840,6 @@ namespace Opm {
|
||||
}
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
logPrimaryVars() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
for (const auto& w : well_container_) {
|
||||
os << w->name() << ":";
|
||||
auto pv = w->getPrimaryVars();
|
||||
for (const Scalar v : pv) {
|
||||
os << ' ' << v;
|
||||
}
|
||||
os << '\n';
|
||||
}
|
||||
OpmLog::debug(os.str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
std::vector<typename BlackoilWellModel<TypeTag>::Scalar>
|
||||
BlackoilWellModel<TypeTag>::
|
||||
getPrimaryVarsDomain(const Domain& domain) const
|
||||
{
|
||||
std::vector<Scalar> ret;
|
||||
for (const auto& well : well_container_) {
|
||||
if (well_domain_.at(well->name()) == domain.index) {
|
||||
const auto& pv = well->getPrimaryVars();
|
||||
ret.insert(ret.end(), pv.begin(), pv.end());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
setPrimaryVarsDomain(const Domain& domain, const std::vector<Scalar>& vars)
|
||||
{
|
||||
std::size_t offset = 0;
|
||||
for (auto& well : well_container_) {
|
||||
if (well_domain_.at(well->name()) == domain.index) {
|
||||
int num_pri_vars = well->setPrimaryVars(vars.begin() + offset);
|
||||
offset += num_pri_vars;
|
||||
}
|
||||
}
|
||||
assert(offset == vars.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
@@ -3060,7 +2862,7 @@ namespace Opm {
|
||||
if (cell_present(first_well_cell)) {
|
||||
// Assuming that if the first well cell is found in a domain,
|
||||
// then all of that well's cells are in that same domain.
|
||||
well_domain_[wellPtr->name()] = domain.index;
|
||||
this->well_domain_[wellPtr->name()] = domain.index;
|
||||
|
||||
// Verify that all of that well's cells are in that same domain.
|
||||
for (int well_cell : wellPtr->cells()) {
|
||||
@@ -3080,10 +2882,10 @@ namespace Opm {
|
||||
const Opm::Parallel::Communication& comm = grid().comm();
|
||||
const int rank = comm.rank();
|
||||
DeferredLogger local_log;
|
||||
if (!well_domain_.empty()) {
|
||||
if (!this->well_domain_.empty()) {
|
||||
std::ostringstream os;
|
||||
os << "Well name Rank Domain\n";
|
||||
for (const auto& [wname, domain] : well_domain_) {
|
||||
for (const auto& [wname, domain] : this->well_domain_) {
|
||||
os << wname << std::setw(19 - wname.size()) << rank << std::setw(12) << domain << '\n';
|
||||
}
|
||||
local_log.debug(os.str());
|
||||
@@ -3099,7 +2901,7 @@ namespace Opm {
|
||||
std::vector<int> local_cells;
|
||||
for (const auto& well : well_container_) {
|
||||
const auto& global_cells = well->cells();
|
||||
const int domain_index = well_domain_.at(well->name());
|
||||
const int domain_index = this->well_domain_.at(well->name());
|
||||
const auto& domain_cells = domains[domain_index].cells;
|
||||
local_cells.resize(global_cells.size());
|
||||
|
||||
|
||||
@@ -270,9 +270,6 @@ public:
|
||||
WellState<Scalar>& well_state,
|
||||
DeferredLogger& deferred_logger) const = 0;
|
||||
|
||||
virtual Scalar connectionDensity(const int globalConnIdx,
|
||||
const int openConnIdx) const = 0;
|
||||
|
||||
/// \brief Wether the Jacobian will also have well contributions in it.
|
||||
virtual bool jacobianContainsWellContributions() const
|
||||
{
|
||||
@@ -358,16 +355,6 @@ public:
|
||||
return connectionRates_;
|
||||
}
|
||||
|
||||
virtual std::vector<Scalar> getPrimaryVars() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual int setPrimaryVars(typename std::vector<Scalar>::const_iterator)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<Scalar> wellIndex(const int perf,
|
||||
const IntensiveQuantities& intQuants,
|
||||
const Scalar trans_mult,
|
||||
|
||||
@@ -189,6 +189,20 @@ public:
|
||||
|
||||
void resetWellOperability();
|
||||
|
||||
|
||||
virtual std::vector<Scalar> getPrimaryVars() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual int setPrimaryVars(typename std::vector<Scalar>::const_iterator)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Scalar connectionDensity(const int globalConnIdx,
|
||||
const int openConnIdx) const = 0;
|
||||
|
||||
protected:
|
||||
bool getAllowCrossFlow() const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user