diff --git a/opm/simulators/flow/BlackoilModelNldd.hpp b/opm/simulators/flow/BlackoilModelNldd.hpp index 2a7d501af..1ee045655 100644 --- a/opm/simulators/flow/BlackoilModelNldd.hpp +++ b/opm/simulators/flow/BlackoilModelNldd.hpp @@ -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); } diff --git a/opm/simulators/wells/BlackoilWellModel.hpp b/opm/simulators/wells/BlackoilWellModel.hpp index d2b864b90..a9949c567 100644 --- a/opm/simulators/wells/BlackoilWellModel.hpp +++ b/opm/simulators/wells/BlackoilWellModel.hpp @@ -296,7 +296,7 @@ template 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 WellContributions; const Domain& domain); void updateWellControlsDomain(DeferredLogger& deferred_logger, const Domain& domain); - void logPrimaryVars() const; - std::vector getPrimaryVarsDomain(const Domain& domain) const; - void setPrimaryVarsDomain(const Domain& domain, const std::vector& vars); - void setupDomains(const std::vector& domains); protected: @@ -429,14 +425,6 @@ template class WellContributions; std::unique_ptr rateConverter_{}; std::map> regionalAveragePressureCalculator_{}; - struct WBPCalcID - { - std::optional::size_type> openWellIdx_{}; - std::size_t wbpCalcIdx_{}; - }; - - std::vector 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 WellContributions; std::vector B_avg_{}; - // Keep track of the domain of each well, if using subdomains. - std::map well_domain_; - // Store the local index of the wells perforated cells in the domain, if using subdomains SparseTable well_local_cells_; @@ -515,16 +500,6 @@ template class WellContributions; // setting the well_solutions_ based on well_state. void updatePrimaryVariables(DeferredLogger& deferred_logger); - void initializeWBPCalculationService(); - - data::WellBlockAveragePressures - computeWellBlockAveragePressures() const; - - typename ParallelWBPCalculation::EvaluatorFactory - makeWellSourceEvaluatorFactory(const std::vector::size_type wellIdx) const; - - void registerOpenWellsForWBPCalculation(); - void updateAverageFormationFactor(); void computePotentials(const std::size_t widx, diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.cpp b/opm/simulators/wells/BlackoilWellModelGeneric.cpp index 7023d41f9..ed422668d 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.cpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.cpp @@ -69,9 +69,8 @@ #include #include #include -#include #include -#include +#include #include #include #include @@ -2041,6 +2040,182 @@ updateFiltrationModelsPreStep(DeferredLogger& deferred_logger) } } +template +void BlackoilWellModelGeneric:: +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 +std::vector +BlackoilWellModelGeneric:: +getPrimaryVarsDomain(const int domainIdx) const +{ + std::vector 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 +void BlackoilWellModelGeneric:: +setPrimaryVarsDomain(const int domainIdx, const std::vector& 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 +void BlackoilWellModelGeneric:: +registerOpenWellsForWBPCalculation() +{ + assert (this->wbpCalcMap_.size() == this->wells_ecl_.size()); + + for (auto& wbpCalc : this->wbpCalcMap_) { + wbpCalc.openWellIdx_.reset(); + } + + auto openWellIdx = typename std::vector*>::size_type{0}; + for (const auto* openWell : this->well_container_generic_) { + this->wbpCalcMap_[openWell->indexOfWell()].openWellIdx_ = openWellIdx++; + } +} + +template +typename ParallelWBPCalculation::EvaluatorFactory +BlackoilWellModelGeneric:: +makeWellSourceEvaluatorFactory(const std::vector::size_type wellIdx) const +{ + using Span = typename PAvgDynamicSourceData::template SourceDataSpan; + using Item = typename Span::Item; + + return [wellIdx, this]() -> typename ParallelWBPCalculation::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 +void BlackoilWellModelGeneric:: +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 +data::WellBlockAveragePressures +BlackoilWellModelGeneric:: +computeWellBlockAveragePressures(const Scalar gravity) const +{ + auto wbpResult = data::WellBlockAveragePressures{}; + + using Calculated = typename PAvgCalculatorResult::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; diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.hpp b/opm/simulators/wells/BlackoilWellModelGeneric.hpp index b0107bc01..2ef35efd8 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.hpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.hpp @@ -219,6 +219,10 @@ public: } bool wasDynamicallyShutThisTimeStep(const std::string& well_name) const; + void logPrimaryVars() const; + std::vector getPrimaryVarsDomain(const int domainIdx) const; + void setPrimaryVarsDomain(const int domainIdx, const std::vector& vars); + template void serializeOp(Serializer& serializer) { @@ -454,6 +458,16 @@ protected: void assignMassGasRate(data::Wells& wsrpt, const Scalar& gasDensity) const; + void registerOpenWellsForWBPCalculation(); + + typename ParallelWBPCalculation::EvaluatorFactory + makeWellSourceEvaluatorFactory(const std::vector::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> prod_index_calc_; mutable ParallelWBPCalculation wbpCalculationService_; + struct WBPCalcID + { + std::optional*>::size_type> openWellIdx_{}; + std::size_t wbpCalcIdx_{}; + }; + + std::vector wbpCalcMap_{}; + std::vector pvt_region_idx_; mutable std::unordered_set closed_this_step_; @@ -613,6 +635,9 @@ protected: // Store map of group name and close offending well for output std::map> closed_offending_wells_; + // Keep track of the domain of each well, if using subdomains. + std::map well_domain_; + private: WellInterfaceGeneric* getGenWell(const std::string& well_name); diff --git a/opm/simulators/wells/BlackoilWellModel_impl.hpp b/opm/simulators/wells/BlackoilWellModel_impl.hpp index 58c9b281b..01b8654a4 100644 --- a/opm/simulators/wells/BlackoilWellModel_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModel_impl.hpp @@ -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 void BlackoilWellModel:: - 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 bool BlackoilWellModel:: - 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 std::pair BlackoilWellModel:: - 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::IndividualOrGroup::Individual; well->updateWellControl(simulator_, mode, this->wellState(), this->groupState(), deferred_logger); } @@ -2357,156 +2362,6 @@ namespace Opm { - template - void - BlackoilWellModel:: - 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 - data::WellBlockAveragePressures - BlackoilWellModel:: - computeWellBlockAveragePressures() const - { - auto wbpResult = data::WellBlockAveragePressures{}; - - using Calculated = typename PAvgCalculatorResult::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 ParallelWBPCalculation::Scalar>::EvaluatorFactory - BlackoilWellModel:: - makeWellSourceEvaluatorFactory(const std::vector::size_type wellIdx) const - { - using Span = typename PAvgDynamicSourceData::template SourceDataSpan; - using Item = typename Span::Item; - - return [wellIdx, this]() -> typename ParallelWBPCalculation::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 - void - BlackoilWellModel:: - registerOpenWellsForWBPCalculation() - { - assert (this->wbpCalcMap_.size() == this->wells_ecl_.size()); - - for (auto& wbpCalc : this->wbpCalcMap_) { - wbpCalc.openWellIdx_.reset(); - } - - auto openWellIdx = typename std::vector::size_type{0}; - for (const auto* openWell : this->well_container_generic_) { - this->wbpCalcMap_[openWell->indexOfWell()].openWellIdx_ = openWellIdx++; - } - } - - - - - template void BlackoilWellModel:: @@ -2985,59 +2840,6 @@ namespace Opm { } - template - void - BlackoilWellModel:: - 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 - std::vector::Scalar> - BlackoilWellModel:: - getPrimaryVarsDomain(const Domain& domain) const - { - std::vector 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 - void - BlackoilWellModel:: - setPrimaryVarsDomain(const Domain& domain, const std::vector& 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 void BlackoilWellModel:: @@ -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 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()); diff --git a/opm/simulators/wells/WellInterface.hpp b/opm/simulators/wells/WellInterface.hpp index 9ed3c7a1d..71d4e9702 100644 --- a/opm/simulators/wells/WellInterface.hpp +++ b/opm/simulators/wells/WellInterface.hpp @@ -270,9 +270,6 @@ public: WellState& 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 getPrimaryVars() const - { - return {}; - } - - virtual int setPrimaryVars(typename std::vector::const_iterator) - { - return 0; - } - std::vector wellIndex(const int perf, const IntensiveQuantities& intQuants, const Scalar trans_mult, diff --git a/opm/simulators/wells/WellInterfaceGeneric.hpp b/opm/simulators/wells/WellInterfaceGeneric.hpp index b1268847b..f511eb097 100644 --- a/opm/simulators/wells/WellInterfaceGeneric.hpp +++ b/opm/simulators/wells/WellInterfaceGeneric.hpp @@ -189,6 +189,20 @@ public: void resetWellOperability(); + + virtual std::vector getPrimaryVars() const + { + return {}; + } + + virtual int setPrimaryVars(typename std::vector::const_iterator) + { + return 0; + } + + virtual Scalar connectionDensity(const int globalConnIdx, + const int openConnIdx) const = 0; + protected: bool getAllowCrossFlow() const;