diff --git a/opm/autodiff/BlackoilWellModel_impl.hpp b/opm/autodiff/BlackoilWellModel_impl.hpp index b3cc189be..f49934fe7 100644 --- a/opm/autodiff/BlackoilWellModel_impl.hpp +++ b/opm/autodiff/BlackoilWellModel_impl.hpp @@ -433,10 +433,9 @@ namespace Opm { const Well* well_ecl = wells_ecl_[index_well]; - // TODO: a new WCON keyword can re-open the well closed by physical reason // A new WCON keywords can re-open a well that was closed/shut due to Physical limit if ( wellTestState_.hasWell(well_name, WellTestConfig::Reason::PHYSICAL ) ) { - // TODO: more checking here, to makre sure this standard more specific and complete + // TODO: more checking here, to make sure this standard more specific and complete // maybe there is some WCON keywords will not open the well if (well_state_.effectiveEventsOccurred(w) ) { wellTestState_.openWell(well_name); @@ -449,6 +448,7 @@ namespace Opm { wellTestState_.hasWell(well_name, WellTestConfig::Reason::PHYSICAL) ) { if( well_ecl->getAutomaticShutIn() ) { // shut wells are not added to the well container + // TODO: make a function from well_state side to handle the following well_state_.thp()[w] = 0.; well_state_.bhp()[w] = 0.; const int np = numPhases(); @@ -954,7 +954,7 @@ namespace Opm { prepareGroupControl(); for (const auto& well : well_container_) { - well->checkWellOperatability(ebosSimulator_); + well->checkWellOperability(ebosSimulator_); } // since the controls are all updated, we should update well_state accordingly @@ -973,7 +973,7 @@ namespace Opm { // there is no new well control change input within a report step, // so next time step, the well does not consider to have effective events anymore // TODO: if we can know whether this is the first time step within the report step, - // we do not need to change this + // we do not need to set it to false // TODO: we should do this at the end of the time step in case we will need it within // this time step somewhere if (well_state_.effectiveEventsOccurred(w) ) { diff --git a/opm/autodiff/MultisegmentWell.hpp b/opm/autodiff/MultisegmentWell.hpp index eb56ba6bf..c3613ff98 100644 --- a/opm/autodiff/MultisegmentWell.hpp +++ b/opm/autodiff/MultisegmentWell.hpp @@ -332,7 +332,7 @@ namespace Opm // checking the operability of the well based on current reservoir condition // it is not implemented for multisegment well yet - virtual void checkWellOperatability(const Simulator& ebos_simulator); + virtual void checkWellOperability(const Simulator& ebos_simulator); void updateWellStateFromPrimaryVariables(WellState& well_state) const; diff --git a/opm/autodiff/MultisegmentWell_impl.hpp b/opm/autodiff/MultisegmentWell_impl.hpp index 8f4bc2977..e101e21af 100644 --- a/opm/autodiff/MultisegmentWell_impl.hpp +++ b/opm/autodiff/MultisegmentWell_impl.hpp @@ -1645,10 +1645,10 @@ namespace Opm template void MultisegmentWell:: - checkWellOperatability(const Simulator& ebos_simulator) + checkWellOperability(const Simulator& ebos_simulator) { - const std::string msg = "Support of well operatability checking for mutlisegment wells is not yet," - " checkWellOperatability() for " + name() + " will do nothing"; + const std::string msg = "Support of well operatability checking for mutlisegment wells is not implemented " + "yet, checkWellOperability() for " + name() + " will do nothing"; OpmLog::warning("NO_OPERATABILITY_CHECKING_MS_WELLS", msg); } diff --git a/opm/autodiff/StandardWell.hpp b/opm/autodiff/StandardWell.hpp index 28d4f2a1f..49a49407e 100644 --- a/opm/autodiff/StandardWell.hpp +++ b/opm/autodiff/StandardWell.hpp @@ -350,7 +350,7 @@ namespace Opm // check whether the well is operable under the current reservoir condition // mostly related to BHP limit and THP limit - virtual void checkWellOperatability(const Simulator& ebos_simulator) override; + virtual void checkWellOperability(const Simulator& ebos_simulator) override; // check whether the well is operable under BHP limit with current reservoir condition void checkOperabilityUnderBHPLimit(const Simulator& ebos_simulator); @@ -367,7 +367,14 @@ namespace Opm // for a well, when all drawdown are in the wrong direction, then this well will not // be able to produce/inject . - bool allDrawDownWrongDirection(const Simulator& ebosSimulator) const; + bool allDrawDownWrongDirection(const Simulator& ebos_simulator) const; + + // turn on crossflow to avoid singular well equations + // when the well is banned from cross-flow and the BHP is not properly initialized, + // we turn on crossflow to avoid singular well equations. It can result in worng-signed + // well rates, it can cause problem for THP calculation + // TODO: looking for better alternative to avoid wrong-signed well rates + bool openCrossFlowAvoidSingularity(const Simulator& ebos_simulator) const; // calculate the BHP from THP target based on IPR // TODO: we need to check the operablility here first, if not operable, then maybe there is diff --git a/opm/autodiff/StandardWell_impl.hpp b/opm/autodiff/StandardWell_impl.hpp index 954a0cb62..eb9f17a34 100644 --- a/opm/autodiff/StandardWell_impl.hpp +++ b/opm/autodiff/StandardWell_impl.hpp @@ -440,7 +440,7 @@ namespace Opm WellState& well_state) { - checkWellOperatability(ebosSimulator); + checkWellOperability(ebosSimulator); if (!this->isOperable()) return; @@ -453,7 +453,11 @@ namespace Opm // TODO: it probably can be static member for StandardWell const double volume = 0.002831684659200; // 0.1 cu ft; - const bool allow_cf = getAllowCrossFlow(); + // to avoid singularity of the well equation when all the drawdown is in the wrong direction + // TODO: make it a function, and avoid repeated calculation + // TODO: it can be avoided through adjusting the bhp of the well + const bool allow_cf = getAllowCrossFlow() || openCrossFlowAvoidSingularity(ebosSimulator); + const EvalWell& bhp = getBhp(); @@ -1293,12 +1297,12 @@ namespace Opm template void StandardWell:: - checkWellOperatability(const Simulator& ebos_simulator) + checkWellOperability(const Simulator& ebos_simulator) { // TODO: this function is probably can split another function out so that // wellTestingPhysical can share some code with this function - // on solution is that this function will be called updateWellOperatability - // and the actual checking part become another function checkWellOperatability + // on solution is that this function will be called updateWellOperability + // and the actual checking part become another function checkWellOperability // Let us wait until finishing the wellTestingPhysical first. // focusing on PRODUCER for now @@ -1428,13 +1432,13 @@ namespace Opm template bool StandardWell:: - allDrawDownWrongDirection(const Simulator& ebosSimulator) const + allDrawDownWrongDirection(const Simulator& ebos_simulator) const { bool all_drawdown_wrong_direction = true; for (int perf = 0; perf < number_of_perforations_; ++perf) { const int cell_idx = well_cells_[perf]; - const auto& intQuants = *(ebosSimulator.model().cachedIntensiveQuantities(cell_idx, /*timeIdx=*/0)); + const auto& intQuants = *(ebos_simulator.model().cachedIntensiveQuantities(cell_idx, /*timeIdx=*/0)); const auto& fs = intQuants.fluidState(); const double pressure = (fs.pressure(FluidSystem::oilPhaseIdx)).value(); @@ -1461,6 +1465,18 @@ namespace Opm + template + bool + StandardWell:: + openCrossFlowAvoidSingularity(const Simulator& ebos_simulator) const + { + return !getAllowCrossFlow() && allDrawDownWrongDirection(ebos_simulator); + } + + + + + template void StandardWell:: @@ -2494,7 +2510,8 @@ namespace Opm return; } // compute the well water velocity with out shear effects. - const bool allow_cf = getAllowCrossFlow(); + // TODO: do we need to turn on crossflow here? + const bool allow_cf = getAllowCrossFlow() || openCrossFlowAvoidSingularity(ebos_simulator); const EvalWell& bhp = getBhp(); std::vector cq_s(num_components_,0.0); double perf_dis_gas_rate = 0.; diff --git a/opm/autodiff/WellInterface.hpp b/opm/autodiff/WellInterface.hpp index 33f07cc8a..f2521a21f 100644 --- a/opm/autodiff/WellInterface.hpp +++ b/opm/autodiff/WellInterface.hpp @@ -223,7 +223,7 @@ namespace Opm void updatePerforatedCell(std::vector& is_cell_perforated); - virtual void checkWellOperatability(const Simulator& ebos_simulator) = 0; + virtual void checkWellOperability(const Simulator& ebos_simulator) = 0; // whether the well is operable bool isOperable() const;