2013-05-23 11:28:50 -05:00
|
|
|
/*
|
2015-05-24 02:59:40 -05:00
|
|
|
Copyright 2013, 2015 SINTEF ICT, Applied Mathematics.
|
|
|
|
Copyright 2014, 2015 Statoil ASA.
|
2015-05-20 02:26:25 -05:00
|
|
|
Copyright 2014, 2015 Dr. Markus Blatt - HPC-Simulation-Software & Services
|
|
|
|
Copyright 2015 NTNU
|
2013-05-23 11:28:50 -05:00
|
|
|
|
2013-05-24 03:49:59 -05:00
|
|
|
This file is part of the Open Porous Media project (OPM).
|
2013-05-23 11:28:50 -05:00
|
|
|
|
|
|
|
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/>.
|
|
|
|
*/
|
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
#ifndef OPM_BLACKOILMODELBASE_HEADER_INCLUDED
|
|
|
|
#define OPM_BLACKOILMODELBASE_HEADER_INCLUDED
|
2013-05-23 11:28:50 -05:00
|
|
|
|
2015-01-20 05:55:46 -06:00
|
|
|
#include <cassert>
|
|
|
|
|
2013-05-23 11:28:50 -05:00
|
|
|
#include <opm/autodiff/AutoDiffBlock.hpp>
|
|
|
|
#include <opm/autodiff/AutoDiffHelpers.hpp>
|
|
|
|
#include <opm/autodiff/BlackoilPropsAdInterface.hpp>
|
2014-04-08 08:56:08 -05:00
|
|
|
#include <opm/autodiff/LinearisedBlackoilResidual.hpp>
|
2014-04-08 09:11:08 -05:00
|
|
|
#include <opm/autodiff/NewtonIterationBlackoilInterface.hpp>
|
2015-05-25 16:06:03 -05:00
|
|
|
#include <opm/autodiff/BlackoilModelEnums.hpp>
|
2015-08-19 04:46:29 -05:00
|
|
|
#include <opm/autodiff/VFPProperties.hpp>
|
2016-10-19 09:18:41 -05:00
|
|
|
#include <opm/autodiff/RateConverter.hpp>
|
2015-06-10 02:25:45 -05:00
|
|
|
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
|
2016-07-05 05:20:19 -05:00
|
|
|
#include <opm/core/simulator/SimulatorTimerInterface.hpp>
|
2013-05-23 11:28:50 -05:00
|
|
|
|
2015-01-20 07:21:45 -06:00
|
|
|
#include <array>
|
|
|
|
|
2013-05-24 04:00:55 -05:00
|
|
|
struct Wells;
|
|
|
|
|
2013-05-23 11:28:50 -05:00
|
|
|
namespace Opm {
|
|
|
|
|
2014-05-16 11:02:55 -05:00
|
|
|
namespace parameter { class ParameterGroup; }
|
2013-05-24 04:00:55 -05:00
|
|
|
class DerivedGeology;
|
2013-06-03 07:14:48 -05:00
|
|
|
class RockCompressibility;
|
2014-04-08 09:11:08 -05:00
|
|
|
class NewtonIterationBlackoilInterface;
|
2015-07-03 05:16:50 -05:00
|
|
|
class VFPProperties;
|
2016-02-28 04:27:00 -06:00
|
|
|
class SimulationDataContainer;
|
2015-05-24 17:46:28 -05:00
|
|
|
|
|
|
|
/// Struct for containing iteration variables.
|
|
|
|
struct DefaultBlackoilSolutionState
|
|
|
|
{
|
|
|
|
typedef AutoDiffBlock<double> ADB;
|
|
|
|
explicit DefaultBlackoilSolutionState(const int np)
|
|
|
|
: pressure ( ADB::null())
|
|
|
|
, temperature( ADB::null())
|
|
|
|
, saturation(np, ADB::null())
|
|
|
|
, rs ( ADB::null())
|
|
|
|
, rv ( ADB::null())
|
|
|
|
, qs ( ADB::null())
|
|
|
|
, bhp ( ADB::null())
|
|
|
|
, canonical_phase_pressures(3, ADB::null())
|
|
|
|
{
|
|
|
|
}
|
|
|
|
ADB pressure;
|
|
|
|
ADB temperature;
|
|
|
|
std::vector<ADB> saturation;
|
|
|
|
ADB rs;
|
|
|
|
ADB rv;
|
|
|
|
ADB qs;
|
|
|
|
ADB bhp;
|
|
|
|
// Below are quantities stored in the state for optimization purposes.
|
|
|
|
std::vector<ADB> canonical_phase_pressures; // Always has 3 elements, even if only 2 phases active.
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-05-24 04:00:55 -05:00
|
|
|
|
2013-05-24 04:14:05 -05:00
|
|
|
|
2015-10-02 06:51:40 -05:00
|
|
|
/// Class used for reporting the outcome of a nonlinearIteration() call.
|
|
|
|
struct IterationReport
|
|
|
|
{
|
|
|
|
bool failed;
|
|
|
|
bool converged;
|
|
|
|
int linear_iterations;
|
2016-06-20 03:25:35 -05:00
|
|
|
int well_iterations;
|
2015-10-02 06:51:40 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-05-24 10:36:29 -05:00
|
|
|
/// Traits to encapsulate the types used by classes using or
|
|
|
|
/// extending this model. Forward declared here, must be
|
|
|
|
/// specialised for each concrete model class.
|
|
|
|
template <class ConcreteModel>
|
|
|
|
struct ModelTraits;
|
|
|
|
|
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
/// A model implementation for three-phase black oil.
|
2013-09-20 07:55:43 -05:00
|
|
|
///
|
|
|
|
/// The simulator is capable of handling three-phase problems
|
2015-05-24 02:59:40 -05:00
|
|
|
/// where gas can be dissolved in oil and vice versa. It
|
2013-09-20 07:55:43 -05:00
|
|
|
/// uses an industry-standard TPFA discretization with per-phase
|
|
|
|
/// upwind weighting of mobilities.
|
|
|
|
///
|
|
|
|
/// It uses automatic differentiation via the class AutoDiffBlock
|
|
|
|
/// to simplify assembly of the jacobian matrix.
|
2015-05-24 10:36:29 -05:00
|
|
|
/// \tparam Grid UnstructuredGrid or CpGrid.
|
2016-04-18 09:06:05 -05:00
|
|
|
/// \tparam WellModel WellModel employed.
|
2015-05-24 10:36:29 -05:00
|
|
|
/// \tparam Implementation Provides concrete state types.
|
2016-04-18 08:32:47 -05:00
|
|
|
template<class Grid, class WellModel, class Implementation>
|
2015-05-24 02:59:40 -05:00
|
|
|
class BlackoilModelBase
|
2013-05-24 04:00:55 -05:00
|
|
|
{
|
2013-05-23 11:28:50 -05:00
|
|
|
public:
|
2015-05-24 02:59:40 -05:00
|
|
|
// --------- Types and enums ---------
|
|
|
|
typedef AutoDiffBlock<double> ADB;
|
|
|
|
typedef ADB::V V;
|
|
|
|
typedef ADB::M M;
|
2015-05-24 10:36:29 -05:00
|
|
|
|
2016-09-02 02:38:25 -05:00
|
|
|
struct ReservoirResidualQuant {
|
|
|
|
ReservoirResidualQuant();
|
|
|
|
std::vector<ADB> accum; // Accumulations
|
|
|
|
ADB mflux; // Mass flux (surface conditions)
|
|
|
|
ADB b; // Reciprocal FVF
|
|
|
|
ADB mu; // Viscosities
|
|
|
|
ADB rho; // Densities
|
|
|
|
ADB kr; // Permeabilities
|
|
|
|
ADB dh; // Pressure drop across int. interfaces
|
|
|
|
ADB mob; // Phase mobility (per cell)
|
|
|
|
};
|
|
|
|
|
2016-09-02 07:15:10 -05:00
|
|
|
struct SimulatorData {
|
|
|
|
SimulatorData(int num_phases);
|
2016-09-26 07:17:52 -05:00
|
|
|
|
|
|
|
enum FipId {
|
2016-11-01 06:56:05 -05:00
|
|
|
FIP_AQUA = Opm::Water,
|
|
|
|
FIP_LIQUID = Opm::Oil,
|
|
|
|
FIP_VAPOUR = Opm::Gas,
|
2016-09-26 07:17:52 -05:00
|
|
|
FIP_DISSOLVED_GAS = 3,
|
|
|
|
FIP_VAPORIZED_OIL = 4,
|
|
|
|
FIP_PV = 5, //< Pore volume
|
|
|
|
FIP_WEIGHTED_PRESSURE = 6
|
|
|
|
};
|
2016-09-02 07:15:10 -05:00
|
|
|
std::vector<ReservoirResidualQuant> rq;
|
2016-09-26 07:17:52 -05:00
|
|
|
ADB rsSat; // Saturated gas-oil ratio
|
|
|
|
ADB rvSat; // Saturated oil-gas ratio
|
|
|
|
std::array<V, 7> fip;
|
2016-09-02 07:15:10 -05:00
|
|
|
};
|
|
|
|
|
2015-05-24 10:36:29 -05:00
|
|
|
typedef typename ModelTraits<Implementation>::ReservoirState ReservoirState;
|
|
|
|
typedef typename ModelTraits<Implementation>::WellState WellState;
|
|
|
|
typedef typename ModelTraits<Implementation>::ModelParameters ModelParameters;
|
2015-05-24 17:46:28 -05:00
|
|
|
typedef typename ModelTraits<Implementation>::SolutionState SolutionState;
|
2014-10-01 05:48:41 -05:00
|
|
|
|
2016-10-19 09:18:41 -05:00
|
|
|
// for the conversion between the surface volume rate and resrevoir voidage rate
|
|
|
|
// Due to the requirement of the grid information, put the converter in the model.
|
|
|
|
using RateConverterType = RateConverter::
|
|
|
|
SurfaceToReservoirVoidage<BlackoilPropsAdInterface, std::vector<int> >;
|
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
// --------- Public methods ---------
|
|
|
|
|
|
|
|
/// Construct the model. It will retain references to the
|
2013-09-20 07:55:43 -05:00
|
|
|
/// arguments of this functions, and they are expected to
|
|
|
|
/// remain in scope for the lifetime of the solver.
|
2014-10-01 05:48:41 -05:00
|
|
|
/// \param[in] param parameters
|
2013-09-20 07:55:43 -05:00
|
|
|
/// \param[in] grid grid data structure
|
|
|
|
/// \param[in] fluid fluid properties
|
|
|
|
/// \param[in] geo rock properties
|
|
|
|
/// \param[in] rock_comp_props if non-null, rock compressibility properties
|
|
|
|
/// \param[in] wells well structure
|
2015-07-03 05:16:50 -05:00
|
|
|
/// \param[in] vfp_properties Vertical flow performance tables
|
2013-09-20 07:55:43 -05:00
|
|
|
/// \param[in] linsolver linear solver
|
2015-06-10 02:25:45 -05:00
|
|
|
/// \param[in] eclState eclipse state
|
2015-05-24 02:59:40 -05:00
|
|
|
/// \param[in] has_disgas turn on dissolved gas
|
|
|
|
/// \param[in] has_vapoil turn on vaporized oil feature
|
|
|
|
/// \param[in] terminal_output request output to cout/cerr
|
|
|
|
BlackoilModelBase(const ModelParameters& param,
|
|
|
|
const Grid& grid ,
|
|
|
|
const BlackoilPropsAdInterface& fluid,
|
|
|
|
const DerivedGeology& geo ,
|
|
|
|
const RockCompressibility* rock_comp_props,
|
2016-05-09 10:44:59 -05:00
|
|
|
const WellModel& well_model,
|
2015-05-24 02:59:40 -05:00
|
|
|
const NewtonIterationBlackoilInterface& linsolver,
|
2016-10-14 02:23:26 -05:00
|
|
|
std::shared_ptr< const EclipseState > eclState,
|
2015-05-24 02:59:40 -05:00
|
|
|
const bool has_disgas,
|
|
|
|
const bool has_vapoil,
|
|
|
|
const bool terminal_output);
|
2013-05-23 11:28:50 -05:00
|
|
|
|
2014-08-27 04:30:42 -05:00
|
|
|
/// \brief Set threshold pressures that prevent or reduce flow.
|
|
|
|
/// This prevents flow across faces if the potential
|
|
|
|
/// difference is less than the threshold. If the potential
|
|
|
|
/// difference is greater, the threshold value is subtracted
|
|
|
|
/// before calculating flow. This is treated symmetrically, so
|
|
|
|
/// flow is prevented or reduced in both directions equally.
|
2014-08-27 07:21:34 -05:00
|
|
|
/// \param[in] threshold_pressures_by_face array of size equal to the number of faces
|
2014-08-27 04:30:42 -05:00
|
|
|
/// of the grid passed in the constructor.
|
2014-08-27 07:21:34 -05:00
|
|
|
void setThresholdPressures(const std::vector<double>& threshold_pressures_by_face);
|
2014-08-27 04:30:42 -05:00
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
/// Called once before each time step.
|
2016-07-05 05:20:19 -05:00
|
|
|
/// \param[in] timer simulation timer
|
2015-05-24 02:59:40 -05:00
|
|
|
/// \param[in, out] reservoir_state reservoir state variables
|
|
|
|
/// \param[in, out] well_state well state variables
|
2016-07-05 05:20:19 -05:00
|
|
|
void prepareStep(const SimulatorTimerInterface& timer,
|
2016-01-15 04:28:15 -06:00
|
|
|
const ReservoirState& reservoir_state,
|
|
|
|
const WellState& well_state);
|
2015-05-24 02:59:40 -05:00
|
|
|
|
2015-10-02 06:51:40 -05:00
|
|
|
/// Called once per nonlinear iteration.
|
|
|
|
/// This model will perform a Newton-Raphson update, changing reservoir_state
|
|
|
|
/// and well_state. It will also use the nonlinear_solver to do relaxation of
|
|
|
|
/// updates if necessary.
|
|
|
|
/// \param[in] iteration should be 0 for the first call of a new timestep
|
2016-07-05 05:20:19 -05:00
|
|
|
/// \param[in] timer simulation timer
|
2015-10-02 06:51:40 -05:00
|
|
|
/// \param[in] nonlinear_solver nonlinear solver used (for oscillation/relaxation control)
|
|
|
|
/// \param[in, out] reservoir_state reservoir state variables
|
|
|
|
/// \param[in, out] well_state well state variables
|
|
|
|
template <class NonlinearSolverType>
|
|
|
|
IterationReport nonlinearIteration(const int iteration,
|
2016-07-05 05:20:19 -05:00
|
|
|
const SimulatorTimerInterface& timer,
|
2015-10-02 06:51:40 -05:00
|
|
|
NonlinearSolverType& nonlinear_solver,
|
|
|
|
ReservoirState& reservoir_state,
|
|
|
|
WellState& well_state);
|
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
/// Called once after each time step.
|
|
|
|
/// In this class, this function does nothing.
|
2016-07-05 05:20:19 -05:00
|
|
|
/// \param[in] timer simulation timer
|
2015-05-24 02:59:40 -05:00
|
|
|
/// \param[in, out] reservoir_state reservoir state variables
|
|
|
|
/// \param[in, out] well_state well state variables
|
2016-07-05 05:20:19 -05:00
|
|
|
void afterStep(const SimulatorTimerInterface& timer,
|
2015-05-24 02:59:40 -05:00
|
|
|
ReservoirState& reservoir_state,
|
|
|
|
WellState& well_state);
|
|
|
|
|
|
|
|
/// Assemble the residual and Jacobian of the nonlinear system.
|
|
|
|
/// \param[in] reservoir_state reservoir state variables
|
|
|
|
/// \param[in, out] well_state well state variables
|
|
|
|
/// \param[in] initial_assembly pass true if this is the first call to assemble() in this timestep
|
2016-06-20 03:25:35 -05:00
|
|
|
/// \return well iterations.
|
2016-06-28 01:37:48 -05:00
|
|
|
IterationReport
|
|
|
|
assemble(const ReservoirState& reservoir_state,
|
|
|
|
WellState& well_state,
|
|
|
|
const bool initial_assembly);
|
2015-05-24 02:59:40 -05:00
|
|
|
|
|
|
|
/// \brief Compute the residual norms of the mass balance for each phase,
|
|
|
|
/// the well flux, and the well equation.
|
|
|
|
/// \return a vector that contains for each phase the norm of the mass balance
|
|
|
|
/// and afterwards the norm of the residual of the well flux and the well equation.
|
|
|
|
std::vector<double> computeResidualNorms() const;
|
|
|
|
|
2015-10-31 06:32:54 -05:00
|
|
|
/// \brief compute the relative change between to simulation states
|
|
|
|
// \return || u^n+1 - u^n || / || u^n+1 ||
|
2016-02-28 04:27:00 -06:00
|
|
|
double relativeChange( const SimulationDataContainer& previous, const SimulationDataContainer& current ) const;
|
2015-10-31 06:32:54 -05:00
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
/// The size (number of unknowns) of the nonlinear system of equations.
|
|
|
|
int sizeNonLinear() const;
|
|
|
|
|
|
|
|
/// Number of linear iterations used in last call to solveJacobianSystem().
|
|
|
|
int linearIterationsLastSolve() const;
|
|
|
|
|
|
|
|
/// Solve the Jacobian system Jx = r where J is the Jacobian and
|
|
|
|
/// r is the residual.
|
|
|
|
V solveJacobianSystem() const;
|
|
|
|
|
|
|
|
/// Apply an update to the primary variables, chopped if appropriate.
|
|
|
|
/// \param[in] dx updates to apply to primary variables
|
|
|
|
/// \param[in, out] reservoir_state reservoir state variables
|
|
|
|
/// \param[in, out] well_state well state variables
|
|
|
|
void updateState(const V& dx,
|
2015-05-25 16:49:09 -05:00
|
|
|
ReservoirState& reservoir_state,
|
|
|
|
WellState& well_state);
|
2015-05-24 02:59:40 -05:00
|
|
|
|
2016-09-15 08:43:08 -05:00
|
|
|
/// Return true if this is a parallel run.
|
|
|
|
bool isParallel() const;
|
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
/// Return true if output to cout is wanted.
|
|
|
|
bool terminalOutputEnabled() const;
|
|
|
|
|
|
|
|
/// Compute convergence based on total mass balance (tol_mb) and maximum
|
|
|
|
/// residual mass balance (tol_cnv).
|
2016-07-05 05:20:19 -05:00
|
|
|
/// \param[in] timer simulation timer
|
2015-05-24 02:59:40 -05:00
|
|
|
/// \param[in] iteration current iteration number
|
2016-07-05 05:20:19 -05:00
|
|
|
bool getConvergence(const SimulatorTimerInterface& timer, const int iteration);
|
2015-05-24 02:59:40 -05:00
|
|
|
|
2015-09-30 07:44:50 -05:00
|
|
|
/// The number of active fluid phases in the model.
|
2015-05-24 02:59:40 -05:00
|
|
|
int numPhases() const;
|
2015-03-04 08:02:00 -06:00
|
|
|
|
2015-09-30 07:44:50 -05:00
|
|
|
/// The number of active materials in the model.
|
|
|
|
/// This should be equal to the number of material balance
|
|
|
|
/// equations.
|
|
|
|
int numMaterials() const;
|
|
|
|
|
|
|
|
/// The name of an active material in the model.
|
|
|
|
/// It is required that material_index < numMaterials().
|
|
|
|
const std::string& materialName(int material_index) const;
|
2015-09-30 05:48:16 -05:00
|
|
|
|
2015-08-27 09:58:44 -05:00
|
|
|
/// Update the scaling factors for mass balance equations
|
|
|
|
void updateEquationsScaling();
|
|
|
|
|
2016-06-27 09:14:28 -05:00
|
|
|
/// return the WellModel object
|
|
|
|
WellModel& wellModel() { return well_model_; }
|
|
|
|
const WellModel& wellModel() const { return well_model_; }
|
|
|
|
|
2016-09-02 07:15:10 -05:00
|
|
|
/// Return reservoir simulation data (for output functionality)
|
|
|
|
const SimulatorData& getSimulatorData() const {
|
|
|
|
return sd_;
|
|
|
|
}
|
|
|
|
|
2016-08-09 02:30:25 -05:00
|
|
|
/// Compute fluid in place.
|
|
|
|
/// \param[in] ReservoirState
|
|
|
|
/// \param[in] FIPNUM for active cells not global cells.
|
|
|
|
/// \return fluid in place, number of fip regions, each region contains 5 values which are liquid, vapour, water, free gas and dissolved gas.
|
2016-07-18 20:33:03 -05:00
|
|
|
std::vector<V>
|
|
|
|
computeFluidInPlace(const ReservoirState& x,
|
|
|
|
const std::vector<int>& fipnum);
|
2016-07-17 19:50:50 -05:00
|
|
|
|
2016-10-20 13:10:07 -05:00
|
|
|
/// Function to compute the resevoir voidage for the production wells.
|
|
|
|
/// TODO: it is just prototyping, and not sure where is the best place to
|
|
|
|
/// put this function yet.
|
|
|
|
void computeWellVoidageRates(const ReservoirState& reservoir_state,
|
|
|
|
const WellState& well_state,
|
|
|
|
std::vector<double>& well_voidage_rates,
|
|
|
|
std::vector<double>& voidage_conversion_coeffs);
|
|
|
|
|
2015-05-24 10:36:29 -05:00
|
|
|
protected:
|
2015-05-24 02:59:40 -05:00
|
|
|
|
|
|
|
// --------- Types and enums ---------
|
|
|
|
|
2013-05-23 11:28:50 -05:00
|
|
|
typedef Eigen::Array<double,
|
|
|
|
Eigen::Dynamic,
|
|
|
|
Eigen::Dynamic,
|
|
|
|
Eigen::RowMajor> DataBlock;
|
|
|
|
|
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
// --------- Data members ---------
|
|
|
|
|
2014-02-20 06:17:18 -06:00
|
|
|
const Grid& grid_;
|
2013-05-23 11:28:50 -05:00
|
|
|
const BlackoilPropsAdInterface& fluid_;
|
2013-05-24 04:00:55 -05:00
|
|
|
const DerivedGeology& geo_;
|
2013-06-03 07:14:48 -05:00
|
|
|
const RockCompressibility* rock_comp_props_;
|
2015-08-19 04:46:29 -05:00
|
|
|
VFPProperties vfp_properties_;
|
2014-04-08 09:11:08 -05:00
|
|
|
const NewtonIterationBlackoilInterface& linsolver_;
|
2013-05-24 03:39:10 -05:00
|
|
|
// For each canonical phase -> true if active
|
|
|
|
const std::vector<bool> active_;
|
2014-06-03 03:59:50 -05:00
|
|
|
// Size = # active phases. Maps active -> canonical phase indices.
|
2013-05-24 03:39:10 -05:00
|
|
|
const std::vector<int> canph_;
|
2013-05-23 11:28:50 -05:00
|
|
|
const std::vector<int> cells_; // All grid cells
|
|
|
|
HelperOps ops_;
|
2014-05-27 06:36:22 -05:00
|
|
|
const bool has_disgas_;
|
|
|
|
const bool has_vapoil_;
|
2014-10-01 05:48:41 -05:00
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
ModelParameters param_;
|
2014-08-27 03:27:49 -05:00
|
|
|
bool use_threshold_pressure_;
|
2015-12-08 03:56:42 -06:00
|
|
|
V threshold_pressures_by_connection_;
|
2013-05-23 11:28:50 -05:00
|
|
|
|
2016-09-14 08:41:47 -05:00
|
|
|
mutable SimulatorData sd_;
|
2014-01-10 07:19:37 -06:00
|
|
|
std::vector<PhasePresence> phaseCondition_;
|
2016-04-28 09:20:18 -05:00
|
|
|
|
|
|
|
// Well Model
|
2016-05-10 04:40:43 -05:00
|
|
|
WellModel well_model_;
|
2016-04-28 09:20:18 -05:00
|
|
|
|
2015-05-26 07:38:25 -05:00
|
|
|
V isRs_;
|
|
|
|
V isRv_;
|
|
|
|
V isSg_;
|
2013-05-23 11:28:50 -05:00
|
|
|
|
2014-04-08 08:56:08 -05:00
|
|
|
LinearisedBlackoilResidual residual_;
|
2013-05-23 11:28:50 -05:00
|
|
|
|
2015-02-20 09:03:08 -06:00
|
|
|
/// \brief Whether we print something to std::cout
|
2015-02-20 09:02:06 -06:00
|
|
|
bool terminal_output_;
|
2015-10-26 18:29:22 -05:00
|
|
|
/// \brief The number of cells of the global grid.
|
|
|
|
int global_nc_;
|
2015-02-20 04:35:47 -06:00
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
V pvdt_;
|
2015-09-30 07:44:50 -05:00
|
|
|
std::vector<std::string> material_name_;
|
2015-10-02 06:51:40 -05:00
|
|
|
std::vector<std::vector<double>> residual_norms_history_;
|
|
|
|
double current_relaxation_;
|
|
|
|
V dx_old_;
|
2014-05-27 08:09:58 -05:00
|
|
|
|
2016-10-19 09:18:41 -05:00
|
|
|
// rate converter between the surface volume rates and reservoir voidage rates
|
|
|
|
RateConverterType rate_converter_;
|
|
|
|
|
2015-05-24 10:36:29 -05:00
|
|
|
// --------- Protected methods ---------
|
2015-01-19 07:14:18 -06:00
|
|
|
|
2015-05-25 18:48:45 -05:00
|
|
|
/// Access the most-derived class used for
|
|
|
|
/// static polymorphism (CRTP).
|
|
|
|
Implementation& asImpl()
|
|
|
|
{
|
|
|
|
return static_cast<Implementation&>(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Access the most-derived class used for
|
|
|
|
/// static polymorphism (CRTP).
|
|
|
|
const Implementation& asImpl() const
|
|
|
|
{
|
|
|
|
return static_cast<const Implementation&>(*this);
|
|
|
|
}
|
|
|
|
|
2016-04-18 05:14:01 -05:00
|
|
|
/// return the Well struct in the WellModel
|
2016-05-10 04:40:43 -05:00
|
|
|
const Wells& wells() const { return well_model_.wells(); }
|
2016-04-06 05:52:54 -05:00
|
|
|
|
|
|
|
/// return true if wells are available in the reservoir
|
2016-05-10 04:40:43 -05:00
|
|
|
bool wellsActive() const { return well_model_.wellsActive(); }
|
2016-04-06 05:52:54 -05:00
|
|
|
|
|
|
|
/// return true if wells are available on this process
|
2016-05-10 04:40:43 -05:00
|
|
|
bool localWellsActive() const { return well_model_.localWellsActive(); }
|
2016-04-06 05:52:54 -05:00
|
|
|
|
2015-03-06 06:05:37 -06:00
|
|
|
void
|
|
|
|
makeConstantState(SolutionState& state) const;
|
2013-05-23 11:28:50 -05:00
|
|
|
|
|
|
|
SolutionState
|
2015-05-25 16:49:09 -05:00
|
|
|
variableState(const ReservoirState& x,
|
|
|
|
const WellState& xw) const;
|
2013-05-23 11:28:50 -05:00
|
|
|
|
2015-05-26 04:16:21 -05:00
|
|
|
std::vector<V>
|
|
|
|
variableStateInitials(const ReservoirState& x,
|
|
|
|
const WellState& xw) const;
|
2015-06-11 01:03:28 -05:00
|
|
|
void
|
|
|
|
variableReservoirStateInitials(const ReservoirState& x,
|
|
|
|
std::vector<V>& vars0) const;
|
2015-05-26 04:16:21 -05:00
|
|
|
|
|
|
|
std::vector<int>
|
|
|
|
variableStateIndices() const;
|
2015-06-11 01:03:28 -05:00
|
|
|
|
2015-05-26 04:16:21 -05:00
|
|
|
SolutionState
|
|
|
|
variableStateExtractVars(const ReservoirState& x,
|
|
|
|
const std::vector<int>& indices,
|
|
|
|
std::vector<ADB>& vars) const;
|
|
|
|
|
2013-05-23 11:28:50 -05:00
|
|
|
void
|
|
|
|
computeAccum(const SolutionState& state,
|
2013-05-24 04:14:05 -05:00
|
|
|
const int aix );
|
2013-05-23 11:28:50 -05:00
|
|
|
|
2015-05-25 17:31:50 -05:00
|
|
|
void
|
|
|
|
assembleMassBalanceEq(const SolutionState& state);
|
|
|
|
|
2016-04-12 07:00:22 -05:00
|
|
|
|
2016-06-28 01:37:48 -05:00
|
|
|
IterationReport
|
2015-06-11 23:49:25 -05:00
|
|
|
solveWellEq(const std::vector<ADB>& mob_perfcells,
|
|
|
|
const std::vector<ADB>& b_perfcells,
|
2016-10-20 13:10:07 -05:00
|
|
|
const ReservoirState& reservoir_state,
|
2015-06-11 23:49:25 -05:00
|
|
|
SolutionState& state,
|
2016-06-28 01:37:48 -05:00
|
|
|
WellState& well_state);
|
2015-06-11 23:49:25 -05:00
|
|
|
|
2016-04-19 10:09:50 -05:00
|
|
|
void
|
Refactor addWellEq().
The method has been split in three parts:
computeWellFlux(const SolutionState& state,
const std::vector<ADB>& mob_perfcells,
const std::vector<ADB>& b_perfcells,
V& aliveWells,
std::vector<ADB>& cq_s);
void
updatePerfPhaseRatesAndPressures(const std::vector<ADB>& cq_s,
const SolutionState& state,
WellState& xw);
void
addWellFluxEq(const std::vector<ADB>& cq_s,
const SolutionState& state);
This reduces the function length, although most of the content of addWellEq()
now is in computeWellFlux(), so that function is still quite long. It also
allows us to use smaller sets of function arguments, which makes methods easier
to understand.
Finally, it makes it easier to create derived models with custom behaviour.
2015-06-22 04:34:10 -05:00
|
|
|
addWellContributionToMassBalanceEq(const std::vector<ADB>& cq_s,
|
|
|
|
const SolutionState& state,
|
|
|
|
const WellState& xw);
|
|
|
|
|
2015-06-11 23:49:25 -05:00
|
|
|
bool getWellConvergence(const int iteration);
|
|
|
|
|
2015-08-18 07:53:36 -05:00
|
|
|
bool isVFPActive() const;
|
2015-08-18 03:24:57 -05:00
|
|
|
|
2015-01-07 04:24:11 -06:00
|
|
|
std::vector<ADB>
|
|
|
|
computePressures(const ADB& po,
|
|
|
|
const ADB& sw,
|
|
|
|
const ADB& so,
|
|
|
|
const ADB& sg) const;
|
|
|
|
|
2015-03-06 09:02:22 -06:00
|
|
|
V
|
|
|
|
computeGasPressure(const V& po,
|
|
|
|
const V& sw,
|
|
|
|
const V& so,
|
|
|
|
const V& sg) const;
|
|
|
|
|
2013-05-23 11:28:50 -05:00
|
|
|
std::vector<ADB>
|
2013-05-25 03:47:22 -05:00
|
|
|
computeRelPerm(const SolutionState& state) const;
|
|
|
|
|
2013-05-23 11:28:50 -05:00
|
|
|
void
|
|
|
|
computeMassFlux(const int actph ,
|
|
|
|
const V& transi,
|
2013-11-26 06:51:10 -06:00
|
|
|
const ADB& kr ,
|
2016-02-03 04:26:11 -06:00
|
|
|
const ADB& mu ,
|
|
|
|
const ADB& rho ,
|
2013-11-26 06:51:10 -06:00
|
|
|
const ADB& p ,
|
2013-05-24 04:14:05 -05:00
|
|
|
const SolutionState& state );
|
2013-05-23 11:28:50 -05:00
|
|
|
|
2014-08-27 03:27:49 -05:00
|
|
|
void applyThresholdPressures(ADB& dp);
|
|
|
|
|
2013-05-23 11:28:50 -05:00
|
|
|
ADB
|
|
|
|
fluidViscosity(const int phase,
|
|
|
|
const ADB& p ,
|
2014-11-20 05:31:50 -06:00
|
|
|
const ADB& temp ,
|
2013-05-30 07:43:32 -05:00
|
|
|
const ADB& rs ,
|
2014-01-10 07:19:37 -06:00
|
|
|
const ADB& rv ,
|
2015-06-24 03:22:23 -05:00
|
|
|
const std::vector<PhasePresence>& cond) const;
|
2013-05-23 11:28:50 -05:00
|
|
|
|
|
|
|
ADB
|
|
|
|
fluidReciprocFVF(const int phase,
|
|
|
|
const ADB& p ,
|
2014-11-20 05:31:50 -06:00
|
|
|
const ADB& temp ,
|
2013-05-30 07:43:32 -05:00
|
|
|
const ADB& rs ,
|
2014-01-10 07:19:37 -06:00
|
|
|
const ADB& rv ,
|
2015-06-24 03:22:23 -05:00
|
|
|
const std::vector<PhasePresence>& cond) const;
|
2013-05-23 11:28:50 -05:00
|
|
|
|
|
|
|
ADB
|
2015-06-24 03:22:23 -05:00
|
|
|
fluidDensity(const int phase,
|
|
|
|
const ADB& b,
|
|
|
|
const ADB& rs,
|
|
|
|
const ADB& rv) const;
|
2013-05-27 03:29:04 -05:00
|
|
|
|
2013-05-30 07:43:32 -05:00
|
|
|
V
|
2014-01-10 07:19:37 -06:00
|
|
|
fluidRsSat(const V& p,
|
2014-07-05 08:06:12 -05:00
|
|
|
const V& so,
|
2013-05-30 07:43:32 -05:00
|
|
|
const std::vector<int>& cells) const;
|
|
|
|
|
2013-05-27 03:29:04 -05:00
|
|
|
ADB
|
2014-01-10 07:19:37 -06:00
|
|
|
fluidRsSat(const ADB& p,
|
2014-07-05 08:06:12 -05:00
|
|
|
const ADB& so,
|
2014-01-10 07:19:37 -06:00
|
|
|
const std::vector<int>& cells) const;
|
|
|
|
|
|
|
|
V
|
|
|
|
fluidRvSat(const V& p,
|
2014-07-05 08:06:12 -05:00
|
|
|
const V& so,
|
2014-01-10 07:19:37 -06:00
|
|
|
const std::vector<int>& cells) const;
|
|
|
|
|
|
|
|
ADB
|
|
|
|
fluidRvSat(const ADB& p,
|
2014-07-05 08:06:12 -05:00
|
|
|
const ADB& so,
|
2013-05-27 03:29:04 -05:00
|
|
|
const std::vector<int>& cells) const;
|
2013-06-03 07:14:48 -05:00
|
|
|
|
|
|
|
ADB
|
|
|
|
poroMult(const ADB& p) const;
|
|
|
|
|
|
|
|
ADB
|
|
|
|
transMult(const ADB& p) const;
|
2013-11-28 04:27:25 -06:00
|
|
|
|
2014-01-10 07:19:37 -06:00
|
|
|
const std::vector<PhasePresence>
|
|
|
|
phaseCondition() const {return phaseCondition_;}
|
|
|
|
|
|
|
|
void
|
2015-05-25 16:49:09 -05:00
|
|
|
classifyCondition(const ReservoirState& state);
|
2014-01-10 07:19:37 -06:00
|
|
|
|
2014-06-03 06:30:35 -05:00
|
|
|
|
|
|
|
/// update the primal variable for Sg, Rv or Rs. The Gas phase must
|
|
|
|
/// be active to call this method.
|
2014-05-27 08:09:58 -05:00
|
|
|
void
|
2015-05-25 16:49:09 -05:00
|
|
|
updatePrimalVariableFromState(const ReservoirState& state);
|
2014-05-27 08:09:58 -05:00
|
|
|
|
2014-07-17 07:34:07 -05:00
|
|
|
/// Update the phaseCondition_ member based on the primalVariable_ member.
|
2015-05-26 07:38:25 -05:00
|
|
|
/// Also updates isRs_, isRv_ and isSg_;
|
2014-07-17 07:34:07 -05:00
|
|
|
void
|
2016-05-13 02:04:48 -05:00
|
|
|
updatePhaseCondFromPrimalVariable(const ReservoirState& state);
|
2014-07-17 07:34:07 -05:00
|
|
|
|
2016-05-10 07:58:45 -05:00
|
|
|
// TODO: added since the interfaces of the function are different
|
|
|
|
// TODO: for StandardWells and MultisegmentWells
|
|
|
|
void
|
|
|
|
computeWellConnectionPressures(const SolutionState& state,
|
|
|
|
const WellState& well_state);
|
|
|
|
|
2015-01-27 05:49:55 -06:00
|
|
|
/// \brief Compute the reduction within the convergence check.
|
2015-01-28 09:53:16 -06:00
|
|
|
/// \param[in] B A matrix with MaxNumPhases columns and the same number rows
|
|
|
|
/// as the number of cells of the grid. B.col(i) contains the values
|
|
|
|
/// for phase i.
|
|
|
|
/// \param[in] tempV A matrix with MaxNumPhases columns and the same number rows
|
|
|
|
/// as the number of cells of the grid. tempV.col(i) contains the
|
|
|
|
/// values
|
|
|
|
/// for phase i.
|
|
|
|
/// \param[in] R A matrix with MaxNumPhases columns and the same number rows
|
|
|
|
/// as the number of cells of the grid. B.col(i) contains the values
|
|
|
|
/// for phase i.
|
|
|
|
/// \param[out] R_sum An array of size MaxNumPhases where entry i contains the sum
|
|
|
|
/// of R for the phase i.
|
2015-01-28 12:08:48 -06:00
|
|
|
/// \param[out] maxCoeff An array of size MaxNumPhases where entry i contains the
|
2015-01-28 12:17:25 -06:00
|
|
|
/// maximum of tempV for the phase i.
|
2015-01-28 12:08:48 -06:00
|
|
|
/// \param[out] B_avg An array of size MaxNumPhases where entry i contains the average
|
|
|
|
/// of B for the phase i.
|
2015-10-12 08:49:10 -05:00
|
|
|
/// \param[out] maxNormWell The maximum of the well flux equations for each phase.
|
2015-01-28 09:53:16 -06:00
|
|
|
/// \param[in] nc The number of cells of the local grid.
|
|
|
|
/// \return The total pore volume over all cells.
|
2015-01-27 05:49:55 -06:00
|
|
|
double
|
2015-09-30 03:03:48 -05:00
|
|
|
convergenceReduction(const Eigen::Array<double, Eigen::Dynamic, Eigen::Dynamic>& B,
|
|
|
|
const Eigen::Array<double, Eigen::Dynamic, Eigen::Dynamic>& tempV,
|
|
|
|
const Eigen::Array<double, Eigen::Dynamic, Eigen::Dynamic>& R,
|
|
|
|
std::vector<double>& R_sum,
|
|
|
|
std::vector<double>& maxCoeff,
|
|
|
|
std::vector<double>& B_avg,
|
2015-05-13 05:00:38 -05:00
|
|
|
std::vector<double>& maxNormWell,
|
2015-10-12 08:49:10 -05:00
|
|
|
int nc) const;
|
2015-01-20 07:21:45 -06:00
|
|
|
|
2014-10-01 05:48:41 -05:00
|
|
|
double dpMaxRel() const { return param_.dp_max_rel_; }
|
|
|
|
double dsMax() const { return param_.ds_max_; }
|
2014-11-05 06:03:00 -06:00
|
|
|
double drMaxRel() const { return param_.dr_max_rel_; }
|
2015-01-21 08:43:18 -06:00
|
|
|
double maxResidualAllowed() const { return param_.max_residual_allowed_; }
|
2014-01-10 07:19:37 -06:00
|
|
|
|
2013-05-23 11:28:50 -05:00
|
|
|
};
|
|
|
|
} // namespace Opm
|
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
#include "BlackoilModelBase_impl.hpp"
|
2013-05-24 03:49:59 -05:00
|
|
|
|
2015-05-24 02:59:40 -05:00
|
|
|
#endif // OPM_BLACKOILMODELBASE_HEADER_INCLUDED
|