23 #include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>
24 #include <opm/core/props/phaseUsageFromDeck.hpp>
26 #include <opm/parser/eclipse/Units/UnitSystem.hpp>
28 #include <opm/simulators/wells/VFPProperties.hpp>
33 #include <fmt/format.h>
36 template<
typename TypeTag>
37 BlackoilWellModel<TypeTag>::
38 BlackoilWellModel(Simulator& ebosSimulator,
const PhaseUsage& phase_usage)
39 : BlackoilWellModelGeneric(ebosSimulator.vanguard().schedule(),
40 ebosSimulator.vanguard().summaryState(),
41 ebosSimulator.vanguard().eclState(),
43 ebosSimulator.gridView().comm())
44 , ebosSimulator_(ebosSimulator)
46 terminal_output_ = ((ebosSimulator.gridView().comm().rank() == 0) &&
47 EWOMS_GET_PARAM(TypeTag,
bool, EnableTerminalOutput));
49 local_num_cells_ = ebosSimulator_.gridView().size(0);
52 global_num_cells_ = ebosSimulator_.vanguard().globalNumCells();
56 const auto& grid = this->ebosSimulator_.vanguard().grid();
57 const auto& cartDims = UgGridHelpers::cartDims(grid);
58 setupCartesianToCompressed_(UgGridHelpers::globalCell(grid),
59 cartDims[0] * cartDims[1] * cartDims[2]);
61 auto& parallel_wells = ebosSimulator.vanguard().parallelWells();
63 for (
const auto& wellinfo : parallel_wells) {
64 this->parallel_well_info_.emplace_back(wellinfo, grid.comm());
68 this->alternative_well_rate_init_ =
69 EWOMS_GET_PARAM(TypeTag,
bool, AlternativeWellRateInit);
72 template<
typename TypeTag>
73 BlackoilWellModel<TypeTag>::
74 BlackoilWellModel(Simulator& ebosSimulator) :
75 BlackoilWellModel(ebosSimulator,
phaseUsageFromDeck(ebosSimulator.vanguard().eclState()))
79 template<
typename TypeTag>
81 BlackoilWellModel<TypeTag>::
84 extractLegacyCellPvtRegionIndex_();
85 extractLegacyDepth_();
87 gravity_ = ebosSimulator_.problem().gravity()[2];
92 ebosSimulator_.model().addAuxiliaryModule(
this);
94 is_cell_perforated_.resize(local_num_cells_,
false);
98 template<
typename TypeTag>
100 BlackoilWellModel<TypeTag>::
103 for (
auto& wellPtr : this->well_container_) {
104 wellPtr->init(&this->phase_usage_, this->depth_, this->gravity_,
105 this->local_num_cells_, this->B_avg_);
109 template<
typename TypeTag>
111 BlackoilWellModel<TypeTag>::
112 addNeighbors(std::vector<NeighborSet>& neighbors)
const
114 if (!param_.matrix_add_well_contributions_) {
119 const auto& schedule_wells = schedule().getWellsatEnd();
122 for (
const auto& well : schedule_wells)
124 std::vector<int> wellCells;
126 const auto& connectionSet = well.getConnections();
127 wellCells.reserve(connectionSet.size());
129 for (
size_t c=0; c < connectionSet.size(); c++ )
131 const auto& connection = connectionSet.get(c);
132 int compressed_idx = cartesian_to_compressed_
133 .at(connection.global_index());
135 if ( compressed_idx >= 0 ) {
136 wellCells.push_back(compressed_idx);
140 for (
int cellIdx : wellCells) {
141 neighbors[cellIdx].insert(wellCells.begin(),
147 template<
typename TypeTag>
149 BlackoilWellModel<TypeTag>::
150 linearize(SparseMatrixAdapter& jacobian, GlobalEqVector& res)
152 if (!param_.matrix_add_well_contributions_)
154 OPM_BEGIN_PARALLEL_TRY_CATCH();
158 for (
const auto& well: well_container_) {
163 OPM_END_PARALLEL_TRY_CATCH(
"BlackoilWellModel::linearize failed: ",
164 ebosSimulator_.gridView().comm());
168 for (
const auto& well: well_container_) {
169 well->addWellContributions(jacobian);
178 template<
typename TypeTag>
180 BlackoilWellModel<TypeTag>::
181 beginReportStep(
const int timeStepIdx)
183 DeferredLogger local_deferredLogger;
185 report_step_starts_ =
true;
187 const Grid& grid = ebosSimulator_.vanguard().grid();
188 const auto& summaryState = ebosSimulator_.vanguard().summaryState();
190 wells_ecl_ = getLocalWells(timeStepIdx);
191 this->local_parallel_well_info_ = createLocalParallelWellInfo(wells_ecl_);
196 OPM_BEGIN_PARALLEL_TRY_CATCH();
201 this->initializeWellPerfData();
202 this->initializeWellState(timeStepIdx, summaryState);
206 wells_active_ = localWellsActive() ? 1 : 0;
207 wells_active_ = grid.comm().max(wells_active_);
210 if (param_.use_multisegment_well_&& anyMSWellOpenLocal()) {
211 this->wellState().initWellStateMSWell(wells_ecl_, &this->prevWellState());
214 const Group& fieldGroup = schedule().getGroup(
"FIELD", timeStepIdx);
215 WellGroupHelpers::setCmodeGroup(fieldGroup, schedule(), summaryState, timeStepIdx, this->wellState(), this->groupState());
218 rateConverter_.reset(
new RateConverterType (phase_usage_,
219 std::vector<int>(local_num_cells_, 0)));
220 rateConverter_->template defineState<ElementContext>(ebosSimulator_);
223 if (schedule_[timeStepIdx].has_gpmaint()) {
224 const auto& fp = this->eclState_.fieldProps();
225 const auto& fipnum = fp.get_int(
"FIPNUM");
226 regionalAveragePressureCalculator_.reset(
new AverageRegionalPressureType (phase_usage_,fipnum));
230 const auto& sched_state = this->schedule()[timeStepIdx];
232 vfp_properties_.reset(
new VFPProperties( sched_state.vfpinj(), sched_state.vfpprod()) );
233 this->initializeWellProdIndCalculators();
234 if (sched_state.events().hasEvent(ScheduleEvents::Events::WELL_PRODUCTIVITY_INDEX)) {
235 this->runWellPIScaling(timeStepIdx, local_deferredLogger);
239 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
"beginReportStep() failed: ",
240 terminal_output_, grid.comm());
242 this->commitWGState();
247 template<
typename TypeTag>
249 BlackoilWellModel<TypeTag>::
252 updatePerforationIntensiveQuantities();
253 updateAverageFormationFactor();
254 DeferredLogger local_deferredLogger;
256 this->resetWGState();
257 const int reportStepIdx = ebosSimulator_.episodeIndex();
258 updateAndCommunicateGroupData(reportStepIdx,
259 ebosSimulator_.model().newtonMethod().numIterations());
260 this->wellState().gliftTimeStepInit();
261 const double simulationTime = ebosSimulator_.time();
262 OPM_BEGIN_PARALLEL_TRY_CATCH();
265 wellTesting(reportStepIdx, simulationTime, local_deferredLogger);
268 createWellContainer(reportStepIdx);
273 this->initWellContainer();
276 std::fill(is_cell_perforated_.begin(), is_cell_perforated_.end(),
false);
277 for (
auto& well : well_container_) {
278 well->updatePerforatedCell(is_cell_perforated_);
282 calculateEfficiencyFactors(reportStepIdx);
284 if constexpr (has_polymer_)
286 if (PolymerModule::hasPlyshlog() || getPropValue<TypeTag, Properties::EnablePolymerMW>() ) {
287 setRepRadiusPerfLength();
292 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
"beginTimeStep() failed: ",
293 terminal_output_, ebosSimulator_.vanguard().grid().comm());
295 for (
auto& well : well_container_) {
296 well->setVFPProperties(vfp_properties_.get());
297 well->setGuideRate(&guideRate_);
301 for (
auto& well : well_container_) {
302 well->closeCompletions(wellTestState());
307 updateWellPotentials(reportStepIdx,
309 ebosSimulator_.vanguard().summaryConfig(),
310 local_deferredLogger);
311 }
catch ( std::runtime_error& e ) {
312 const std::string msg =
"A zero well potential is returned for output purposes. ";
313 local_deferredLogger.warning(
"WELL_POTENTIAL_CALCULATION_FAILED", msg);
316 if (alternative_well_rate_init_) {
321 for (
auto& well : well_container_) {
322 if (well->isProducer()) {
323 well->updateWellStateRates(ebosSimulator_, this->wellState(), local_deferredLogger);
329 const auto& comm = ebosSimulator_.vanguard().grid().comm();
330 const auto& summaryState = ebosSimulator_.vanguard().summaryState();
331 std::vector<double> pot(numPhases(), 0.0);
332 const Group& fieldGroup = schedule().getGroup(
"FIELD", reportStepIdx);
333 WellGroupHelpers::updateGuideRates(fieldGroup, schedule(), summaryState, this->phase_usage_, reportStepIdx, simulationTime,
334 this->wellState(), this->groupState(), comm, &this->guideRate_, pot, local_deferredLogger);
336 auto exc_type = ExceptionType::NONE;
338 if (schedule_[reportStepIdx].has_gpmaint()) {
339 regionalAveragePressureCalculator_->template defineState<ElementContext>(ebosSimulator_);
340 const double dt = ebosSimulator_.timeStepSize();
341 WellGroupHelpers::updateGpMaintTargetForGroups(fieldGroup,
342 schedule_, *regionalAveragePressureCalculator_, reportStepIdx, dt, this->wellState(), this->groupState());
346 for (
auto& well : well_container_) {
347 const uint64_t effective_events_mask = ScheduleEvents::WELL_STATUS_CHANGE
348 + ScheduleEvents::INJECTION_TYPE_CHANGED
349 + ScheduleEvents::WELL_SWITCHED_INJECTOR_PRODUCER
350 + ScheduleEvents::NEW_WELL;
352 const auto& events = schedule()[reportStepIdx].wellgroup_events();
353 const bool event = report_step_starts_ && events.hasEvent(well->name(), effective_events_mask);
354 const bool dyn_status_change = this->wellState().well(well->name()).status
355 != this->prevWellState().well(well->name()).status;
357 if (event || dyn_status_change) {
359 well->updateWellStateWithTarget(ebosSimulator_, this->groupState(), this->wellState(), local_deferredLogger);
360 well->calculateExplicitQuantities(ebosSimulator_, this->wellState(), local_deferredLogger);
361 well->solveWellEquation(ebosSimulator_, this->wellState(), this->groupState(), local_deferredLogger);
362 }
catch (
const std::exception& e) {
363 const std::string msg =
"Compute initial well solution for new well " + well->name() +
" failed. Continue with zero initial rates";
364 local_deferredLogger.warning(
"WELL_INITIAL_SOLVE_FAILED", msg);
370 OPM_PARALLEL_CATCH_CLAUSE(exc_type, exc_msg);
372 if (exc_type != ExceptionType::NONE) {
373 const std::string msg =
"Compute initial well solution for new wells failed. Continue with zero initial rates";
374 local_deferredLogger.warning(
"WELL_INITIAL_SOLVE_FAILED", msg);
377 logAndCheckForExceptionsAndThrow(local_deferredLogger,
378 exc_type,
"beginTimeStep() failed: " + exc_msg, terminal_output_, comm);
382 template<
typename TypeTag>
384 BlackoilWellModel<TypeTag>::wellTesting(
const int timeStepIdx,
385 const double simulationTime,
386 DeferredLogger& deferred_logger)
388 const auto& wtest_config = schedule()[timeStepIdx].wtest_config();
389 if (!wtest_config.empty()) {
390 const std::vector<std::string> wellsForTesting = wellTestState()
391 .test_wells(wtest_config, simulationTime);
393 for (
const std::string& well_name : wellsForTesting) {
394 const auto& ws = this->wellState().well(well_name);
395 if (ws.status != Well::Status::OPEN)
398 WellInterfacePtr well = createWellForWellTest(well_name, timeStepIdx, deferred_logger);
400 well->init(&phase_usage_, depth_, gravity_, local_num_cells_, B_avg_);
401 const Well& wellEcl = schedule().getWell(well_name, timeStepIdx);
402 double well_efficiency_factor = wellEcl.getEfficiencyFactor();
403 WellGroupHelpers::accumulateGroupEfficiencyFactor(schedule().getGroup(wellEcl.groupName(), timeStepIdx),
404 schedule(), timeStepIdx, well_efficiency_factor);
406 well->setWellEfficiencyFactor(well_efficiency_factor);
407 well->setVFPProperties(vfp_properties_.get());
408 well->setGuideRate(&guideRate_);
410 well->wellTesting(ebosSimulator_, simulationTime, this->wellState(), this->groupState(), wellTestState(), deferred_logger);
420 template<
typename TypeTag>
422 BlackoilWellModel<TypeTag>::
426 for (
auto&& pinfo : this->local_parallel_well_info_)
437 template<
typename TypeTag>
438 const SimulatorReportSingle&
439 BlackoilWellModel<TypeTag>::
440 lastReport()
const {
return last_report_; }
447 template<
typename TypeTag>
449 BlackoilWellModel<TypeTag>::
450 timeStepSucceeded(
const double& simulationTime,
const double dt)
452 this->closed_this_step_.clear();
455 report_step_starts_ =
false;
456 const int reportStepIdx = ebosSimulator_.episodeIndex();
458 DeferredLogger local_deferredLogger;
459 for (
const auto& well : well_container_) {
460 if (getPropValue<TypeTag, Properties::EnablePolymerMW>() && well->isInjector()) {
461 well->updateWaterThroughput(dt, this->wellState());
465 for (
const auto& well : well_container_) {
466 well->reportWellSwitching(this->wellState().well(well->indexOfWell()), local_deferredLogger);
470 rateConverter_->template defineState<ElementContext>(ebosSimulator_);
474 updateWellPotentials(reportStepIdx,
476 ebosSimulator_.vanguard().summaryConfig(),
477 local_deferredLogger);
478 }
catch ( std::runtime_error& e ) {
479 const std::string msg =
"A zero well potential is returned for output purposes. ";
480 local_deferredLogger.warning(
"WELL_POTENTIAL_CALCULATION_FAILED", msg);
483 updateWellTestState(simulationTime, wellTestState());
486 const Group& fieldGroup = schedule_.getGroup(
"FIELD", reportStepIdx);
487 checkGconsaleLimits(fieldGroup, this->wellState(),
488 ebosSimulator_.episodeIndex(), local_deferredLogger);
490 this->calculateProductivityIndexValues(local_deferredLogger);
492 this->commitWGState();
494 const Opm::Parallel::Communication& comm = grid().comm();
496 if (terminal_output_) {
497 global_deferredLogger.logMessages();
501 this->computeWellTemperature();
505 template<
typename TypeTag>
506 template <
class Context>
508 BlackoilWellModel<TypeTag>::
509 computeTotalRatesForDof(RateVector& rate,
510 const Context& context,
512 unsigned timeIdx)
const
515 int elemIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
517 if (!is_cell_perforated_[elemIdx])
520 for (
const auto& well : well_container_)
521 well->addCellRates(rate, elemIdx);
526 template<
typename TypeTag>
528 BlackoilWellModel<TypeTag>::
529 initializeWellState(
const int timeStepIdx,
530 const SummaryState& summaryState)
532 std::vector<double> cellPressures(this->local_num_cells_, 0.0);
533 ElementContext elemCtx(ebosSimulator_);
535 const auto& gridView = ebosSimulator_.vanguard().gridView();
536 const auto& elemEndIt = gridView.template end<0>();
537 OPM_BEGIN_PARALLEL_TRY_CATCH();
539 for (
auto elemIt = gridView.template begin</*codim=*/0>();
543 if (elemIt->partitionType() != Dune::InteriorEntity) {
547 elemCtx.updatePrimaryStencil(*elemIt);
548 elemCtx.updatePrimaryIntensiveQuantities(0);
550 const auto& fs = elemCtx.intensiveQuantities(0, 0).fluidState();
552 double& perf_pressure = cellPressures[elemCtx.globalSpaceIndex(0, 0)];
553 if (Indices::oilEnabled) {
554 perf_pressure = fs.pressure(FluidSystem::oilPhaseIdx).value();
555 }
else if (Indices::waterEnabled) {
556 perf_pressure = fs.pressure(FluidSystem::waterPhaseIdx).value();
558 perf_pressure = fs.pressure(FluidSystem::gasPhaseIdx).value();
561 OPM_END_PARALLEL_TRY_CATCH(
"BlackoilWellModel::initializeWellState() failed: ", ebosSimulator_.vanguard().grid().comm());
563 this->wellState().init(cellPressures, schedule(), wells_ecl_, local_parallel_well_info_, timeStepIdx,
564 &this->prevWellState(), well_perf_data_,
572 template<
typename TypeTag>
574 BlackoilWellModel<TypeTag>::
575 createWellContainer(
const int time_step)
577 DeferredLogger local_deferredLogger;
579 const int nw = numLocalWells();
581 well_container_.clear();
584 well_container_.reserve(nw);
586 for (
int w = 0; w < nw; ++w) {
587 const Well& well_ecl = wells_ecl_[w];
589 if (well_ecl.getConnections().empty()) {
594 const std::string& well_name = well_ecl.name();
595 const auto well_status = this->schedule()
596 .getWell(well_name, time_step).getStatus();
598 if ((well_ecl.getStatus() == Well::Status::SHUT) ||
599 (well_status == Well::Status::SHUT))
602 if (well_ecl.getStatus() != Well::Status::SHUT) {
603 this->closed_this_step_.insert(well_name);
604 this->wellState().shutWell(w);
611 if (this->wellTestState().well_is_closed(well_name)) {
614 auto& events = this->wellState().well(w).events;
615 if (events.hasEvent(WellState::event_mask)) {
616 if (wellTestState().lastTestTime(well_name) == ebosSimulator_.time()) {
621 events.clearEvent(WellState::event_mask);
623 wellTestState().open_well(well_name);
624 wellTestState().open_completions(well_name);
631 bool wellIsStopped =
false;
632 if (wellTestState().well_is_closed(well_name))
634 if (well_ecl.getAutomaticShutIn()) {
636 this->wellState().shutWell(w);
640 this->wellState().stopWell(w);
641 wellIsStopped =
true;
647 if (!well_ecl.getAllowCrossFlow() && well_ecl.isProducer() && well_ecl.predictionMode()) {
648 const auto& summaryState = ebosSimulator_.vanguard().summaryState();
649 const auto prod_controls = well_ecl.productionControls(summaryState);
651 auto is_zero = [](
const double x)
653 return std::isfinite(x) && !std::isnormal(x);
656 bool zero_rate_control =
false;
657 switch (prod_controls.cmode) {
658 case Well::ProducerCMode::ORAT:
659 zero_rate_control = is_zero(prod_controls.oil_rate);
662 case Well::ProducerCMode::WRAT:
663 zero_rate_control = is_zero(prod_controls.water_rate);
666 case Well::ProducerCMode::GRAT:
667 zero_rate_control = is_zero(prod_controls.gas_rate);
670 case Well::ProducerCMode::LRAT:
671 zero_rate_control = is_zero(prod_controls.liquid_rate);
674 case Well::ProducerCMode::RESV:
675 zero_rate_control = is_zero(prod_controls.resv_rate);
680 zero_rate_control =
false;
684 if (zero_rate_control) {
686 local_deferredLogger.info(
" Well shut due to zero rate control and disallowing crossflow: " + well_ecl.name());
687 this->wellState().shutWell(w);
692 if (well_status == Well::Status::STOP) {
693 this->wellState().stopWell(w);
694 wellIsStopped =
true;
697 well_container_.emplace_back(this->createWellPointer(w, time_step));
700 well_container_.back()->stopWell();
706 const Opm::Parallel::Communication& comm = grid().comm();
708 if (terminal_output_) {
709 global_deferredLogger.logMessages();
712 well_container_generic_.clear();
713 for (
auto& w : well_container_)
714 well_container_generic_.push_back(w.get());
721 template <
typename TypeTag>
722 typename BlackoilWellModel<TypeTag>::WellInterfacePtr
723 BlackoilWellModel<TypeTag>::
724 createWellPointer(
const int wellID,
const int time_step)
const
726 const auto is_multiseg = this->wells_ecl_[wellID].isMultiSegment();
728 if (! (this->param_.use_multisegment_well_ && is_multiseg)) {
729 return this->
template createTypedWellPointer<StandardWell<TypeTag>>(wellID, time_step);
732 return this->
template createTypedWellPointer<MultisegmentWell<TypeTag>>(wellID, time_step);
740 template <
typename TypeTag>
741 template <
typename WellType>
742 std::unique_ptr<WellType>
743 BlackoilWellModel<TypeTag>::
744 createTypedWellPointer(
const int wellID,
const int time_step)
const
747 const auto& perf_data = this->well_perf_data_[wellID];
750 const auto pvtreg = perf_data.empty()
751 ? 0 : pvt_region_idx_[perf_data.front().cell_index];
753 const auto& parallel_well_info = this->local_parallel_well_info_[wellID].get();
754 const auto global_pvtreg = parallel_well_info.broadcastFirstPerforationValue(pvtreg);
756 return std::make_unique<WellType>(this->wells_ecl_[wellID],
760 *this->rateConverter_,
762 this->numComponents(),
772 template<
typename TypeTag>
773 typename BlackoilWellModel<TypeTag>::WellInterfacePtr
774 BlackoilWellModel<TypeTag>::
775 createWellForWellTest(
const std::string& well_name,
776 const int report_step,
777 DeferredLogger& deferred_logger)
const
780 const int nw_wells_ecl = wells_ecl_.size();
781 int index_well_ecl = 0;
782 for (; index_well_ecl < nw_wells_ecl; ++index_well_ecl) {
783 if (well_name == wells_ecl_[index_well_ecl].name()) {
788 if (index_well_ecl == nw_wells_ecl) {
789 OPM_DEFLOG_THROW(std::logic_error,
"Could not find well " << well_name <<
" in wells_ecl ", deferred_logger);
792 return this->createWellPointer(index_well_ecl, report_step);
799 template<
typename TypeTag>
801 BlackoilWellModel<TypeTag>::
802 assemble(
const int iterationIdx,
806 DeferredLogger local_deferredLogger;
807 if (this->glift_debug) {
808 const std::string msg = fmt::format(
809 "assemble() : iteration {}" , iterationIdx);
810 gliftDebug(msg, local_deferredLogger);
812 last_report_ = SimulatorReportSingle();
813 Dune::Timer perfTimer;
816 if ( ! wellsActive() ) {
821 updatePerforationIntensiveQuantities();
823 if (iterationIdx == 0) {
828 OPM_BEGIN_PARALLEL_TRY_CATCH();
830 calculateExplicitQuantities(local_deferredLogger);
831 prepareTimeStep(local_deferredLogger);
833 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
"assemble() failed (It=0): ",
834 terminal_output_, grid().comm());
836 updateWellControls(local_deferredLogger,
true);
838 OPM_BEGIN_PARALLEL_TRY_CATCH();
841 initPrimaryVariablesEvaluation();
843 maybeDoGasLiftOptimize(local_deferredLogger);
844 assembleWellEq(dt, local_deferredLogger);
846 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
"assemble() failed: ",
847 terminal_output_, grid().comm());
848 last_report_.converged =
true;
849 last_report_.assemble_time_well += perfTimer.stop();
852 template<
typename TypeTag>
854 BlackoilWellModel<TypeTag>::
855 maybeDoGasLiftOptimize(DeferredLogger& deferred_logger)
857 const bool do_glift_optimization =
true;
858 if (do_glift_optimization) {
859 GLiftOptWells glift_wells;
860 GLiftProdWells prod_wells;
861 GLiftWellStateMap state_map;
869 GLiftEclWells ecl_well_map;
870 initGliftEclWellMap(ecl_well_map);
871 GasLiftGroupInfo group_info {
873 ebosSimulator_.vanguard().schedule(),
874 ebosSimulator_.vanguard().summaryState(),
875 ebosSimulator_.episodeIndex(),
876 ebosSimulator_.model().newtonMethod().numIterations(),
880 ebosSimulator_.vanguard().grid().comm()
882 group_info.initialize();
883 gasLiftOptimizationStage1(
884 deferred_logger, prod_wells, glift_wells, group_info, state_map);
885 gasLiftOptimizationStage2(
886 deferred_logger, prod_wells, glift_wells, state_map,
887 ebosSimulator_.episodeIndex());
888 if (this->glift_debug) gliftDebugShowALQ(deferred_logger);
892 template<
typename TypeTag>
894 BlackoilWellModel<TypeTag>::
895 gasLiftOptimizationStage1(DeferredLogger& deferred_logger,
896 GLiftProdWells &prod_wells, GLiftOptWells &glift_wells,
897 GasLiftGroupInfo &group_info, GLiftWellStateMap &state_map)
899 auto comm = ebosSimulator_.vanguard().grid().comm();
900 int num_procs = comm.size();
926 for (
int i = 0; i< num_procs; i++) {
927 int num_rates_to_sync = 0;
928 GLiftSyncGroups groups_to_sync;
929 if (comm.rank() == i) {
931 for (
const auto& well : well_container_) {
933 if (group_info.hasWell(well->name())) {
934 well->gasLiftOptimizationStage1(
935 this->wellState(), this->groupState(), ebosSimulator_, deferred_logger,
936 prod_wells, glift_wells, state_map,
937 group_info, groups_to_sync);
940 num_rates_to_sync = groups_to_sync.size();
944 if (i == (num_procs - 1))
946 num_rates_to_sync = comm.sum(num_rates_to_sync);
947 if (num_rates_to_sync > 0) {
948 std::vector<int> group_indexes;
949 group_indexes.reserve(num_rates_to_sync);
950 std::vector<double> group_alq_rates;
951 group_alq_rates.reserve(num_rates_to_sync);
952 std::vector<double> group_oil_rates;
953 group_oil_rates.reserve(num_rates_to_sync);
954 std::vector<double> group_gas_rates;
955 group_gas_rates.reserve(num_rates_to_sync);
956 if (comm.rank() == i) {
957 for (
auto idx : groups_to_sync) {
958 auto [oil_rate, gas_rate, alq] = group_info.getRates(idx);
959 group_indexes.push_back(idx);
960 group_oil_rates.push_back(oil_rate);
961 group_gas_rates.push_back(gas_rate);
962 group_alq_rates.push_back(alq);
973 comm.broadcast(group_indexes.data(), num_rates_to_sync, i);
974 comm.broadcast(group_oil_rates.data(), num_rates_to_sync, i);
975 comm.broadcast(group_gas_rates.data(), num_rates_to_sync, i);
976 comm.broadcast(group_alq_rates.data(), num_rates_to_sync, i);
977 if (comm.rank() != i) {
978 for (
int j=0; j<num_rates_to_sync; j++) {
979 group_info.updateRate(group_indexes[j],
980 group_oil_rates[j], group_gas_rates[j], group_alq_rates[j]);
987 template<
typename TypeTag>
989 BlackoilWellModel<TypeTag>::
990 initGliftEclWellMap(GLiftEclWells &ecl_well_map)
992 for (
const auto& well: well_container_ ) {
993 ecl_well_map.try_emplace(
994 well->name(), &(well->wellEcl()), well->indexOfWell());
999 template<
typename TypeTag>
1001 BlackoilWellModel<TypeTag>::
1002 assembleWellEq(
const double dt, DeferredLogger& deferred_logger)
1004 for (
auto& well : well_container_) {
1005 well->assembleWellEq(ebosSimulator_, dt, this->wellState(), this->groupState(), deferred_logger);
1009 template<
typename TypeTag>
1011 BlackoilWellModel<TypeTag>::
1012 apply( BVector& r)
const
1014 if ( ! localWellsActive() ) {
1018 for (
auto& well : well_container_) {
1025 template<
typename TypeTag>
1027 BlackoilWellModel<TypeTag>::
1028 apply(
const BVector& x, BVector& Ax)
const
1031 if ( ! localWellsActive() ) {
1035 for (
auto& well : well_container_) {
1040 #if HAVE_CUDA || HAVE_OPENCL
1041 template<
typename TypeTag>
1043 BlackoilWellModel<TypeTag>::
1044 getWellContributions(WellContributions& wellContribs)
const
1047 wellContribs.setBlockSize(StandardWell<TypeTag>::Indices::numEq, StandardWell<TypeTag>::numStaticWellEq);
1049 for(
unsigned int i = 0; i < well_container_.size(); i++){
1050 auto& well = well_container_[i];
1051 std::shared_ptr<StandardWell<TypeTag> > derived = std::dynamic_pointer_cast<StandardWell<TypeTag> >(well);
1053 unsigned int numBlocks;
1054 derived->getNumBlocks(numBlocks);
1055 wellContribs.addNumBlocks(numBlocks);
1060 wellContribs.alloc();
1062 for(
unsigned int i = 0; i < well_container_.size(); i++){
1063 auto& well = well_container_[i];
1065 auto derived_std = std::dynamic_pointer_cast<StandardWell<TypeTag> >(well);
1067 derived_std->addWellContribution(wellContribs);
1069 auto derived_ms = std::dynamic_pointer_cast<MultisegmentWell<TypeTag> >(well);
1071 derived_ms->addWellContribution(wellContribs);
1073 OpmLog::warning(
"Warning unknown type of well");
1081 template<
typename TypeTag>
1083 BlackoilWellModel<TypeTag>::
1084 applyScaleAdd(
const Scalar alpha,
const BVector& x, BVector& Ax)
const
1086 if ( ! localWellsActive() ) {
1090 if( scaleAddRes_.size() != Ax.size() ) {
1091 scaleAddRes_.resize( Ax.size() );
1096 apply( x, scaleAddRes_ );
1098 Ax.axpy( alpha, scaleAddRes_ );
1105 template<
typename TypeTag>
1107 BlackoilWellModel<TypeTag>::
1108 recoverWellSolutionAndUpdateWellState(
const BVector& x)
1111 DeferredLogger local_deferredLogger;
1112 OPM_BEGIN_PARALLEL_TRY_CATCH();
1114 if (localWellsActive()) {
1115 for (
auto& well : well_container_) {
1116 well->recoverWellSolutionAndUpdateWellState(x, this->wellState(), local_deferredLogger);
1121 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
1122 "recoverWellSolutionAndUpdateWellState() failed: ",
1123 terminal_output_, ebosSimulator_.vanguard().grid().comm());
1130 template<
typename TypeTag>
1132 BlackoilWellModel<TypeTag>::
1133 initPrimaryVariablesEvaluation()
const
1135 for (
auto& well : well_container_) {
1136 well->initPrimaryVariablesEvaluation();
1145 template<
typename TypeTag>
1147 BlackoilWellModel<TypeTag>::
1148 getWellConvergence(
const std::vector<Scalar>& B_avg,
bool checkGroupConvergence)
const
1151 DeferredLogger local_deferredLogger;
1153 ConvergenceReport local_report;
1154 const int iterationIdx = ebosSimulator_.model().newtonMethod().numIterations();
1155 for (
const auto& well : well_container_) {
1156 if (well->isOperableAndSolvable() ) {
1157 local_report += well->getWellConvergence(this->wellState(), B_avg, local_deferredLogger, iterationIdx > param_.strict_outer_iter_wells_ );
1161 const Opm::Parallel::Communication comm = grid().comm();
1163 if (terminal_output_) {
1164 global_deferredLogger.logMessages();
1167 ConvergenceReport report = gatherConvergenceReport(local_report, comm);
1170 if (terminal_output_) {
1171 for (
const auto& f : report.wellFailures()) {
1172 if (f.severity() == ConvergenceReport::Severity::NotANumber) {
1173 OpmLog::debug(
"NaN residual found with phase " + std::to_string(f.phase()) +
" for well " + f.wellName());
1174 }
else if (f.severity() == ConvergenceReport::Severity::TooLarge) {
1175 OpmLog::debug(
"Too large residual found with phase " + std::to_string(f.phase()) +
" for well " + f.wellName());
1180 if (checkGroupConvergence) {
1181 const int reportStepIdx = ebosSimulator_.episodeIndex();
1182 const Group& fieldGroup = schedule().getGroup(
"FIELD", reportStepIdx);
1183 bool violated = checkGroupConstraints(fieldGroup,
1184 ebosSimulator_.episodeIndex(),
1185 global_deferredLogger);
1186 report.setGroupConverged(!violated);
1195 template<
typename TypeTag>
1201 for (
auto& well : well_container_) {
1210 template<
typename TypeTag>
1218 if( !wellsActive() ) return ;
1220 const int episodeIdx = ebosSimulator_.episodeIndex();
1221 const int iterationIdx = ebosSimulator_.model().newtonMethod().numIterations();
1222 const auto& comm = ebosSimulator_.vanguard().grid().comm();
1223 updateAndCommunicateGroupData(episodeIdx, iterationIdx);
1225 updateNetworkPressures(episodeIdx);
1227 std::set<std::string> switched_wells;
1228 std::set<std::string> switched_groups;
1230 if (checkGroupControls) {
1232 bool changed_individual = updateGroupIndividualControls(deferred_logger, switched_groups,
1233 episodeIdx, iterationIdx);
1235 if (changed_individual)
1236 updateAndCommunicate(episodeIdx, iterationIdx, deferred_logger);
1239 bool changed_higher = updateGroupHigherControls(deferred_logger,
1244 updateAndCommunicate(episodeIdx, iterationIdx, deferred_logger);
1247 bool changed_well_group =
false;
1248 for (
const auto& well : well_container_) {
1250 const bool changed_well = well->updateWellControl(ebosSimulator_, mode, this->wellState(), this->groupState(), deferred_logger);
1252 switched_wells.insert(well->name());
1253 changed_well_group = changed_well || changed_well_group;
1256 changed_well_group = comm.sum(changed_well_group);
1257 if (changed_well_group)
1258 updateAndCommunicate(episodeIdx, iterationIdx, deferred_logger);
1262 bool changed_well_individual =
false;
1263 for (
const auto& well : well_container_) {
1264 if (switched_wells.count(well->name())) {
1267 const auto mode = WellInterface<TypeTag>::IndividualOrGroup::Individual;
1268 const bool changed_well = well->updateWellControl(ebosSimulator_, mode, this->wellState(), this->groupState(), deferred_logger);
1270 changed_well_individual = changed_well || changed_well_individual;
1273 changed_well_individual = comm.sum(changed_well_individual);
1274 if (changed_well_individual)
1275 updateAndCommunicate(episodeIdx, iterationIdx, deferred_logger);
1278 const Group& fieldGroup = schedule().getGroup(
"FIELD", episodeIdx);
1279 updateWsolvent(fieldGroup, episodeIdx, this->nupcolWellState());
1283 template<
typename TypeTag>
1285 BlackoilWellModel<TypeTag>::
1286 updateAndCommunicate(
const int reportStepIdx,
1287 const int iterationIdx,
1288 DeferredLogger& deferred_logger)
1290 updateAndCommunicateGroupData(reportStepIdx, iterationIdx);
1292 for (
const auto& well : well_container_) {
1293 well->updateWellStateWithTarget(ebosSimulator_, this->groupState(), this->wellState(), deferred_logger);
1295 updateAndCommunicateGroupData(reportStepIdx, iterationIdx);
1298 template<
typename TypeTag>
1304 for (
const auto& well : well_container_) {
1305 const auto& wname = well->name();
1306 const auto wasClosed = wellTestState.well_is_closed(wname);
1307 well->checkWellOperability(ebosSimulator_, this->wellState(), local_deferredLogger);
1308 well->updateWellTestState(this->wellState().well(wname), simulationTime,
true, wellTestState, local_deferredLogger);
1310 if (!wasClosed && wellTestState.well_is_closed(wname)) {
1311 this->closed_this_step_.insert(wname);
1315 const Opm::Parallel::Communication comm = grid().comm();
1317 if (terminal_output_) {
1323 template<
typename TypeTag>
1327 std::string& exc_msg,
1328 ExceptionType::ExcEnum& exc_type,
1331 const int np = numPhases();
1332 std::vector<double> potentials;
1333 const auto& well= well_container_[widx];
1335 well->computeWellPotentials(ebosSimulator_, well_state_copy, potentials, deferred_logger);
1338 OPM_PARALLEL_CATCH_CLAUSE(exc_type, exc_msg);
1342 auto& ws = this->wellState().well(well->indexOfWell());
1343 for (
int p = 0; p < np; ++p) {
1344 ws.well_potentials[p] = std::abs(potentials[p]);
1350 template <
typename TypeTag>
1352 BlackoilWellModel<TypeTag>::
1353 calculateProductivityIndexValues(DeferredLogger& deferred_logger)
1355 for (
const auto& wellPtr : this->well_container_) {
1356 this->calculateProductivityIndexValues(wellPtr.get(), deferred_logger);
1364 template <
typename TypeTag>
1366 BlackoilWellModel<TypeTag>::
1367 calculateProductivityIndexValuesShutWells(
const int reportStepIdx,
1368 DeferredLogger& deferred_logger)
1375 for (
const auto& shutWell : this->local_shut_wells_) {
1376 if (this->wells_ecl_[shutWell].getConnections().empty()) {
1381 auto wellPtr = this->
template createTypedWellPointer
1382 <StandardWell<TypeTag>>(shutWell, reportStepIdx);
1384 wellPtr->init(&this->phase_usage_, this->depth_, this->gravity_,
1385 this->local_num_cells_, this->B_avg_);
1387 this->calculateProductivityIndexValues(wellPtr.get(), deferred_logger);
1395 template <
typename TypeTag>
1397 BlackoilWellModel<TypeTag>::
1398 calculateProductivityIndexValues(
const WellInterface<TypeTag>* wellPtr,
1399 DeferredLogger& deferred_logger)
1401 wellPtr->updateProductivityIndex(this->ebosSimulator_,
1402 this->prod_index_calc_[wellPtr->indexOfWell()],
1411 template<
typename TypeTag>
1413 BlackoilWellModel<TypeTag>::
1414 prepareTimeStep(DeferredLogger& deferred_logger)
1416 for (
const auto& well : well_container_) {
1417 auto& events = this->wellState().well(well->indexOfWell()).events;
1418 if (events.hasEvent(WellState::event_mask)) {
1419 well->updateWellStateWithTarget(ebosSimulator_, this->groupState(), this->wellState(), deferred_logger);
1422 events.clearEvent(WellState::event_mask);
1425 if (param_.solve_welleq_initially_) {
1426 well->solveWellEquation(ebosSimulator_, this->wellState(), this->groupState(), deferred_logger);
1429 updatePrimaryVariables(deferred_logger);
1434 template<
typename TypeTag>
1436 BlackoilWellModel<TypeTag>::
1437 setupCartesianToCompressed_(
const int* global_cell,
int number_of_cartesian_cells)
1439 cartesian_to_compressed_.resize(number_of_cartesian_cells, -1);
1441 auto elemIt = ebosSimulator_.gridView().template begin< 0>();
1442 for (
unsigned i = 0; i < local_num_cells_; ++i) {
1444 if (elemIt->partitionType() == Dune::InteriorEntity)
1446 assert(ebosSimulator_.gridView().indexSet().index(*elemIt) ==
static_cast<int>(i));
1447 cartesian_to_compressed_[global_cell[i]] = i;
1453 for (
unsigned i = 0; i < local_num_cells_; ++i) {
1454 cartesian_to_compressed_[i] = i;
1460 template<
typename TypeTag>
1462 BlackoilWellModel<TypeTag>::
1463 updateAverageFormationFactor()
1465 std::vector< Scalar > B_avg(numComponents(), Scalar() );
1466 const auto& grid = ebosSimulator_.vanguard().grid();
1467 const auto& gridView = grid.leafGridView();
1468 ElementContext elemCtx(ebosSimulator_);
1469 const auto& elemEndIt = gridView.template end<0, Dune::Interior_Partition>();
1470 OPM_BEGIN_PARALLEL_TRY_CATCH();
1472 for (
auto elemIt = gridView.template begin</*codim=*/0, Dune::Interior_Partition>();
1473 elemIt != elemEndIt; ++elemIt)
1475 elemCtx.updatePrimaryStencil(*elemIt);
1476 elemCtx.updatePrimaryIntensiveQuantities(0);
1478 const auto& intQuants = elemCtx.intensiveQuantities(0, 0);
1479 const auto& fs = intQuants.fluidState();
1481 for (
unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx)
1483 if (!FluidSystem::phaseIsActive(phaseIdx)) {
1487 const unsigned compIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
1488 auto& B = B_avg[ compIdx ];
1490 B += 1 / fs.invB(phaseIdx).value();
1492 if constexpr (has_solvent_) {
1493 auto& B = B_avg[solventSaturationIdx];
1494 B += 1 / intQuants.solventInverseFormationVolumeFactor().value();
1497 OPM_END_PARALLEL_TRY_CATCH(
"BlackoilWellModel::updateAverageFormationFactor() failed: ", grid.comm())
1500 grid.comm().sum(B_avg.data(), B_avg.size());
1501 for(auto& bval: B_avg)
1503 bval/=global_num_cells_;
1512 template<
typename TypeTag>
1514 BlackoilWellModel<TypeTag>::
1515 updatePrimaryVariables(DeferredLogger& deferred_logger)
1517 for (
const auto& well : well_container_) {
1518 well->updatePrimaryVariables(this->wellState(), deferred_logger);
1522 template<
typename TypeTag>
1524 BlackoilWellModel<TypeTag>::extractLegacyCellPvtRegionIndex_()
1526 const auto& grid = ebosSimulator_.vanguard().grid();
1527 const auto& eclProblem = ebosSimulator_.problem();
1528 const unsigned numCells = grid.size(0);
1530 pvt_region_idx_.resize(numCells);
1531 for (
unsigned cellIdx = 0; cellIdx < numCells; ++cellIdx) {
1532 pvt_region_idx_[cellIdx] =
1533 eclProblem.pvtRegionIndex(cellIdx);
1538 template<
typename TypeTag>
1540 BlackoilWellModel<TypeTag>::numComponents()
const
1542 if (wellsActive() && numPhases() < 3) {
1545 int numComp = FluidSystem::numComponents;
1546 if constexpr (has_solvent_) {
1553 template<
typename TypeTag>
1555 BlackoilWellModel<TypeTag>::extractLegacyDepth_()
1557 const auto& grid = ebosSimulator_.vanguard().grid();
1558 const unsigned numCells = grid.size(0);
1560 depth_.resize(numCells);
1561 for (
unsigned cellIdx = 0; cellIdx < numCells; ++cellIdx) {
1562 depth_[cellIdx] = UgGridHelpers::cellCenterDepth( grid, cellIdx );
1566 template<
typename TypeTag>
1568 BlackoilWellModel<TypeTag>::
1569 updatePerforationIntensiveQuantities() {
1570 ElementContext elemCtx(ebosSimulator_);
1571 const auto& gridView = ebosSimulator_.gridView();
1572 const auto& elemEndIt = gridView.template end<0, Dune::Interior_Partition>();
1573 OPM_BEGIN_PARALLEL_TRY_CATCH();
1574 for (
auto elemIt = gridView.template begin</*codim=*/0, Dune::Interior_Partition>();
1575 elemIt != elemEndIt;
1579 elemCtx.updatePrimaryStencil(*elemIt);
1580 int elemIdx = elemCtx.globalSpaceIndex(0, 0);
1582 if (!is_cell_perforated_[elemIdx]) {
1585 elemCtx.updatePrimaryIntensiveQuantities(0);
1587 OPM_END_PARALLEL_TRY_CATCH(
"BlackoilWellModel::updatePerforationIntensiveQuantities() failed: ", ebosSimulator_.vanguard().grid().comm());
1591 template<
typename TypeTag>
1592 typename BlackoilWellModel<TypeTag>::WellInterfacePtr
1593 BlackoilWellModel<TypeTag>::
1594 getWell(
const std::string& well_name)
const
1597 auto well = std::find_if(well_container_.begin(),
1598 well_container_.end(),
1599 [&well_name](
const WellInterfacePtr& elem)->bool {
1600 return elem->name() == well_name;
1603 assert(well != well_container_.end());
1608 template<
typename TypeTag>
1610 BlackoilWellModel<TypeTag>::
1611 hasWell(
const std::string& well_name)
const
1613 return std::any_of(well_container_.begin(), well_container_.end(),
1614 [&well_name](
const WellInterfacePtr& elem) ->
bool
1616 return elem->name() == well_name;
1623 template <
typename TypeTag>
1625 BlackoilWellModel<TypeTag>::
1626 reportStepIndex()
const
1628 return std::max(this->ebosSimulator_.episodeIndex(), 0);
1635 template<
typename TypeTag>
1637 BlackoilWellModel<TypeTag>::
1638 calcRates(
const int fipnum,
1640 std::vector<double>& resv_coeff)
1642 rateConverter_->calcCoeff(fipnum, pvtreg, resv_coeff);
1645 template<
typename TypeTag>
1647 BlackoilWellModel<TypeTag>::
1648 calcInjRates(
const int fipnum,
1650 std::vector<double>& resv_coeff)
1652 rateConverter_->calcInjCoeff(fipnum, pvtreg, resv_coeff);
1656 template <
typename TypeTag>
1658 BlackoilWellModel<TypeTag>::
1659 computeWellTemperature()
1664 int np = numPhases();
1665 double cellInternalEnergy;
1668 double perfPhaseRate;
1669 const int nw = numLocalWells();
1670 for (
auto wellID = 0*nw; wellID < nw; ++wellID) {
1671 const Well& well = wells_ecl_[wellID];
1672 if (well.isInjector())
1676 for (
int i = 0; i < wellID; ++i) {
1677 connpos += well_perf_data_[i].size();
1680 double weighted_temperature = 0.0;
1681 double total_weight = 0.0;
1683 auto& well_info = local_parallel_well_info_[wellID].get();
1684 const int num_perf_this_well = well_info.communication().sum(well_perf_data_[wellID].size());
1685 auto& ws = this->wellState().well(wellID);
1686 auto& perf_data = ws.perf_data;
1687 auto& perf_phase_rate = perf_data.phase_rates;
1689 for (
int perf = 0; perf < num_perf_this_well; ++perf) {
1690 const int cell_idx = well_perf_data_[wellID][perf].cell_index;
1691 const auto& intQuants = *(ebosSimulator_.model().cachedIntensiveQuantities(cell_idx, 0));
1692 const auto& fs = intQuants.fluidState();
1694 double cellTemperatures = fs.temperature(0).value();
1695 double weight_factor = 0.0;
1696 for (
int phaseIdx = 0; phaseIdx < np; ++phaseIdx) {
1697 cellInternalEnergy = fs.enthalpy(phaseIdx).value() - fs.pressure(phaseIdx).value() / fs.density(phaseIdx).value();
1698 cellBinv = fs.invB(phaseIdx).value();
1699 cellDensity = fs.density(phaseIdx).value();
1700 perfPhaseRate = perf_phase_rate[ perf*np + phaseIdx ];
1701 weight_factor += cellDensity * perfPhaseRate/cellBinv * cellInternalEnergy/cellTemperatures;
1703 total_weight += weight_factor;
1704 weighted_temperature += weight_factor * cellTemperatures;
1706 weighted_temperature = well_info.communication().sum(weighted_temperature);
1707 total_weight = well_info.communication().sum(total_weight);
1708 this->wellState().well(wellID).temperature = weighted_temperature/total_weight;
1714 template <
typename TypeTag>
1716 BlackoilWellModel<TypeTag>::
1717 assignWellTracerRates(data::Wells& wsrpt)
const
1719 const auto & wellTracerRates = ebosSimulator_.problem().tracerModel().getWellTracerRates();
1721 if (wellTracerRates.empty())
1724 for (
const auto& wTR : wellTracerRates) {
1725 std::string wellName = wTR.first.first;
1726 auto xwPos = wsrpt.find(wellName);
1727 if (xwPos == wsrpt.end()) {
1730 std::string tracerName = wTR.first.second;
1731 double rate = wTR.second;
1732 xwPos->second.rates.set(data::Rates::opt::tracer, rate, tracerName);
Class for handling the blackoil well model.
Definition: BlackoilWellModel.hpp:94
void calculateExplicitQuantities(DeferredLogger &deferred_logger) const
Calculating the explict quantities used in the well calculation.
Definition: BlackoilWellModel_impl.hpp:1198
Definition: DeferredLogger.hpp:57
void logMessages()
Log all messages to the OpmLog backends, and clear the message container.
Definition: DeferredLogger.cpp:85
Definition: WellInterface.hpp:71
The state of a set of wells, tailored for use by the fully implicit blackoil simulator.
Definition: WellState.hpp:56
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: BlackoilPhases.hpp:26
Opm::DeferredLogger gatherDeferredLogger(const Opm::DeferredLogger &local_deferredlogger, Opm::Parallel::Communication)
Create a global log combining local logs.
Definition: gatherDeferredLogger.cpp:168
PhaseUsage phaseUsageFromDeck(const EclipseState &eclipseState)
Looks at presence of WATER, OIL and GAS keywords in state object to determine active phases.
Definition: phaseUsageFromDeck.cpp:141