/*
Copyright 2016 SINTEF ICT, Applied Mathematics.
Copyright 2016 - 2017 Statoil ASA.
Copyright 2017 Dr. Blatt - HPC-Simulation-Software & Services
Copyright 2016 - 2017 IRIS AS
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 .
*/
#ifndef OPM_STANDARDWELLSDENSE_HEADER_INCLUDED
#define OPM_STANDARDWELLSDENSE_HEADER_INCLUDED
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace Opm {
/// Class for handling the standard well model.
template
class StandardWellsDense {
public:
// --------- Types ---------
typedef WellStateFullyImplicitBlackoilDense WellState;
typedef BlackoilModelParameters ModelParameters;
typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid;
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
typedef typename GET_PROP_TYPE(TypeTag, ElementContext) ElementContext;
typedef typename GET_PROP_TYPE(TypeTag, Indices) BlackoilIndices;
typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
static const int numEq = BlackoilIndices::numEq;
static const int solventSaturationIdx = BlackoilIndices::solventSaturationIdx;
// TODO: where we should put these types, WellInterface or Well Model?
// or there is some other strategy, like TypeTag
typedef Dune::FieldVector VectorBlockType;
typedef Dune::BlockVector BVector;
typedef Ewoms::BlackOilPolymerModule PolymerModule;
// For the conversion between the surface volume rate and resrevoir voidage rate
using RateConverterType = RateConverter::
SurfaceToReservoirVoidage >;
// --------- Public methods ---------
StandardWellsDense(const Wells* wells_arg,
WellCollection* well_collection,
const std::vector< const Well* >& wells_ecl,
const ModelParameters& param,
const RateConverterType& rate_converter,
const bool terminal_output,
const int current_index);
void init(const PhaseUsage phase_usage_arg,
const std::vector& active_arg,
const double gravity_arg,
const std::vector& depth_arg,
const std::vector& pv_arg,
long int global_nc,
const Grid& grid);
void setVFPProperties(const VFPProperties* vfp_properties_arg);
/// The number of components in the model.
int numComponents() const
{
if (numPhases() == 2) {
return 2;
}
int numComp = FluidSystem::numComponents;
if (has_solvent_) {
numComp ++;
}
return numComp;
}
SimulatorReport assemble(Simulator& ebosSimulator,
const int iterationIdx,
const double dt,
WellState& well_state);
void assembleWellEq(Simulator& ebosSimulator,
const double dt,
WellState& well_state,
bool only_wells);
// substract Binv(D)rw from r;
void apply( BVector& r) const;
// subtract B*inv(D)*C * x from A*x
void apply(const BVector& x, BVector& Ax) const;
// apply well model with scaling of alpha
void applyScaleAdd(const Scalar alpha, const BVector& x, BVector& Ax) const;
// using the solution x to recover the solution xw for wells and applying
// xw to update Well State
void applySolutionWellState(const BVector& x, WellState& well_state) const;
int flowToEbosPvIdx( const int flowPv ) const;
int flowPhaseToEbosPhaseIdx( const int phaseIdx ) const;
int numPhases() const;
int numCells() const;
void resetWellControlFromState(const WellState& xw) const;
const Wells& wells() const;
const Wells* wellsPointer() const;
/// return true if wells are available in the reservoir
bool wellsActive() const;
void setWellsActive(const bool wells_active);
/// return true if wells are available on this process
bool localWellsActive() const;
void setWellVariables();
void computeAccumWells();
SimulatorReport solveWellEq(Simulator& ebosSimulator,
const double dt,
WellState& well_state);
void printIf(const int c, const double x, const double y, const double eps, const std::string type) const;
std::vector residual() const;
bool getWellConvergence(Simulator& ebosSimulator,
const std::vector& B_avg) const;
void computeWellConnectionPressures(const Simulator& ebosSimulator,
const WellState& xw);
void updateWellControls(WellState& xw) const;
/// upate the dynamic lists related to economic limits
void updateListEconLimited(const Schedule& schedule,
const int current_step,
const Wells* wells_struct,
const WellState& well_state,
DynamicListEconLimited& list_econ_limited) const;
// Calculating well potentials for each well
// TODO: getBhp() will be refactored to reduce the duplication of the code calculating the bhp from THP.
void computeWellPotentials(const Simulator& ebosSimulator,
const WellState& well_state,
std::vector& well_potentials) const;
// TODO: some preparation work, mostly related to group control and RESV,
// at the beginning of each time step (Not report step)
void prepareTimeStep(const Simulator& ebos_simulator,
WellState& well_state);
WellCollection* wellCollection() const;
const std::vector&
wellPerfEfficiencyFactors() const;
void calculateEfficiencyFactors();
void computeWellVoidageRates(const WellState& well_state,
std::vector& well_voidage_rates,
std::vector& voidage_conversion_coeffs) const;
void applyVREPGroupControl(WellState& well_state) const;
void updateGroupControls(WellState& well_state) const;
/// setting the well_solutions_ based on well_state.
void setWellSolutions(const WellState& well_state) const;
protected:
bool wells_active_;
const Wells* wells_;
const std::vector< const Well* > wells_ecl_;
// the number of wells in this process
// trying not to use things from Wells struct
// TODO: maybe a better name to emphasize it is local?
const int number_of_wells_;
const int number_of_phases_;
// a vector of all the wells.
// eventually, the wells_ above should be gone.
// the name is just temporary
// later, might make share_ptr const later.
// TODO: forget why make it share_ptr instead of unique_ptr
std::vector > > well_container_;
// TODO: forgot why returning a vector here
void createWellContainer(const Wells* wells_arg);
// Well collection is used to enforce the group control
WellCollection* well_collection_;
ModelParameters param_;
bool terminal_output_;
bool has_solvent_;
bool has_polymer_;
int current_timeIdx_;
PhaseUsage phase_usage_;
std::vector active_;
const RateConverterType& rate_converter_;
std::vector pv_;
std::vector wells_rep_radius_;
std::vector wells_perf_length_;
std::vector wells_bore_diameter_;
long int global_nc_;
mutable BVector scaleAddRes_;
void setupCompressedToCartesian(const int* global_cell, int number_of_cells, std::map& cartesian_to_compressed ) const;
void computeRepRadiusPerfLength(const Grid& grid);
void computeAverageFormationFactor(Simulator& ebosSimulator,
std::vector& B_avg) const;
};
} // namespace Opm
#include "StandardWellsDense_impl.hpp"
#endif