Loading...
Searching...
No Matches
WellInterface.hpp
/*
Copyright 2017 SINTEF Digital, Mathematics and Cybernetics.
Copyright 2017 Statoil ASA.
Copyright 2017 IRIS
Copyright 2019 Norce
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_WELLINTERFACE_HEADER_INCLUDED
#define OPM_WELLINTERFACE_HEADER_INCLUDED
// NOTE: GasLiftSingleWell.hpp includes StandardWell.hpp which includes ourself
// (WellInterface.hpp), so we need to forward declare GasLiftSingleWell
// for it to be defined in this file. Similar for BlackoilWellModel
namespace Opm {
template<typename TypeTag> class GasLiftSingleWell;
template<typename TypeTag> class BlackoilWellModel;
}
#include <opm/common/OpmLog/OpmLog.hpp>
#include <opm/common/ErrorMacros.hpp>
#include <opm/common/Exceptions.hpp>
#include <opm/input/eclipse/Schedule/Well/WellTestState.hpp>
#include <opm/material/fluidstates/BlackOilFluidState.hpp>
#include <opm/models/blackoil/blackoilproperties.hh>
#include <opm/simulators/linalg/linalgproperties.hh>
#include <opm/simulators/wells/BlackoilWellModel.hpp>
#include <opm/simulators/wells/GasLiftGroupInfo.hpp>
#include <opm/simulators/wells/GasLiftSingleWell.hpp>
#include <opm/simulators/wells/GasLiftSingleWellGeneric.hpp>
#include <opm/simulators/wells/PerforationData.hpp>
#include <opm/simulators/wells/WellInterfaceIndices.hpp>
#include <opm/simulators/wells/WellProdIndexCalculator.hpp>
#include <opm/simulators/wells/WellState.hpp>
#include <opm/simulators/timestepping/ConvergenceReport.hpp>
#include <opm/simulators/utils/DeferredLogger.hpp>
#include <dune/common/fmatrix.hh>
#include <dune/istl/bcrsmatrix.hh>
#include <dune/istl/matrixmatrix.hh>
#include <opm/material/densead/Evaluation.hpp>
#include <vector>
namespace Opm
{
class WellInjectionProperties;
class WellProductionProperties;
template<typename TypeTag>
class WellInterface : public WellInterfaceIndices<GetPropType<TypeTag, Properties::FluidSystem>,
GetPropType<TypeTag, Properties::Indices>>
{
using Base = WellInterfaceIndices<GetPropType<TypeTag, Properties::FluidSystem>,
GetPropType<TypeTag, Properties::Indices>>;
public:
using Grid = GetPropType<TypeTag, Properties::Grid>;
using Simulator = GetPropType<TypeTag, Properties::Simulator>;
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
using IndexTraits = typename FluidSystem::IndexTraitsType;
using Indices = GetPropType<TypeTag, Properties::Indices>;
using IntensiveQuantities = GetPropType<TypeTag, Properties::IntensiveQuantities>;
using MaterialLaw = GetPropType<TypeTag, Properties::MaterialLaw>;
using SparseMatrixAdapter = GetPropType<TypeTag, Properties::SparseMatrixAdapter>;
using RateVector = GetPropType<TypeTag, Properties::RateVector>;
using GasLiftSingleWell = ::Opm::GasLiftSingleWell<TypeTag>;
using GLiftEclWells = typename GasLiftGroupInfo<Scalar, IndexTraits>::GLiftEclWells;
using VectorBlockType = Dune::FieldVector<Scalar, Indices::numEq>;
using MatrixBlockType = Dune::FieldMatrix<Scalar, Indices::numEq, Indices::numEq>;
using Eval = typename Base::Eval;
using BVector = Dune::BlockVector<VectorBlockType>;
using PressureMatrix = Dune::BCRSMatrix<Opm::MatrixBlock<Scalar, 1, 1>>;
using WellStateType = WellState<Scalar, IndexTraits>;
using SingleWellStateType = SingleWellState<Scalar, IndexTraits>;
using RateConverterType =
typename WellInterfaceFluidSystem<FluidSystem>::RateConverterType;
using WellInterfaceFluidSystem<FluidSystem>::Gas;
using WellInterfaceFluidSystem<FluidSystem>::Oil;
using WellInterfaceFluidSystem<FluidSystem>::Water;
using ModelParameters = typename Base::ModelParameters;
static constexpr bool has_solvent = getPropValue<TypeTag, Properties::EnableSolvent>();
static constexpr bool has_zFraction = getPropValue<TypeTag, Properties::EnableExtbo>();
static constexpr bool has_polymer = getPropValue<TypeTag, Properties::EnablePolymer>();
static constexpr bool has_energy = getPropValue<TypeTag, Properties::EnableEnergy>();
static const bool has_temperature = getPropValue<TypeTag, Properties::EnableTemperature>();
// flag for polymer molecular weight related
static constexpr bool has_polymermw = getPropValue<TypeTag, Properties::EnablePolymerMW>();
static constexpr bool has_foam = getPropValue<TypeTag, Properties::EnableFoam>();
static constexpr bool has_brine = getPropValue<TypeTag, Properties::EnableBrine>();
static constexpr bool has_watVapor = getPropValue<TypeTag, Properties::EnableVapwat>();
static constexpr bool has_disgas_in_water = getPropValue<TypeTag, Properties::EnableDisgasInWater>();
static constexpr bool has_saltPrecip = getPropValue<TypeTag, Properties::EnableSaltPrecipitation>();
static constexpr bool has_bioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>();
static constexpr bool has_micp = Indices::enableMICP;
// For the conversion between the surface volume rate and reservoir voidage rate
using FluidState = BlackOilFluidState<Eval,
FluidSystem,
has_temperature,
has_energy,
Indices::compositionSwitchIdx >= 0,
has_watVapor,
has_brine,
has_saltPrecip,
has_disgas_in_water,
Indices::numPhases >;
WellInterface(const Well& well,
const ParallelWellInfo<Scalar>& pw_info,
const int time_step,
const ModelParameters& param,
const RateConverterType& rate_converter,
const int pvtRegionIdx,
const int num_conservation_quantities,
const int num_phases,
const int index_of_well,
const std::vector<PerforationData<Scalar>>& perf_data);
virtual ~WellInterface() = default;
virtual void init(const std::vector<Scalar>& depth_arg,
const Scalar gravity_arg,
const std::vector<Scalar>& B_avg,
const bool changed_to_open_this_step);
virtual ConvergenceReport getWellConvergence(const Simulator& simulator,
const WellStateType& well_state,
const std::vector<Scalar>& B_avg,
DeferredLogger& deferred_logger,
const bool relax_tolerance) const = 0;
virtual void solveEqAndUpdateWellState(const Simulator& simulator,
WellStateType& well_state,
DeferredLogger& deferred_logger) = 0;
void assembleWellEq(const Simulator& simulator,
const double dt,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger);
void assembleWellEqWithoutIteration(const Simulator& simulator,
const double dt,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger);
// TODO: better name or further refactoring the function to make it more clear
void prepareWellBeforeAssembling(const Simulator& simulator,
const double dt,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger);
virtual void computeWellRatesWithBhp(const Simulator& ebosSimulator,
const Scalar& bhp,
std::vector<Scalar>& well_flux,
DeferredLogger& deferred_logger) const = 0;
virtual std::optional<Scalar>
computeBhpAtThpLimitProdWithAlq(const Simulator& ebos_simulator,
const SummaryState& summary_state,
const Scalar alq_value,
DeferredLogger& deferred_logger,
bool iterate_if_no_solution) const = 0;
virtual void recoverWellSolutionAndUpdateWellState(const Simulator& simulator,
const BVector& x,
WellStateType& well_state,
DeferredLogger& deferred_logger) = 0;
virtual void apply(const BVector& x, BVector& Ax) const = 0;
virtual void apply(BVector& r) const = 0;
// TODO: before we decide to put more information under mutable, this function is not const
virtual void computeWellPotentials(const Simulator& simulator,
const WellStateType& well_state,
std::vector<Scalar>& well_potentials,
DeferredLogger& deferred_logger) = 0;
virtual void updateWellStateWithTarget(const Simulator& simulator,
const GroupState<Scalar>& group_state,
WellStateType& well_state,
DeferredLogger& deferred_logger) const;
virtual void scaleSegmentRatesAndPressure(WellStateType& well_state) const;
virtual void computeWellRatesWithBhpIterations(const Simulator& simulator,
const Scalar& bhp,
std::vector<Scalar>& well_flux,
DeferredLogger& deferred_logger) const = 0;
bool wellUnderZeroRateTarget(const Simulator& simulator,
const WellStateType& well_state,
DeferredLogger& deferred_logger) const;
bool wellUnderZeroGroupRateTarget(const Simulator& simulator,
const WellStateType& well_state,
DeferredLogger& deferred_logger,
std::optional<bool> group_control = std::nullopt) const;
bool stoppedOrZeroRateTarget(const Simulator& simulator,
const WellStateType& well_state,
DeferredLogger& deferred_logger) const;
bool updateWellStateWithTHPTargetProd(const Simulator& simulator,
WellStateType& well_state,
DeferredLogger& deferred_logger) const;
enum class IndividualOrGroup { Individual, Group, Both };
bool updateWellControl(const Simulator& simulator,
const IndividualOrGroup iog,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger) /* const */;
bool updateWellControlAndStatusLocalIteration(const Simulator& simulator,
WellStateType& 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);
virtual void updatePrimaryVariables(const Simulator& simulator,
const WellStateType& well_state,
DeferredLogger& deferred_logger) = 0;
virtual void calculateExplicitQuantities(const Simulator& simulator,
const WellStateType& well_state,
DeferredLogger& deferred_logger) = 0; // should be const?
virtual void updateProductivityIndex(const Simulator& simulator,
const WellProdIndexCalculator<Scalar>& wellPICalc,
WellStateType& well_state,
DeferredLogger& deferred_logger) const = 0;
// Add well contributions to matrix
virtual void addWellContributions(SparseMatrixAdapter&) const = 0;
virtual void addWellPressureEquations(PressureMatrix& mat,
const BVector& x,
const int pressureVarIndex,
const bool use_well_weights,
const WellStateType& well_state) const = 0;
void addCellRates(RateVector& rates, int cellIdx) const;
Scalar volumetricSurfaceRateForConnection(int cellIdx, int phaseIdx) const;
// TODO: theoretically, it should be a const function
// Simulator is not const is because that assembleWellEq is non-const Simulator
void wellTesting(const Simulator& simulator,
const double simulation_time,
/* const */ WellStateType& well_state,
const GroupState<Scalar>& group_state,
WellTestState& welltest_state,
GLiftEclWells& ecl_well_map,
std::map<std::string, double>& open_times,
DeferredLogger& deferred_logger);
void checkWellOperability(const Simulator& simulator,
const WellStateType& well_state,
DeferredLogger& deferred_logger);
void gliftBeginTimeStepWellTestUpdateALQ(const Simulator& simulator,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
GLiftEclWells& ecl_well_map,
DeferredLogger& deferred_logger);
// check whether the well is operable under the current reservoir condition
// mostly related to BHP limit and THP limit
void updateWellOperability(const Simulator& simulator,
const WellStateType& well_state,
DeferredLogger& deferred_logger);
bool updateWellOperabilityFromWellEq(const Simulator& simulator,
const WellStateType& well_state,
DeferredLogger& deferred_logger);
// update perforation water throughput based on solved water rate
virtual void updateWaterThroughput(const double dt,
WellStateType& well_state) const = 0;
virtual std::vector<Scalar>
computeCurrentWellRates(const Simulator& simulator,
DeferredLogger& deferred_logger) const = 0;
void initializeProducerWellState(const Simulator& simulator,
WellStateType& well_state,
DeferredLogger& deferred_logger) const;
void solveWellEquation(const Simulator& simulator,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger);
const std::vector<RateVector>& connectionRates() const
{
return connectionRates_;
}
std::vector<Scalar> wellIndex(const int perf,
const IntensiveQuantities& intQuants,
const Scalar trans_mult,
const SingleWellStateType& ws) const;
void updateConnectionDFactor(const Simulator& simulator,
SingleWellStateType& ws) const;
void updateConnectionTransmissibilityFactor(const Simulator& simulator,
SingleWellStateType& ws) const;
virtual bool iterateWellEqWithSwitching(const Simulator& simulator,
const double dt,
const WellInjectionControls& inj_controls,
const WellProductionControls& prod_controls,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger,
const bool fixed_control = false,
const bool fixed_status = false) = 0;
protected:
// simulation parameters
std::vector<RateVector> connectionRates_;
std::vector<Scalar> B_avg_;
bool changed_to_stopped_this_step_ = false;
bool thp_update_iterations = false;
int number_of_well_reopenings_{0};
Scalar wpolymer() const;
Scalar wfoam() const;
Scalar wsalt() const;
Scalar wmicrobes() const;
Scalar woxygen() const;
Scalar wurea() const;
virtual Scalar getRefDensity() const = 0;
std::vector<Scalar>
initialWellRateFractions(const Simulator& ebosSimulator,
const WellStateType& well_state) const;
// check whether the well is operable under BHP limit with current reservoir condition
virtual void checkOperabilityUnderBHPLimit(const WellStateType& well_state,
const Simulator& simulator,
DeferredLogger& deferred_logger) = 0;
// check whether the well is operable under THP limit with current reservoir condition
virtual void checkOperabilityUnderTHPLimit(const Simulator& simulator,
const WellStateType& well_state,
DeferredLogger& deferred_logger) = 0;
virtual void updateIPR(const Simulator& simulator,
DeferredLogger& deferred_logger) const = 0;
virtual void assembleWellEqWithoutIteration(const Simulator& simulator,
const double dt,
const WellInjectionControls& inj_controls,
const WellProductionControls& prod_controls,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger) = 0;
// iterate well equations with the specified control until converged
virtual bool iterateWellEqWithControl(const Simulator& simulator,
const double dt,
const WellInjectionControls& inj_controls,
const WellProductionControls& prod_controls,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger) = 0;
virtual void updateIPRImplicit(const Simulator& simulator,
WellStateType& well_state,
DeferredLogger& deferred_logger) = 0;
bool iterateWellEquations(const Simulator& simulator,
const double dt,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger);
bool solveWellWithOperabilityCheck(const Simulator& simulator,
const double dt,
const Well::InjectionControls& inj_controls,
const Well::ProductionControls& prod_controls,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger);
std::optional<Scalar>
estimateOperableBhp(const Simulator& ebos_simulator,
const double dt,
WellStateType& well_state,
const SummaryState& summary_state,
DeferredLogger& deferred_logger);
bool solveWellWithBhp(const Simulator& simulator,
const double dt,
const Scalar bhp,
WellStateType& well_state,
DeferredLogger& deferred_logger);
bool solveWellWithZeroRate(const Simulator& simulator,
const double dt,
WellStateType& well_state,
DeferredLogger& deferred_logger);
bool solveWellForTesting(const Simulator& simulator,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
DeferredLogger& deferred_logger);
template<class GasLiftSingleWell>
std::unique_ptr<GasLiftSingleWell> initializeGliftWellTest_(const Simulator& simulator,
WellStateType& well_state,
const GroupState<Scalar>& group_state,
GLiftEclWells& ecl_well_map,
DeferredLogger& deferred_logger);
Eval getPerfCellPressure(const FluidState& fs) const;
// get the mobility for specific perforation
template<class Value, class Callback>
void getMobility(const Simulator& simulator,
const int local_perf_index,
std::vector<Value>& mob,
Callback& extendEval,
[[maybe_unused]] DeferredLogger& deferred_logger) const;
void computeConnLevelProdInd(const FluidState& fs,
const std::function<Scalar(const Scalar)>& connPICalc,
const std::vector<Scalar>& mobility,
Scalar* connPI) const;
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;
Scalar computeConnectionDFactor(const int perf,
const IntensiveQuantities& intQuants,
const SingleWellStateType& ws) const;
};
} // namespace Opm
#include "WellInterface_impl.hpp"
#endif // OPM_WELLINTERFACE_HEADER_INCLUDED
blackoilproperties.hh
Declares the properties required by the black oil model.
Opm::BlackoilWellModel
Class for handling the blackoil well model.
Definition BlackoilWellModel.hpp:102
Opm::ConvergenceReport
Represents the convergence status of the whole simulator, to make it possible to query and store the ...
Definition ConvergenceReport.hpp:38
Opm::DeferredLogger
Definition DeferredLogger.hpp:57
Opm::GasLiftSingleWell
Definition GasLiftSingleWell.hpp:39
Opm::GroupState
Definition GroupState.hpp:41
Opm::ParallelWellInfo
Class encapsulating some information about parallel wells.
Definition ParallelWellInfo.hpp:198
Opm::Simulator
Manages the initializing and running of time dependent problems.
Definition simulator.hh:84
Opm::SingleWellState
Definition SingleWellState.hpp:43
Opm::WellInterfaceFluidSystem
Definition WellInterfaceFluidSystem.hpp:49
Opm::WellInterface::computeCurrentWellRates
virtual std::vector< Scalar > computeCurrentWellRates(const Simulator &simulator, DeferredLogger &deferred_logger) const =0
Compute well rates based on current reservoir conditions and well variables.
Opm::WellInterface::apply
virtual void apply(const BVector &x, BVector &Ax) const =0
Ax = Ax - C D^-1 B x.
Opm::WellInterface::initializeProducerWellState
void initializeProducerWellState(const Simulator &simulator, WellStateType &well_state, DeferredLogger &deferred_logger) const
Modify the well_state's rates if there is only one nonzero rate.
Definition WellInterface_impl.hpp:1686
Opm::WellInterface::apply
virtual void apply(BVector &r) const =0
r = r - C D^-1 Rw
Opm::WellInterface::~WellInterface
virtual ~WellInterface()=default
Virtual destructor.
Opm::WellInterface::recoverWellSolutionAndUpdateWellState
virtual void recoverWellSolutionAndUpdateWellState(const Simulator &simulator, const BVector &x, WellStateType &well_state, DeferredLogger &deferred_logger)=0
using the solution x to recover the solution xw for wells and applying xw to update Well State
Opm::WellInterface::WellInterface
WellInterface(const Well &well, const ParallelWellInfo< Scalar > &pw_info, const int time_step, const ModelParameters &param, const RateConverterType &rate_converter, const int pvtRegionIdx, const int num_conservation_quantities, const int num_phases, const int index_of_well, const std::vector< PerforationData< Scalar > > &perf_data)
Constructor.
Definition WellInterface_impl.hpp:58
Opm::WellProdIndexCalculator
Collect per-connection static information to enable calculating connection-level or well-level produc...
Definition WellProdIndexCalculator.hpp:37
Opm::WellState
The state of a set of wells, tailored for use by the fully implicit blackoil simulator.
Definition WellState.hpp:66
linalgproperties.hh
Declares the properties required by the black oil model.
Opm
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition blackoilbioeffectsmodules.hh:43
Opm::GetPropType
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition propertysystem.hh:233
Opm::getPropValue
constexpr auto getPropValue()
get the value data member of a property
Definition propertysystem.hh:240
Opm::PerforationData
Static data associated with a well perforation.
Definition PerforationData.hpp:30