we need to open the cross-flow to solve the sigularity

if a well is banned from cross-flow. When it is under RATE control, its
BHP might be initialized in way causing all the drawdown in the wrong
direction. It will cause singular well equations.

here, we open the croff-flow to fix the singularity and rely on Newton
iteraton to get desired result.

possible alternative approach is to adust the BHP to avoid the situation
that all the drawdown are in the wrong direction.
This commit is contained in:
Kai Bao 2018-11-17 23:39:09 +01:00
parent bba373c0b5
commit 90f805bf3e
6 changed files with 43 additions and 19 deletions

View File

@ -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) ) {

View File

@ -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;

View File

@ -1645,10 +1645,10 @@ namespace Opm
template <typename TypeTag>
void
MultisegmentWell<TypeTag>::
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);
}

View File

@ -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

View File

@ -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<typename TypeTag>
void
StandardWell<TypeTag>::
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<typename TypeTag>
bool
StandardWell<TypeTag>::
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<typename TypeTag>
bool
StandardWell<TypeTag>::
openCrossFlowAvoidSingularity(const Simulator& ebos_simulator) const
{
return !getAllowCrossFlow() && allDrawDownWrongDirection(ebos_simulator);
}
template<typename TypeTag>
void
StandardWell<TypeTag>::
@ -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<EvalWell> cq_s(num_components_,0.0);
double perf_dis_gas_rate = 0.;

View File

@ -223,7 +223,7 @@ namespace Opm
void updatePerforatedCell(std::vector<bool>& 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;