23#ifndef OPM_WELLINTERFACE_HEADER_INCLUDED
25#define OPM_WELLINTERFACE_IMPL_HEADER_INCLUDED
29#include <opm/common/Exceptions.hpp>
31#include <opm/input/eclipse/Schedule/ScheduleTypes.hpp>
32#include <opm/input/eclipse/Schedule/Well/WDFAC.hpp>
41#include <dune/common/version.hh>
47#include <fmt/format.h>
53 template<
typename TypeTag>
60 const int pvtRegionIdx,
61 const int num_components,
63 const int index_of_well,
79 if (well.isInjector()) {
80 auto injectorType = this->
well_ecl_.injectorType();
81 if (injectorType == InjectorType::GAS) {
89 template<
typename TypeTag>
93 const std::vector<Scalar>& ,
96 const std::vector<Scalar>& B_avg,
97 const bool changed_to_open_this_step)
99 this->phase_usage_ = phase_usage_arg;
100 this->gravity_ = gravity_arg;
102 this->changed_to_open_this_step_ = changed_to_open_this_step;
108 template<
typename TypeTag>
113 if constexpr (has_polymer) {
114 return this->wpolymer_();
124 template<
typename TypeTag>
129 if constexpr (has_foam) {
130 return this->wfoam_();
138 template<
typename TypeTag>
143 if constexpr (has_brine) {
144 return this->wsalt_();
150 template<
typename TypeTag>
155 if constexpr (has_micp) {
156 return this->wmicrobes_();
162 template<
typename TypeTag>
167 if constexpr (has_micp) {
168 return this->woxygen_();
180 template<
typename TypeTag>
185 if constexpr (has_micp) {
186 return this->wurea_();
192 template<
typename TypeTag>
201 if (stoppedOrZeroRateTarget(simulator, well_state, deferred_logger)) {
205 const auto& summaryState = simulator.vanguard().summaryState();
206 const auto& schedule = simulator.vanguard().schedule();
207 const auto& well = this->well_ecl_;
208 auto& ws = well_state.
well(this->index_of_well_);
210 if (well.isInjector()) {
211 from = WellInjectorCMode2String(ws.injection_cmode);
213 from = WellProducerCMode2String(ws.production_cmode);
215 bool oscillating = std::count(this->well_control_log_.begin(), this->well_control_log_.end(), from) >= param_.max_number_of_well_switches_;
219 bool output = std::count(this->well_control_log_.begin(), this->well_control_log_.end(), from) == param_.max_number_of_well_switches_;
221 std::ostringstream ss;
222 ss <<
" The control mode for well " << this->name()
223 <<
" is oscillating\n"
224 <<
" We don't allow for more than "
225 << param_.max_number_of_well_switches_
226 <<
" switches. The control is kept at " << from;
227 deferred_logger.
info(ss.str());
229 this->well_control_log_.push_back(from);
233 bool changed =
false;
234 if (iog == IndividualOrGroup::Individual) {
235 changed = this->checkIndividualConstraints(ws, summaryState, deferred_logger);
236 }
else if (iog == IndividualOrGroup::Group) {
237 changed = this->checkGroupConstraints(well_state, group_state, schedule, summaryState, deferred_logger);
239 assert(iog == IndividualOrGroup::Both);
240 changed = this->checkConstraints(well_state, group_state, schedule, summaryState, deferred_logger);
246 if (well.isInjector()) {
247 to = WellInjectorCMode2String(ws.injection_cmode);
249 to = WellProducerCMode2String(ws.production_cmode);
251 std::ostringstream ss;
252 ss <<
" Switching control mode for well " << this->name()
256 ss <<
" on rank " << cc.rank();
258 deferred_logger.
debug(ss.str());
260 this->well_control_log_.push_back(from);
261 updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger);
262 updatePrimaryVariables(simulator, well_state, deferred_logger);
268 template<
typename TypeTag>
274 const Well::InjectionControls& inj_controls,
275 const Well::ProductionControls& prod_controls,
278 const bool fixed_control,
279 const bool fixed_status)
281 const auto& summary_state = simulator.vanguard().summaryState();
282 auto& ws = well_state.
well(this->index_of_well_);
284 if (this->isInjector()) {
285 from = WellInjectorCMode2String(ws.injection_cmode);
287 from = WellProducerCMode2String(ws.production_cmode);
289 const bool oscillating = std::count(this->well_control_log_.begin(), this->well_control_log_.end(), from) >= param_.max_number_of_well_switches_;
291 if (oscillating || this->wellUnderZeroRateTarget(simulator, well_state, deferred_logger) || !(this->well_ecl_.getStatus() == WellStatus::OPEN)) {
295 const Scalar sgn = this->isInjector() ? 1.0 : -1.0;
296 if (!this->wellIsStopped()){
297 if (wqTotal*sgn <= 0.0 && !fixed_status){
301 bool changed =
false;
302 if (!fixed_control) {
311 changed = this->checkIndividualConstraints(ws, summary_state, deferred_logger, inj_controls, prod_controls);
317 const bool thp_controlled = this->isInjector() ? ws.injection_cmode == Well::InjectorCMode::THP :
318 ws.production_cmode == Well::ProducerCMode::THP;
319 if (!thp_controlled){
321 updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger);
323 ws.thp = this->getTHPConstraint(summary_state);
325 updatePrimaryVariables(simulator, well_state, deferred_logger);
330 }
else if (!fixed_status){
332 const Scalar bhp = well_state.
well(this->index_of_well_).bhp;
333 Scalar prod_limit = prod_controls.bhp_limit;
334 Scalar inj_limit = inj_controls.bhp_limit;
335 const bool has_thp = this->wellHasTHPConstraints(summary_state);
337 std::vector<Scalar> rates(this->num_components_);
338 if (this->isInjector()){
340 calculateBhpFromThp(well_state, rates,
343 this->getRefDensity(),
345 inj_limit = std::min(bhp_thp,
static_cast<Scalar>(inj_controls.bhp_limit));
350 calculateMinimumBhpFromThp(well_state,
353 this->getRefDensity());
354 prod_limit = std::max(bhp_min,
static_cast<Scalar>(prod_controls.bhp_limit));
357 const Scalar bhp_diff = (this->isInjector())? inj_limit - bhp: bhp - prod_limit;
360 well_state.
well(this->index_of_well_).bhp = (this->isInjector())? inj_limit : prod_limit;
362 well_state.
well(this->index_of_well_).thp = this->getTHPConstraint(summary_state);
373 template<
typename TypeTag>
377 const double simulation_time,
380 WellTestState& well_test_state,
383 deferred_logger.
info(
" well " + this->name() +
" is being tested");
386 auto& ws = well_state_copy.
well(this->indexOfWell());
388 updateWellStateWithTarget(simulator, group_state, well_state_copy, deferred_logger);
389 calculateExplicitQuantities(simulator, well_state_copy, deferred_logger);
390 updatePrimaryVariables(simulator, well_state_copy, deferred_logger);
391 initPrimaryVariablesEvaluation();
393 if (this->isProducer()) {
394 const auto& schedule = simulator.vanguard().schedule();
395 const auto report_step = simulator.episodeIndex();
396 const auto& glo = schedule.glo(report_step);
398 gliftBeginTimeStepWellTestUpdateALQ(simulator, well_state_copy, deferred_logger);
402 WellTestState welltest_state_temp;
404 bool testWell =
true;
409 const std::size_t original_number_closed_completions = welltest_state_temp.num_closed_completions();
410 bool converged = solveWellForTesting(simulator, well_state_copy, group_state, deferred_logger);
412 const auto msg = fmt::format(
"WTEST: Well {} is not solvable (physical)", this->name());
413 deferred_logger.
debug(msg);
418 updateWellOperability(simulator, well_state_copy, deferred_logger);
419 if ( !this->isOperableAndSolvable() ) {
420 const auto msg = fmt::format(
"WTEST: Well {} is not operable (physical)", this->name());
421 deferred_logger.
debug(msg);
424 std::vector<Scalar> potentials;
426 computeWellPotentials(simulator, well_state_copy, potentials, deferred_logger);
427 }
catch (
const std::exception& e) {
428 const std::string msg = fmt::format(
"well {}: computeWellPotentials() "
429 "failed during testing for re-opening: ",
430 this->name(), e.what());
431 deferred_logger.
info(msg);
434 const int np = well_state_copy.
numPhases();
435 for (
int p = 0; p < np; ++p) {
436 ws.well_potentials[p] = std::max(
Scalar{0.0}, potentials[p]);
438 const bool under_zero_target = this->wellUnderZeroGroupRateTarget(simulator, well_state_copy, deferred_logger);
439 this->updateWellTestState(well_state_copy.
well(this->indexOfWell()),
445 this->closeCompletions(welltest_state_temp);
451 if ( welltest_state_temp.num_closed_wells() > 0 ||
452 (original_number_closed_completions == welltest_state_temp.num_closed_completions()) ) {
458 if (!welltest_state_temp.well_is_closed(this->name())) {
459 well_test_state.open_well(this->name());
461 std::string msg = std::string(
"well ") + this->name() + std::string(
" is re-opened");
462 deferred_logger.
info(msg);
465 for (
auto& completion : this->well_ecl_.getCompletions()) {
466 if (!welltest_state_temp.completion_is_closed(this->name(), completion.first))
467 well_test_state.open_completion(this->name(), completion.first);
471 well_state = well_state_copy;
478 template<
typename TypeTag>
487 const auto& summary_state = simulator.vanguard().summaryState();
488 const auto inj_controls = this->well_ecl_.isInjector() ? this->well_ecl_.injectionControls(summary_state) : Well::InjectionControls(0);
489 const auto prod_controls = this->well_ecl_.isProducer() ? this->well_ecl_.productionControls(summary_state) : Well::ProductionControls(0);
490 bool converged =
false;
493 if (!this->param_.local_well_solver_control_switching_){
494 converged = this->iterateWellEqWithControl(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
496 if (this->param_.use_implicit_ipr_ && this->well_ecl_.isProducer() && this->wellHasTHPConstraints(summary_state) && (this->well_ecl_.getStatus() == WellStatus::OPEN)) {
497 converged = solveWellWithTHPConstraint(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
499 converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
503 }
catch (NumericalProblem& e ) {
504 const std::string msg =
"Inner well iterations failed for well " + this->name() +
" Treat the well as unconverged. ";
505 deferred_logger.
warning(
"INNER_ITERATION_FAILED", msg);
511 template<
typename TypeTag>
516 const Well::InjectionControls& inj_controls,
517 const Well::ProductionControls& prod_controls,
522 const auto& summary_state = simulator.vanguard().summaryState();
523 bool is_operable =
true;
524 bool converged =
true;
525 auto& ws = well_state.
well(this->index_of_well_);
527 if (this->wellIsStopped()) {
529 auto bhp_target = estimateOperableBhp(simulator, dt, well_state, summary_state, deferred_logger);
530 if (!bhp_target.has_value()) {
532 const auto msg = fmt::format(
"estimateOperableBhp: Did not find operable BHP for well {}", this->name());
533 deferred_logger.
debug(msg);
536 solveWellWithZeroRate(simulator, dt, well_state, deferred_logger);
540 ws.thp = this->getTHPConstraint(summary_state);
541 const Scalar bhp = std::max(bhp_target.value(),
542 static_cast<Scalar>(prod_controls.bhp_limit));
543 solveWellWithBhp(simulator, dt, bhp, well_state, deferred_logger);
548 converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
551 const bool isThp = ws.production_cmode == Well::ProducerCMode::THP;
553 if (converged && !stoppedOrZeroRateTarget(simulator, well_state, deferred_logger) && isThp) {
554 auto rates = well_state.
well(this->index_of_well_).surface_rates;
555 this->adaptRatesForVFP(rates);
556 this->updateIPRImplicit(simulator, well_state, deferred_logger);
560 this->operability_status_.use_vfpexplicit =
true;
563 const Scalar reltol = 1e-3;
564 const Scalar cur_bhp = ws.bhp;
565 if (bhp_stable.has_value() && cur_bhp - bhp_stable.value() > cur_bhp*reltol){
566 const auto msg = fmt::format(
"Well {} converged to an unstable solution, re-solving", this->name());
567 deferred_logger.
debug(msg);
568 solveWellWithBhp(simulator, dt, bhp_stable.value(), well_state, deferred_logger);
570 ws.thp = this->getTHPConstraint(summary_state);
571 converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
578 this->operability_status_.use_vfpexplicit =
true;
580 auto bhp_target = estimateOperableBhp(simulator, dt, well_state, summary_state, deferred_logger);
581 if (!bhp_target.has_value()) {
585 converged = solveWellWithZeroRate(simulator, dt, well_state, deferred_logger);
589 const Scalar bhp = std::max(bhp_target.value(),
590 static_cast<Scalar>(prod_controls.bhp_limit));
591 solveWellWithBhp(simulator, dt, bhp, well_state, deferred_logger);
592 ws.thp = this->getTHPConstraint(summary_state);
593 converged = this->iterateWellEqWithSwitching(simulator, dt,
602 is_operable = is_operable && !this->wellIsStopped();
603 this->operability_status_.can_obtain_bhp_with_thp_limit = is_operable;
604 this->operability_status_.obey_thp_limit_under_bhp_limit = is_operable;
608 template<
typename TypeTag>
609 std::optional<typename WellInterface<TypeTag>::Scalar>
614 const SummaryState& summary_state,
621 const bool converged = solveWellWithBhp(simulator, dt, bhp_min, well_state, deferred_logger);
622 if (!converged || this->wellIsStopped()) {
625 this->updateIPRImplicit(simulator, well_state, deferred_logger);
626 auto rates = well_state.
well(this->index_of_well_).surface_rates;
627 this->adaptRatesForVFP(rates);
631 template<
typename TypeTag>
642 auto inj_controls = Well::InjectionControls(0);
643 auto prod_controls = Well::ProductionControls(0);
644 auto& ws = well_state.
well(this->index_of_well_);
645 auto cmode_inj = ws.injection_cmode;
646 auto cmode_prod = ws.production_cmode;
647 if (this->isInjector()) {
648 inj_controls.addControl(Well::InjectorCMode::BHP);
649 inj_controls.bhp_limit = bhp;
650 inj_controls.cmode = Well::InjectorCMode::BHP;
651 ws.injection_cmode = Well::InjectorCMode::BHP;
653 prod_controls.addControl(Well::ProducerCMode::BHP);
654 prod_controls.bhp_limit = bhp;
655 prod_controls.cmode = Well::ProducerCMode::BHP;
656 ws.production_cmode = Well::ProducerCMode::BHP;
661 const bool converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger,
true);
662 ws.injection_cmode = cmode_inj;
663 ws.production_cmode = cmode_prod;
667 template<
typename TypeTag>
676 const auto well_status_orig = this->wellStatus_;
680 auto inj_controls = Well::InjectionControls(0);
681 auto prod_controls = Well::ProductionControls(0);
682 const bool converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger,
true,
true);
683 this->wellStatus_ = well_status_orig;
687 template<
typename TypeTag>
697 const double dt = simulator.timeStepSize();
698 const auto& summary_state = simulator.vanguard().summaryState();
699 const bool has_thp_limit = this->wellHasTHPConstraints(summary_state);
702 well_state.
well(this->indexOfWell()).production_cmode = Well::ProducerCMode::THP;
703 converged = gliftBeginTimeStepWellTestIterateWellEquations(
704 simulator, dt, well_state, group_state, deferred_logger);
707 well_state.
well(this->indexOfWell()).production_cmode = Well::ProducerCMode::BHP;
708 converged = iterateWellEquations(simulator, dt, well_state, group_state, deferred_logger);
711 deferred_logger.
debug(
"WellTest: Well equation for well " + this->name() +
" converged");
714 const int max_iter = param_.max_welleq_iter_;
715 deferred_logger.
debug(
"WellTest: Well equation for well " + this->name() +
" failed converging in "
717 well_state = well_state0;
722 template<
typename TypeTag>
730 if (!this->isOperableAndSolvable() && !this->wellIsStopped())
735 const double dt = simulator.timeStepSize();
736 bool converged = iterateWellEquations(simulator, dt, well_state, group_state, deferred_logger);
746 auto& ws = well_state.
well(this->indexOfWell());
747 bool thp_control =
false;
748 if (this->well_ecl_.isInjector()) {
749 thp_control = ws.injection_cmode == Well::InjectorCMode::THP;
751 ws.injection_cmode = Well::InjectorCMode::BHP;
752 this->well_control_log_.push_back(WellInjectorCMode2String(Well::InjectorCMode::THP));
755 thp_control = ws.production_cmode == Well::ProducerCMode::THP;
757 ws.production_cmode = Well::ProducerCMode::BHP;
758 this->well_control_log_.push_back(WellProducerCMode2String(Well::ProducerCMode::THP));
762 const std::string msg = std::string(
"The newly opened well ") + this->name()
763 + std::string(
" with THP control did not converge during inner iterations, we try again with bhp control");
764 deferred_logger.
debug(msg);
765 converged = this->iterateWellEquations(simulator, dt, well_state, group_state, deferred_logger);
770 const int max_iter = param_.max_welleq_iter_;
771 deferred_logger.
debug(
"Compute initial well solution for well " + this->name() +
". Failed to converge in "
773 well_state = well_state0;
779 template <
typename TypeTag>
788 prepareWellBeforeAssembling(simulator, dt, well_state, group_state, deferred_logger);
789 assembleWellEqWithoutIteration(simulator, dt, well_state, group_state, deferred_logger);
794 template <
typename TypeTag>
803 const auto& summary_state = simulator.vanguard().summaryState();
804 const auto inj_controls = this->well_ecl_.isInjector() ? this->well_ecl_.injectionControls(summary_state) : Well::InjectionControls(0);
805 const auto prod_controls = this->well_ecl_.isProducer() ? this->well_ecl_.productionControls(summary_state) : Well::ProductionControls(0);
808 assembleWellEqWithoutIteration(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
813 template<
typename TypeTag>
822 const bool old_well_operable = this->operability_status_.isOperableAndSolvable();
824 if (param_.check_well_operability_iter_)
825 checkWellOperability(simulator, well_state, deferred_logger);
828 const int iteration_idx = simulator.model().newtonMethod().numIterations();
829 if (iteration_idx < param_.max_niter_inner_well_iter_ || this->well_ecl_.isMultiSegment()) {
830 this->operability_status_.solvable =
true;
831 bool converged = this->iterateWellEquations(simulator, dt, well_state, group_state, deferred_logger);
835 if (param_.shut_unsolvable_wells_)
836 this->operability_status_.solvable =
false;
839 if (this->operability_status_.has_negative_potentials) {
840 auto well_state_copy = well_state;
841 std::vector<Scalar> potentials;
843 computeWellPotentials(simulator, well_state_copy, potentials, deferred_logger);
844 }
catch (
const std::exception& e) {
845 const std::string msg = fmt::format(
"well {}: computeWellPotentials() failed "
846 "during attempt to recompute potentials for well: ",
847 this->name(), e.what());
848 deferred_logger.
info(msg);
849 this->operability_status_.has_negative_potentials =
true;
851 auto& ws = well_state.
well(this->indexOfWell());
853 for (
int p = 0; p < np; ++p) {
854 ws.well_potentials[p] = std::max(
Scalar{0.0}, potentials[p]);
857 this->changed_to_open_this_step_ =
false;
858 const bool well_operable = this->operability_status_.isOperableAndSolvable();
860 if (!well_operable && old_well_operable) {
861 deferred_logger.
info(
" well " + this->name() +
" gets STOPPED during iteration ");
863 changed_to_stopped_this_step_ =
true;
864 }
else if (well_operable && !old_well_operable) {
865 deferred_logger.
info(
" well " + this->name() +
" gets REVIVED during iteration ");
867 changed_to_stopped_this_step_ =
false;
868 this->changed_to_open_this_step_ =
true;
872 template<
typename TypeTag>
876 if(!this->isOperableAndSolvable() && !this->wellIsStopped())
879 for (
int perfIdx = 0; perfIdx < this->number_of_perforations_; ++perfIdx) {
880 if (this->cells()[perfIdx] == cellIdx) {
881 for (
int i = 0; i < RateVector::dimension; ++i) {
882 rates[i] += connectionRates_[perfIdx][i];
888 template<
typename TypeTag>
892 for (
int perfIdx = 0; perfIdx < this->number_of_perforations_; ++perfIdx) {
893 if (this->cells()[perfIdx] == cellIdx) {
894 const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
895 return connectionRates_[perfIdx][activeCompIdx].value();
899 OPM_THROW(std::invalid_argument,
"The well with name " + this->name()
907 template<
typename TypeTag>
915 if (!param_.check_well_operability_) {
919 if (this->wellIsStopped() && !changed_to_stopped_this_step_) {
923 updateWellOperability(simulator, well_state, deferred_logger);
924 if (!this->operability_status_.isOperableAndSolvable()) {
925 this->operability_status_.use_vfpexplicit =
true;
926 deferred_logger.
debug(
"EXPLICIT_LOOKUP_VFP",
927 "well not operable, trying with explicit vfp lookup: " + this->name());
928 updateWellOperability(simulator, well_state, deferred_logger);
932 template<
typename TypeTag>
941 const auto& well_name = this->name();
942 assert(this->wellHasTHPConstraints(simulator.vanguard().summaryState()));
943 const auto& schedule = simulator.vanguard().schedule();
944 auto report_step_idx = simulator.episodeIndex();
945 const auto& glo = schedule.glo(report_step_idx);
946 if(glo.active() && glo.has_well(well_name)) {
947 const auto increment = glo.gaslift_increment();
948 auto alq = well_state.
getALQ(well_name);
951 well_state.
setALQ(well_name, alq);
953 iterateWellEquations(simulator, dt, well_state, group_state, deferred_logger)))
962 return iterateWellEquations(simulator, dt, well_state, group_state, deferred_logger);
966 template<
typename TypeTag>
973 const auto& summary_state = simulator.vanguard().summaryState();
974 const auto& well_name = this->name();
975 if (!this->wellHasTHPConstraints(summary_state)) {
976 const std::string msg = fmt::format(
"GLIFT WTEST: Well {} does not have THP constraints", well_name);
977 deferred_logger.
info(msg);
980 const auto& schedule = simulator.vanguard().schedule();
981 const auto report_step_idx = simulator.episodeIndex();
982 const auto& glo = schedule.glo(report_step_idx);
983 if (!glo.has_well(well_name)) {
984 const std::string msg = fmt::format(
985 "GLIFT WTEST: Well {} : Gas Lift not activated: "
986 "WLIFTOPT is probably missing. Skipping.", well_name);
987 deferred_logger.
info(msg);
990 const auto& gl_well = glo.well(well_name);
991 auto& max_alq_optional = gl_well.max_rate();
993 if (max_alq_optional) {
994 max_alq = *max_alq_optional;
997 const auto& well_ecl = this->wellEcl();
998 const auto& controls = well_ecl.productionControls(summary_state);
999 const auto& table = this->vfpProperties()->getProd()->getTable(controls.vfp_table_number);
1000 const auto& alq_values = table.getALQAxis();
1001 max_alq = alq_values.back();
1003 well_state.
setALQ(well_name, max_alq);
1004 const std::string msg = fmt::format(
1005 "GLIFT WTEST: Well {} : Setting ALQ to max value: {}",
1006 well_name, max_alq);
1007 deferred_logger.
info(msg);
1010 template<
typename TypeTag>
1017 if (this->param_.local_well_solver_control_switching_) {
1018 const bool success = updateWellOperabilityFromWellEq(simulator, well_state, deferred_logger);
1022 deferred_logger.
debug(
"Operability check using well equations did not converge for well "
1023 + this->name() +
", reverting to classical approach." );
1026 this->operability_status_.resetOperability();
1028 bool thp_controlled = this->isInjector() ? well_state.
well(this->index_of_well_).injection_cmode == Well::InjectorCMode::THP:
1029 well_state.
well(this->index_of_well_).production_cmode == Well::ProducerCMode::THP;
1030 bool bhp_controlled = this->isInjector() ? well_state.
well(this->index_of_well_).injection_cmode == Well::InjectorCMode::BHP:
1031 well_state.
well(this->index_of_well_).production_cmode == Well::ProducerCMode::BHP;
1035 bool check_thp = thp_controlled || this->operability_status_.thp_limit_violated_but_not_switched;
1036 if (check_thp || bhp_controlled) {
1037 updateIPR(simulator, deferred_logger);
1038 checkOperabilityUnderBHPLimit(well_state, simulator, deferred_logger);
1042 checkOperabilityUnderTHPLimit(simulator, well_state, deferred_logger);
1046 template<
typename TypeTag>
1054 assert(this->param_.local_well_solver_control_switching_);
1055 this->operability_status_.resetOperability();
1057 const auto& group_state = simulator.problem().wellModel().groupState();
1058 const double dt = simulator.timeStepSize();
1060 bool converged = iterateWellEquations(simulator, dt, well_state_copy, group_state, deferred_logger);
1064 template<
typename TypeTag>
1074 const auto& well = this->well_ecl_;
1075 const int well_index = this->index_of_well_;
1076 auto& ws = well_state.
well(well_index);
1079 const auto& summaryState = simulator.vanguard().summaryState();
1080 const auto& schedule = simulator.vanguard().schedule();
1082 if (this->wellIsStopped()) {
1083 for (
int p = 0; p<np; ++p) {
1084 ws.surface_rates[p] = 0;
1090 if (this->isInjector() )
1092 const auto& controls = well.injectionControls(summaryState);
1094 InjectorType injectorType = controls.injector_type;
1096 switch (injectorType) {
1097 case InjectorType::WATER:
1102 case InjectorType::OIL:
1107 case InjectorType::GAS:
1113 OPM_DEFLOG_THROW(std::runtime_error,
"Expected WATER, OIL or GAS as type for injectors " + this->name(), deferred_logger );
1116 const auto current = ws.injection_cmode;
1119 case Well::InjectorCMode::RATE:
1121 ws.surface_rates[phasePos] = (1.0 - this->rsRvInj()) * controls.surface_rate;
1122 if(this->rsRvInj() > 0) {
1123 if (injectorType == InjectorType::OIL && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
1125 }
else if (injectorType == InjectorType::GAS && FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
1128 OPM_DEFLOG_THROW(std::runtime_error,
"Expected OIL or GAS as type for injectors when RS/RV (item 10) is non-zero " + this->name(), deferred_logger );
1134 case Well::InjectorCMode::RESV:
1136 std::vector<Scalar> convert_coeff(this->number_of_phases_, 1.0);
1137 this->rateConverter_.calcCoeff( 0, this->pvtRegionIdx_, convert_coeff);
1138 const Scalar coeff = convert_coeff[phasePos];
1139 ws.surface_rates[phasePos] = controls.reservoir_rate/coeff;
1143 case Well::InjectorCMode::THP:
1145 auto rates = ws.surface_rates;
1150 this->getRefDensity(),
1153 ws.thp = this->getTHPConstraint(summaryState);
1158 Scalar total_rate = std::accumulate(rates.begin(), rates.end(), 0.0);
1159 if (total_rate <= 0.0)
1160 ws.surface_rates = ws.well_potentials;
1164 case Well::InjectorCMode::BHP:
1166 ws.bhp = controls.bhp_limit;
1168 for (
int p = 0; p<np; ++p) {
1169 total_rate += ws.surface_rates[p];
1174 if (total_rate <= 0.0)
1175 ws.surface_rates = ws.well_potentials;
1179 case Well::InjectorCMode::GRUP:
1181 assert(well.isAvailableForGroupControl());
1182 const auto& group = schedule.getGroup(well.groupName(), this->currentStep());
1183 const Scalar efficiencyFactor = well.getEfficiencyFactor();
1184 std::optional<Scalar> target =
1185 this->getGroupInjectionTargetRate(group,
1194 ws.surface_rates[phasePos] = *target;
1197 case Well::InjectorCMode::CMODE_UNDEFINED:
1199 OPM_DEFLOG_THROW(std::runtime_error,
"Well control must be specified for well " + this->name(), deferred_logger );
1209 ws.surface_rates[phasePos] = std::max(
Scalar{1.e-7}, ws.surface_rates[phasePos]);
1212 ws.bhp = controls.bhp_limit;
1218 const auto current = ws.production_cmode;
1219 const auto& controls = well.productionControls(summaryState);
1221 case Well::ProducerCMode::ORAT:
1223 Scalar current_rate = -ws.surface_rates[ pu.phase_pos[Oil] ];
1226 if (current_rate > 0.0) {
1227 for (
int p = 0; p<np; ++p) {
1228 ws.surface_rates[p] *= controls.oil_rate/current_rate;
1231 const std::vector<Scalar> fractions = initialWellRateFractions(simulator, well_state);
1232 double control_fraction = fractions[pu.phase_pos[Oil]];
1233 if (control_fraction != 0.0) {
1234 for (
int p = 0; p<np; ++p) {
1235 ws.surface_rates[p] = - fractions[p] * controls.oil_rate/control_fraction;
1241 case Well::ProducerCMode::WRAT:
1243 Scalar current_rate = -ws.surface_rates[ pu.phase_pos[Water] ];
1246 if (current_rate > 0.0) {
1247 for (
int p = 0; p<np; ++p) {
1248 ws.surface_rates[p] *= controls.water_rate/current_rate;
1251 const std::vector<Scalar> fractions = initialWellRateFractions(simulator, well_state);
1252 const Scalar control_fraction = fractions[pu.phase_pos[Water]];
1253 if (control_fraction != 0.0) {
1254 for (
int p = 0; p<np; ++p) {
1255 ws.surface_rates[p] = - fractions[p] * controls.water_rate / control_fraction;
1261 case Well::ProducerCMode::GRAT:
1263 Scalar current_rate = -ws.surface_rates[pu.phase_pos[Gas] ];
1266 if (current_rate > 0.0) {
1267 for (
int p = 0; p<np; ++p) {
1268 ws.surface_rates[p] *= controls.gas_rate/current_rate;
1271 const std::vector<Scalar > fractions = initialWellRateFractions(simulator, well_state);
1272 const Scalar control_fraction = fractions[pu.phase_pos[Gas]];
1273 if (control_fraction != 0.0) {
1274 for (
int p = 0; p<np; ++p) {
1275 ws.surface_rates[p] = - fractions[p] * controls.gas_rate / control_fraction;
1283 case Well::ProducerCMode::LRAT:
1285 Scalar current_rate = - ws.surface_rates[ pu.phase_pos[Water] ]
1286 - ws.surface_rates[ pu.phase_pos[Oil] ];
1289 if (current_rate > 0.0) {
1290 for (
int p = 0; p<np; ++p) {
1291 ws.surface_rates[p] *= controls.liquid_rate/current_rate;
1294 const std::vector<Scalar> fractions = initialWellRateFractions(simulator, well_state);
1295 const Scalar control_fraction = fractions[pu.phase_pos[Water]] + fractions[pu.phase_pos[Oil]];
1296 if (control_fraction != 0.0) {
1297 for (
int p = 0; p<np; ++p) {
1298 ws.surface_rates[p] = - fractions[p] * controls.liquid_rate / control_fraction;
1304 case Well::ProducerCMode::CRAT:
1307 fmt::format(
"CRAT control not supported, well {}", this->name()),
1310 case Well::ProducerCMode::RESV:
1312 std::vector<Scalar> convert_coeff(this->number_of_phases_, 1.0);
1313 this->rateConverter_.calcCoeff( 0, this->pvtRegionIdx_, ws.surface_rates, convert_coeff);
1314 Scalar total_res_rate = 0.0;
1315 for (
int p = 0; p<np; ++p) {
1316 total_res_rate -= ws.surface_rates[p] * convert_coeff[p];
1318 if (controls.prediction_mode) {
1321 if (total_res_rate > 0.0) {
1322 for (
int p = 0; p<np; ++p) {
1323 ws.surface_rates[p] *= controls.resv_rate/total_res_rate;
1326 const std::vector<Scalar> fractions = initialWellRateFractions(simulator, well_state);
1327 for (
int p = 0; p<np; ++p) {
1328 ws.surface_rates[p] = - fractions[p] * controls.resv_rate / convert_coeff[p];
1332 std::vector<Scalar> hrates(this->number_of_phases_,0.);
1333 if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
1334 hrates[pu.phase_pos[Water]] = controls.water_rate;
1336 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
1337 hrates[pu.phase_pos[Oil]] = controls.oil_rate;
1339 if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
1340 hrates[pu.phase_pos[Gas]] = controls.gas_rate;
1342 std::vector<Scalar> hrates_resv(this->number_of_phases_,0.);
1343 this->rateConverter_.calcReservoirVoidageRates( 0, this->pvtRegionIdx_, hrates, hrates_resv);
1344 Scalar target = std::accumulate(hrates_resv.begin(), hrates_resv.end(), 0.0);
1347 if (total_res_rate > 0.0) {
1348 for (
int p = 0; p<np; ++p) {
1349 ws.surface_rates[p] *= target/total_res_rate;
1352 const std::vector<Scalar> fractions = initialWellRateFractions(simulator, well_state);
1353 for (
int p = 0; p<np; ++p) {
1354 ws.surface_rates[p] = - fractions[p] * target / convert_coeff[p];
1360 case Well::ProducerCMode::BHP:
1362 ws.bhp = controls.bhp_limit;
1364 for (
int p = 0; p<np; ++p) {
1365 total_rate -= ws.surface_rates[p];
1370 if (total_rate <= 0.0){
1371 for (
int p = 0; p<np; ++p) {
1372 ws.surface_rates[p] = -ws.well_potentials[p];
1377 case Well::ProducerCMode::THP:
1379 const bool update_success = updateWellStateWithTHPTargetProd(simulator, well_state, deferred_logger);
1381 if (!update_success) {
1385 auto rates = ws.surface_rates;
1386 this->adaptRatesForVFP(rates);
1388 well_state, rates, well, summaryState, this->getRefDensity(), deferred_logger);
1390 ws.thp = this->getTHPConstraint(summaryState);
1394 const Scalar total_rate = -std::accumulate(rates.begin(), rates.end(), 0.0);
1395 if (total_rate <= 0.0) {
1396 for (
int p = 0; p < this->number_of_phases_; ++p) {
1397 ws.surface_rates[p] = -ws.well_potentials[p];
1403 case Well::ProducerCMode::GRUP:
1405 assert(well.isAvailableForGroupControl());
1406 const auto& group = schedule.getGroup(well.groupName(), this->currentStep());
1407 const Scalar efficiencyFactor = well.getEfficiencyFactor();
1408 Scalar scale = this->getGroupProductionTargetRate(group,
1418 for (
int p = 0; p<np; ++p) {
1419 ws.surface_rates[p] *= scale;
1421 ws.trivial_target =
false;
1423 ws.trivial_target =
true;
1427 case Well::ProducerCMode::CMODE_UNDEFINED:
1430 OPM_DEFLOG_THROW(std::runtime_error,
"Well control must be specified for well " + this->name() , deferred_logger);
1436 ws.bhp = controls.bhp_limit;
1441 template<
typename TypeTag>
1449 const bool isGroupControlled = this->wellUnderGroupControl(well_state.
well(this->index_of_well_));
1450 if (!isGroupControlled) {
1452 const auto& summaryState = simulator.vanguard().summaryState();
1453 return this->wellUnderZeroRateTargetIndividual(summaryState, well_state);
1455 return this->wellUnderZeroGroupRateTarget(simulator, well_state, deferred_logger, isGroupControlled);
1459 template <
typename TypeTag>
1464 const std::optional<bool> group_control)
const
1467 const bool isGroupControlled = group_control.value_or(this->wellUnderGroupControl(well_state.
well(this->index_of_well_)));
1468 if (isGroupControlled) {
1469 const auto& summaryState = simulator.vanguard().summaryState();
1470 const auto& group_state = simulator.problem().wellModel().groupState();
1471 const auto& schedule = simulator.vanguard().schedule();
1472 return this->zeroGroupRateTarget(summaryState, schedule, well_state, group_state, deferred_logger);
1477 template<
typename TypeTag>
1486 return this->wellIsStopped()
1487 || this->wellUnderZeroRateTarget(simulator, well_state, deferred_logger);
1490 template<
typename TypeTag>
1491 std::vector<typename WellInterface<TypeTag>::Scalar>
1496 const int np = this->number_of_phases_;
1497 std::vector<Scalar> scaling_factor(np);
1498 const auto& ws = well_state.
well(this->index_of_well_);
1500 Scalar total_potentials = 0.0;
1501 for (
int p = 0; p<np; ++p) {
1502 total_potentials += ws.well_potentials[p];
1504 if (total_potentials > 0) {
1505 for (
int p = 0; p<np; ++p) {
1506 scaling_factor[p] = ws.well_potentials[p] / total_potentials;
1508 return scaling_factor;
1513 const int nperf = this->number_of_perforations_;
1514 for (
int perf = 0; perf < nperf; ++perf) {
1515 total_tw += this->well_index_[perf];
1517 for (
int perf = 0; perf < nperf; ++perf) {
1518 const int cell_idx = this->well_cells_[perf];
1519 const auto& intQuants = simulator.model().intensiveQuantities(cell_idx, 0);
1520 const auto& fs = intQuants.fluidState();
1521 const Scalar well_tw_fraction = this->well_index_[perf] / total_tw;
1522 Scalar total_mobility = 0.0;
1523 for (
int p = 0; p < np; ++p) {
1524 int modelPhaseIdx = this->flowPhaseToModelPhaseIdx(p);
1525 total_mobility += fs.invB(modelPhaseIdx).value() * intQuants.mobility(modelPhaseIdx).value();
1527 for (
int p = 0; p < np; ++p) {
1528 int modelPhaseIdx = this->flowPhaseToModelPhaseIdx(p);
1529 scaling_factor[p] += well_tw_fraction * fs.invB(modelPhaseIdx).value() * intQuants.mobility(modelPhaseIdx).value() / total_mobility;
1532 return scaling_factor;
1537 template <
typename TypeTag>
1546 auto& ws = well_state.
well(this->index_of_well_);
1547 int nonzero_rate_index = -1;
1548 const Scalar floating_point_error_epsilon = 1e-14;
1549 for (
int p = 0; p < this->number_of_phases_; ++p) {
1550 if (std::abs(ws.surface_rates[p]) > floating_point_error_epsilon) {
1551 if (nonzero_rate_index == -1) {
1552 nonzero_rate_index = p;
1561 std::vector<Scalar> well_q_s = computeCurrentWellRates(simulator, deferred_logger);
1563 if (nonzero_rate_index == -1) {
1566 for (
int p = 0; p < this->number_of_phases_; ++p) {
1567 ws.surface_rates[p] = well_q_s[this->flowPhaseToModelCompIdx(p)];
1573 const Scalar initial_nonzero_rate = ws.surface_rates[nonzero_rate_index];
1574 const int comp_idx_nz = this->flowPhaseToModelCompIdx(nonzero_rate_index);
1575 if (std::abs(well_q_s[comp_idx_nz]) > floating_point_error_epsilon) {
1576 for (
int p = 0; p < this->number_of_phases_; ++p) {
1577 if (p != nonzero_rate_index) {
1578 const int comp_idx = this->flowPhaseToModelCompIdx(p);
1579 Scalar& rate = ws.surface_rates[p];
1580 rate = (initial_nonzero_rate / well_q_s[comp_idx_nz]) * (well_q_s[comp_idx]);
1586 template <
typename TypeTag>
1587 std::vector<typename WellInterface<TypeTag>::Scalar>
1597 auto wi = std::vector<Scalar>
1598 (this->num_components_, this->well_index_[perf] * trans_mult);
1600 if constexpr (! Indices::gasEnabled) {
1604 const auto& wdfac = this->well_ecl_.getWDFAC();
1606 if (! wdfac.useDFactor() || (this->well_index_[perf] == 0.0)) {
1610 const Scalar d = this->computeConnectionDFactor(perf, intQuants, ws);
1617 const auto& connection = this->well_ecl_.getConnections()[ws.
perf_data.ecl_index[perf]];
1618 const Scalar Kh = connection.Kh();
1619 const Scalar scaling = 3.141592653589 * Kh * connection.wpimult();
1620 const unsigned gas_comp_idx = Indices::canonicalToActiveComponentIndex(FluidSystem::gasCompIdx);
1623 const Scalar cell_pressure = getValue(intQuants.fluidState().pressure(FluidSystem::gasPhaseIdx));
1624 const Scalar drawdown = cell_pressure - connection_pressure;
1625 const Scalar invB = getValue(intQuants.fluidState().invB(FluidSystem::gasPhaseIdx));
1626 const Scalar mob_g = getValue(intQuants.mobility(FluidSystem::gasPhaseIdx)) * invB;
1628 const Scalar b = 2*scaling/wi[gas_comp_idx];
1629 const Scalar c = -2*scaling*mob_g*drawdown;
1631 Scalar consistent_Q = -1.0e20;
1633 const Scalar r2n = b*b + 4*a*c;
1635 const Scalar rn = std::sqrt(r2n);
1636 const Scalar xn1 = (b-rn)*0.5/a;
1640 const Scalar xn2 = (b+rn)*0.5/a;
1641 if (xn2 <= 0 && xn2 > consistent_Q) {
1647 const Scalar r2p = b*b - 4*a*c;
1649 const Scalar rp = std::sqrt(r2p);
1650 const Scalar xp1 = (rp-b)*0.5/a;
1651 if (xp1 > 0 && xp1 < consistent_Q) {
1654 const Scalar xp2 = -(rp+b)*0.5/a;
1655 if (xp2 > 0 && xp2 < consistent_Q) {
1659 wi[gas_comp_idx] = 1.0/(1.0/(trans_mult * this->well_index_[perf]) + (consistent_Q/2 * d / scaling));
1664 template <
typename TypeTag>
1670 if (! this->well_ecl_.getWDFAC().useDFactor()) {
1674 auto& d_factor = ws.
perf_data.connection_d_factor;
1676 for (
int perf = 0; perf < this->number_of_perforations_; ++perf) {
1677 const int cell_idx = this->well_cells_[perf];
1678 const auto& intQuants = simulator.model().intensiveQuantities(cell_idx, 0);
1680 d_factor[perf] = this->computeConnectionDFactor(perf, intQuants, ws);
1684 template <
typename TypeTag>
1691 auto rhoGS = [regIdx = this->pvtRegionIdx()]() {
1692 return FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, regIdx);
1696 auto gas_visc = [connection_pressure = ws.
perf_data.pressure[perf],
1698 regIdx = this->pvtRegionIdx(), &intQuants]()
1700 const auto rv = getValue(intQuants.fluidState().Rv());
1702 const auto& gasPvt = FluidSystem::gasPvt();
1707 const Scalar rv_sat = gasPvt.saturatedOilVaporizationFactor
1708 (regIdx, temperature, connection_pressure);
1710 if (! (rv < rv_sat)) {
1711 return gasPvt.saturatedViscosity(regIdx, temperature,
1712 connection_pressure);
1715 return gasPvt.viscosity(regIdx, temperature, connection_pressure,
1716 rv, getValue(intQuants.fluidState().Rvw()));
1719 const auto& connection = this->well_ecl_.getConnections()
1722 return this->well_ecl_.getWDFAC().getDFactor(rhoGS, gas_visc, connection);
1726 template <
typename TypeTag>
1732 auto connCF = [&connIx = std::as_const(ws.
perf_data.ecl_index),
1733 &conns = this->well_ecl_.getConnections()]
1736 return conns[connIx[perf]].CF();
1739 auto& tmult = ws.
perf_data.connection_compaction_tmult;
1740 auto& ctf = ws.
perf_data.connection_transmissibility_factor;
1742 for (
int perf = 0; perf < this->number_of_perforations_; ++perf) {
1743 const int cell_idx = this->well_cells_[perf];
1745 const auto& intQuants = simulator.model()
1746 .intensiveQuantities(cell_idx, 0);
1748 tmult[perf] = simulator.problem()
1749 .template wellTransMultiplier<double>(intQuants, cell_idx);
1751 ctf[perf] = connCF(perf) * tmult[perf];
1756 template<
typename TypeTag>
1760 if constexpr (Indices::oilEnabled) {
1761 return fs.pressure(FluidSystem::oilPhaseIdx);
1762 }
else if constexpr (Indices::gasEnabled) {
1763 return fs.pressure(FluidSystem::gasPhaseIdx);
1765 return fs.pressure(FluidSystem::waterPhaseIdx);
1769 template <
typename TypeTag>
1770 template<
class Value,
class Callback>
1775 std::vector<Value>& mob,
1776 Callback& extendEval,
1779 auto relpermArray = []()
1781 if constexpr (std::is_same_v<Value, Scalar>) {
1782 return std::array<Scalar,3>{};
1784 return std::array<Eval,3>{};
1787 const int cell_idx = this->well_cells_[perf];
1788 assert (
int(mob.size()) == this->num_components_);
1789 const auto& intQuants = simulator.model().intensiveQuantities(cell_idx, 0);
1790 const auto& materialLawManager = simulator.problem().materialLawManager();
1794 const int satid = this->saturation_table_number_[perf] - 1;
1795 const int satid_elem = materialLawManager->satnumRegionIdx(cell_idx);
1796 if (satid == satid_elem) {
1797 for (
unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
1798 if (!FluidSystem::phaseIsActive(phaseIdx)) {
1802 const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
1803 mob[activeCompIdx] = extendEval(intQuants.mobility(phaseIdx));
1805 if constexpr (has_solvent) {
1806 mob[Indices::contiSolventEqIdx] = extendEval(intQuants.solventMobility());
1809 const auto& paramsCell = materialLawManager->connectionMaterialLawParams(satid, cell_idx);
1810 auto relativePerms = relpermArray();
1811 MaterialLaw::relativePermeabilities(relativePerms, paramsCell, intQuants.fluidState());
1814 materialLawManager->connectionMaterialLawParams(satid_elem, cell_idx);
1817 for (
unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
1818 if (!FluidSystem::phaseIsActive(phaseIdx)) {
1822 const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
1823 mob[activeCompIdx] = extendEval(relativePerms[phaseIdx] / intQuants.fluidState().viscosity(phaseIdx));
1827 if constexpr (has_solvent) {
1828 OPM_DEFLOG_THROW(std::runtime_error,
"individual mobility for wells does not work in combination with solvent", deferred_logger);
1832 if (this->isInjector() && !this->inj_fc_multiplier_.empty()) {
1833 const auto perf_ecl_index = this->perforationData()[perf].ecl_index;
1834 const auto& connections = this->well_ecl_.getConnections();
1835 const auto& connection = connections[perf_ecl_index];
1836 if (connection.filterCakeActive()) {
1837 for (
auto& val : mob) {
1838 val *= this->inj_fc_multiplier_[perf];
1845 template<
typename TypeTag>
1852 const auto& summary_state = simulator.vanguard().summaryState();
1854 auto bhp_at_thp_limit = computeBhpAtThpLimitProdWithAlq(
1855 simulator, summary_state, this->getALQ(well_state), deferred_logger);
1856 if (bhp_at_thp_limit) {
1857 std::vector<Scalar> rates(this->number_of_phases_, 0.0);
1858 if (thp_update_iterations) {
1859 computeWellRatesWithBhpIterations(simulator, *bhp_at_thp_limit,
1860 rates, deferred_logger);
1862 computeWellRatesWithBhp(simulator, *bhp_at_thp_limit,
1863 rates, deferred_logger);
1865 auto& ws = well_state.
well(this->name());
1866 ws.surface_rates = rates;
1867 ws.bhp = *bhp_at_thp_limit;
1868 ws.thp = this->getTHPConstraint(summary_state);
1875 template <
typename TypeTag>
1880 const std::vector<Scalar>& mobility,
1884 const int np = this->number_of_phases_;
1885 for (
int p = 0; p < np; ++p) {
1888 const auto connMob =
1889 mobility[this->flowPhaseToModelCompIdx(p)]
1890 * fs.invB(this->flowPhaseToModelPhaseIdx(p)).value();
1892 connPI[p] = connPICalc(connMob);
1895 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) &&
1896 FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx))
1898 const auto io = pu.phase_pos[Oil];
1899 const auto ig = pu.phase_pos[Gas];
1901 const auto vapoil = connPI[ig] * fs.Rv().value();
1902 const auto disgas = connPI[io] * fs.Rs().value();
1904 connPI[io] += vapoil;
1905 connPI[ig] += disgas;
1910 template <
typename TypeTag>
1914 const Phase preferred_phase,
1916 const std::vector<Scalar>& mobility,
1924 if (preferred_phase == Phase::GAS) {
1925 phase_pos = pu.phase_pos[Gas];
1927 else if (preferred_phase == Phase::OIL) {
1928 phase_pos = pu.phase_pos[Oil];
1930 else if (preferred_phase == Phase::WATER) {
1931 phase_pos = pu.phase_pos[Water];
1935 fmt::format(
"Unsupported Injector Type ({}) "
1936 "for well {} during connection I.I. calculation",
1937 static_cast<int>(preferred_phase), this->name()),
1941 const auto mt = std::accumulate(mobility.begin(), mobility.end(), 0.0);
1942 connII[phase_pos] = connIICalc(mt * fs.invB(this->flowPhaseToModelPhaseIdx(phase_pos)).value());
#define OPM_DEFLOG_THROW(Exception, message, deferred_logger)
Definition: DeferredLoggingErrorHelpers.hpp:45
@ Liquid
Definition: BlackoilPhases.hpp:42
@ Aqua
Definition: BlackoilPhases.hpp:42
@ Vapour
Definition: BlackoilPhases.hpp:42
Definition: DeferredLogger.hpp:57
void info(const std::string &tag, const std::string &message)
void warning(const std::string &tag, const std::string &message)
void debug(const std::string &tag, const std::string &message)
Definition: GroupState.hpp:38
Class encapsulating some information about parallel wells.
Definition: ParallelWellInfo.hpp:186
Definition: SingleWellState.hpp:42
PerfData< Scalar > perf_data
Definition: SingleWellState.hpp:110
Scalar temperature
Definition: SingleWellState.hpp:90
Class for computing BHP limits.
Definition: WellBhpThpCalculator.hpp:41
std::optional< Scalar > estimateStableBhp(const WellState< Scalar > &well_state, const Well &well, const std::vector< Scalar > &rates, const Scalar rho, const SummaryState &summaryState) const
Scalar calculateMinimumBhpFromThp(const WellState< Scalar > &well_state, const Well &well, const SummaryState &summaryState, const Scalar rho) const
bool isStableSolution(const WellState< Scalar > &well_state, const Well &well, const std::vector< Scalar > &rates, const SummaryState &summaryState) const
EvalWell calculateBhpFromThp(const WellState< Scalar > &well_state, const std::vector< EvalWell > &rates, const Well &well, const SummaryState &summaryState, const Scalar rho, DeferredLogger &deferred_logger) const
int number_of_perforations_
Definition: WellInterfaceGeneric.hpp:306
Well well_ecl_
Definition: WellInterfaceGeneric.hpp:273
const std::vector< FluidSystem::Scalar > & wellIndex() const
Definition: WellInterfaceGeneric.hpp:141
FluidSystem::Scalar wsolvent_
Definition: WellInterfaceGeneric.hpp:348
Definition: WellInterfaceIndices.hpp:34
bool updateWellControl(const Simulator &simulator, const IndividualOrGroup iog, WellState< Scalar > &well_state, const GroupState< Scalar > &group_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:195
Scalar woxygen() const
Definition: WellInterface_impl.hpp:165
IndividualOrGroup
Definition: WellInterface.hpp:244
GetPropType< TypeTag, Properties::Simulator > Simulator
Definition: WellInterface.hpp:78
WellInterface(const Well &well, const ParallelWellInfo< Scalar > &pw_info, const int time_step, const ModelParameters ¶m, const RateConverterType &rate_converter, const int pvtRegionIdx, const int num_components, const int num_phases, const int index_of_well, const std::vector< PerforationData< Scalar > > &perf_data)
Constructor.
Definition: WellInterface_impl.hpp:55
void getMobility(const Simulator &simulator, const int perf, std::vector< Value > &mob, Callback &extendEval, DeferredLogger &deferred_logger) const
Definition: WellInterface_impl.hpp:1773
void assembleWellEq(const Simulator &simulator, const double dt, WellState< Scalar > &well_state, const GroupState< Scalar > &group_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:782
typename WellInterfaceFluidSystem< FluidSystem >::RateConverterType RateConverterType
Definition: WellInterface.hpp:100
BlackOilFluidState< Eval, FluidSystem, has_temperature, has_energy, Indices::compositionSwitchIdx >=0, has_watVapor, has_brine, has_saltPrecip, has_disgas_in_water, Indices::numPhases > FluidState
Definition: WellInterface.hpp:132
Scalar wfoam() const
Definition: WellInterface_impl.hpp:127
std::vector< RateVector > connectionRates_
Definition: WellInterface.hpp:389
bool wellUnderZeroRateTarget(const Simulator &simulator, const WellState< Scalar > &well_state, DeferredLogger &deferred_logger) const
Definition: WellInterface_impl.hpp:1444
void computeConnLevelProdInd(const FluidState &fs, const std::function< Scalar(const Scalar)> &connPICalc, const std::vector< Scalar > &mobility, Scalar *connPI) const
Definition: WellInterface_impl.hpp:1878
bool updateWellStateWithTHPTargetProd(const Simulator &simulator, WellState< Scalar > &well_state, DeferredLogger &deferred_logger) const
Definition: WellInterface_impl.hpp:1848
void addCellRates(RateVector &rates, int cellIdx) const
Definition: WellInterface_impl.hpp:874
Scalar volumetricSurfaceRateForConnection(int cellIdx, int phaseIdx) const
Definition: WellInterface_impl.hpp:890
virtual void init(const PhaseUsage *phase_usage_arg, const std::vector< Scalar > &depth_arg, const Scalar gravity_arg, const int num_cells, const std::vector< Scalar > &B_avg, const bool changed_to_open_this_step)
Definition: WellInterface_impl.hpp:92
bool iterateWellEquations(const Simulator &simulator, const double dt, WellState< Scalar > &well_state, const GroupState< Scalar > &group_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:481
GetPropType< TypeTag, Properties::IntensiveQuantities > IntensiveQuantities
Definition: WellInterface.hpp:82
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: WellInterface.hpp:79
void checkWellOperability(const Simulator &simulator, const WellState< Scalar > &well_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:910
std::optional< Scalar > estimateOperableBhp(const Simulator &ebos_simulator, const double dt, WellState< Scalar > &well_state, const SummaryState &summary_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:611
void updateWellOperability(const Simulator &simulator, const WellState< Scalar > &well_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:1013
void updateWellStateRates(const Simulator &simulator, WellState< Scalar > &well_state, DeferredLogger &deferred_logger) const
Definition: WellInterface_impl.hpp:1540
virtual void updateWellStateWithTarget(const Simulator &simulator, const GroupState< Scalar > &group_state, WellState< Scalar > &well_state, DeferredLogger &deferred_logger) const
Definition: WellInterface_impl.hpp:1067
Eval getPerfCellPressure(const FluidState &fs) const
Definition: WellInterface_impl.hpp:1758
void updateConnectionTransmissibilityFactor(const Simulator &simulator, SingleWellState< Scalar > &ws) const
Definition: WellInterface_impl.hpp:1729
bool stoppedOrZeroRateTarget(const Simulator &simulator, const WellState< Scalar > &well_state, DeferredLogger &deferred_logger) const
Definition: WellInterface_impl.hpp:1480
GetPropType< TypeTag, Properties::FluidSystem > FluidSystem
Definition: WellInterface.hpp:80
static constexpr bool has_solvent
Definition: WellInterface.hpp:108
void prepareWellBeforeAssembling(const Simulator &simulator, const double dt, WellState< Scalar > &well_state, const GroupState< Scalar > &group_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:816
bool gliftBeginTimeStepWellTestIterateWellEquations(const Simulator &ebos_simulator, const double dt, WellState< Scalar > &well_state, const GroupState< Scalar > &group_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:935
GetPropType< TypeTag, Properties::RateVector > RateVector
Definition: WellInterface.hpp:85
void computeConnLevelInjInd(const FluidState &fs, const Phase preferred_phase, const std::function< Scalar(const Scalar)> &connIICalc, const std::vector< Scalar > &mobility, Scalar *connII, DeferredLogger &deferred_logger) const
Definition: WellInterface_impl.hpp:1913
void solveWellEquation(const Simulator &simulator, WellState< Scalar > &well_state, const GroupState< Scalar > &group_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:725
void updateConnectionDFactor(const Simulator &simulator, SingleWellState< Scalar > &ws) const
Definition: WellInterface_impl.hpp:1667
std::vector< Scalar > initialWellRateFractions(const Simulator &ebosSimulator, const WellState< Scalar > &well_state) const
Definition: WellInterface_impl.hpp:1493
Scalar wsalt() const
Definition: WellInterface_impl.hpp:141
bool updateWellOperabilityFromWellEq(const Simulator &simulator, const WellState< Scalar > &well_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:1049
void gliftBeginTimeStepWellTestUpdateALQ(const Simulator &simulator, WellState< Scalar > &well_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:969
typename Base::Eval Eval
Definition: WellInterface.hpp:95
void wellTesting(const Simulator &simulator, const double simulation_time, WellState< Scalar > &well_state, const GroupState< Scalar > &group_state, WellTestState &welltest_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:376
Scalar wpolymer() const
Definition: WellInterface_impl.hpp:111
Scalar computeConnectionDFactor(const int perf, const IntensiveQuantities &intQuants, const SingleWellState< Scalar > &ws) const
Definition: WellInterface_impl.hpp:1687
bool solveWellWithBhp(const Simulator &simulator, const double dt, const Scalar bhp, WellState< Scalar > &well_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:634
bool solveWellWithZeroRate(const Simulator &simulator, const double dt, WellState< Scalar > &well_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:670
bool solveWellForTesting(const Simulator &simulator, WellState< Scalar > &well_state, const GroupState< Scalar > &group_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:690
GetPropType< TypeTag, Properties::Indices > Indices
Definition: WellInterface.hpp:81
bool solveWellWithTHPConstraint(const Simulator &simulator, const double dt, const Well::InjectionControls &inj_controls, const Well::ProductionControls &prod_controls, WellState< Scalar > &well_state, const GroupState< Scalar > &group_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:514
Scalar wurea() const
Definition: WellInterface_impl.hpp:183
bool wellUnderZeroGroupRateTarget(const Simulator &simulator, const WellState< Scalar > &well_state, DeferredLogger &deferred_logger, std::optional< bool > group_control=std::nullopt) const
Definition: WellInterface_impl.hpp:1461
Scalar wmicrobes() const
Definition: WellInterface_impl.hpp:153
void assembleWellEqWithoutIteration(const Simulator &simulator, const double dt, WellState< Scalar > &well_state, const GroupState< Scalar > &group_state, DeferredLogger &deferred_logger)
Definition: WellInterface_impl.hpp:797
bool updateWellControlAndStatusLocalIteration(const Simulator &simulator, WellState< Scalar > &well_state, const GroupState< Scalar > &group_state, const Well::InjectionControls &inj_controls, const Well::ProductionControls &prod_controls, const Scalar WQTotal, DeferredLogger &deferred_logger, const bool fixed_control=false, const bool fixed_status=false)
Definition: WellInterface_impl.hpp:271
static constexpr bool has_zFraction
Definition: WellInterface.hpp:109
Definition: WellState.hpp:62
const SingleWellState< Scalar > & well(std::size_t well_index) const
Definition: WellState.hpp:307
void setALQ(const std::string &name, Scalar value)
Definition: WellState.hpp:186
int numPhases() const
The number of phases present.
Definition: WellState.hpp:261
Scalar getALQ(const std::string &name) const
Definition: WellState.hpp:181
@ NONE
Definition: DeferredLogger.hpp:46
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
Definition: blackoilboundaryratevector.hh:37
PhaseUsage phaseUsage(const Phases &phases)
Determine the active phases.
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
Solver parameters for the BlackoilModel.
Definition: BlackoilModelParameters.hpp:147
Static data associated with a well perforation.
Definition: PerforationData.hpp:30
Definition: BlackoilPhases.hpp:46