// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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 .
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
*
* \copydoc Opm::EclProblem
*/
#ifndef EWOMS_ECL_PROBLEM_HH
#define EWOMS_ECL_PROBLEM_HH
#if USE_ALUGRID
#define DISABLE_ALUGRID_SFC_ORDERING 1
#include "eclalugridvanguard.hh"
#elif USE_POLYHEDRALGRID
#include "eclpolyhedralgridvanguard.hh"
#else
#include "eclcpgridvanguard.hh"
#endif
#include "eclactionhandler.hh"
#include "eclequilinitializer.hh"
#include "eclwriter.hh"
#include "ecloutputblackoilmodule.hh"
#include "ecltransmissibility.hh"
#include "eclthresholdpressure.hh"
#include "ecldummygradientcalculator.hh"
#include "eclfluxmodule.hh"
#include "eclbaseaquifermodel.hh"
#include "eclnewtonmethod.hh"
#include "ecltracermodel.hh"
#include "vtkecltracermodule.hh"
#include "eclgenericproblem.hh"
#include "FIBlackOilModel.hpp"
#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
#include
#include
#include
#include
#include
#include
namespace Opm {
template
class EclProblem;
}
namespace Opm::Properties {
namespace TTag {
#if USE_ALUGRID
struct EclBaseProblem {
using InheritsFrom = std::tuple;
};
#elif USE_POLYHEDRALGRID
struct EclBaseProblem {
using InheritsFrom = std::tuple;
};
#else
struct EclBaseProblem {
using InheritsFrom = std::tuple;
};
#endif
}
// The class which deals with ECL wells
template
struct EclWellModel {
using type = UndefinedProperty;
};
// Write all solutions for visualization, not just the ones for the
// report steps...
template
struct EnableWriteAllSolutions {
using type = UndefinedProperty;
};
// The number of time steps skipped between writing two consequtive restart files
template
struct RestartWritingInterval {
using type = UndefinedProperty;
};
// Enable partial compensation of systematic mass losses via the source term of the next time
// step
template
struct EclEnableDriftCompensation {
using type = UndefinedProperty;
};
// Enable the additional checks even if compiled in debug mode (i.e., with the NDEBUG
// macro undefined). Next to a slightly better performance, this also eliminates some
// print statements in debug mode.
template
struct EnableDebuggingChecks {
using type = UndefinedProperty;
};
// if thermal flux boundaries are enabled an effort is made to preserve the initial
// thermal gradient specified via the TEMPVD keyword
template
struct EnableThermalFluxBoundaries {
using type = UndefinedProperty;
};
// Specify whether API tracking should be enabled (replaces PVT regions).
// TODO: This is not yet implemented
template
struct EnableApiTracking {
using type = UndefinedProperty;
};
// The class which deals with ECL aquifers
template
struct EclAquiferModel {
using type = UndefinedProperty;
};
// In experimental mode, decides if the aquifer model should be enabled or not
template
struct EclEnableAquifers {
using type = UndefinedProperty;
};
// time stepping parameters
template
struct EclMaxTimeStepSizeAfterWellEvent {
using type = UndefinedProperty;
};
template
struct EclRestartShrinkFactor {
using type = UndefinedProperty;
};
template
struct EclEnableTuning {
using type = UndefinedProperty;
};
template
struct OutputMode {
using type = UndefinedProperty;
};
// Set the problem property
template
struct Problem {
using type = EclProblem;
};
template
struct Model {
using type = FIBlackOilModel;
};
// Select the element centered finite volume method as spatial discretization
template
struct SpatialDiscretizationSplice {
using type = TTag::EcfvDiscretization;
};
//! for ebos, use automatic differentiation to linearize the system of PDEs
template
struct LocalLinearizerSplice {
using type = TTag::AutoDiffLocalLinearizer;
};
// Set the material law for fluid fluxes
template
struct MaterialLaw
{
private:
using Scalar = GetPropType;
using FluidSystem = GetPropType;
using Traits = ThreePhaseMaterialTraits;
public:
using EclMaterialLawManager = ::Opm::EclMaterialLawManager;
using type = typename EclMaterialLawManager::MaterialLaw;
};
// Set the material law for energy storage in rock
template
struct SolidEnergyLaw
{
private:
using Scalar = GetPropType;
using FluidSystem = GetPropType;
public:
using EclThermalLawManager = ::Opm::EclThermalLawManager;
using type = typename EclThermalLawManager::SolidEnergyLaw;
};
// Set the material law for thermal conduction
template
struct ThermalConductionLaw
{
private:
using Scalar = GetPropType;
using FluidSystem = GetPropType;
public:
using EclThermalLawManager = ::Opm::EclThermalLawManager;
using type = typename EclThermalLawManager::ThermalConductionLaw;
};
// ebos can use a slightly faster stencil class because it does not need the normals and
// the integration points of intersections
template
struct Stencil
{
private:
using Scalar = GetPropType;
using GridView = GetPropType;
public:
using type = EcfvStencil;
};
// by default use the dummy aquifer "model"
template
struct EclAquiferModel {
using type = EclBaseAquiferModel;
};
// Enable aquifers by default in experimental mode
template
struct EclEnableAquifers {
static constexpr bool value = true;
};
// Enable gravity
template
struct EnableGravity {
static constexpr bool value = true;
};
// Enable diffusion
template
struct EnableDiffusion {
static constexpr bool value = true;
};
// only write the solutions for the report steps to disk
template
struct EnableWriteAllSolutions {
static constexpr bool value = false;
};
// disable API tracking
template
struct EnableApiTracking {
static constexpr bool value = false;
};
// The default for the end time of the simulation [s]
//
// By default, stop it after the universe will probably have stopped
// to exist. (the ECL problem will finish the simulation explicitly
// after it simulated the last episode specified in the deck.)
template
struct EndTime {
using type = GetPropType;
static constexpr type value = 1e100;
};
// The default for the initial time step size of the simulation [s].
//
// The chosen value means that the size of the first time step is the
// one of the initial episode (if the length of the initial episode is
// not millions of trillions of years, that is...)
template
struct InitialTimeStepSize {
using type = GetPropType;
static constexpr type value = 3600*24;
};
// the default for the allowed volumetric error for oil per second
template
struct NewtonTolerance {
using type = GetPropType;
static constexpr type value = 1e-2;
};
// the tolerated amount of "incorrect" amount of oil per time step for the complete
// reservoir. this is scaled by the pore volume of the reservoir, i.e., larger reservoirs
// will tolerate larger residuals.
template
struct EclNewtonSumTolerance {
using type = GetPropType;
static constexpr type value = 1e-4;
};
// set the exponent for the volume scaling of the sum tolerance: larger reservoirs can
// tolerate a higher amount of mass lost per time step than smaller ones! since this is
// not linear, we use the cube root of the overall pore volume by default, i.e., the
// value specified by the NewtonSumTolerance parameter is the "incorrect" mass per
// timestep for an reservoir that exhibits 1 m^3 of pore volume. A reservoir with a total
// pore volume of 10^3 m^3 will tolerate 10 times as much.
template
struct EclNewtonSumToleranceExponent {
using type = GetPropType;
static constexpr type value = 1.0/3.0;
};
// set number of Newton iterations where the volumetric residual is considered for
// convergence
template
struct EclNewtonStrictIterations {
static constexpr int value = 8;
};
// set fraction of the pore volume where the volumetric residual may be violated during
// strict Newton iterations
template
struct EclNewtonRelaxedVolumeFraction {
using type = GetPropType;
static constexpr type value = 0.03;
};
// the maximum volumetric error of a cell in the relaxed region
template
struct EclNewtonRelaxedTolerance {
using type = GetPropType;
static constexpr type value = 1e9;
};
// Ignore the maximum error mass for early termination of the newton method.
template
struct NewtonMaxError {
using type = GetPropType;
static constexpr type value = 10e9;
};
// set the maximum number of Newton iterations to 14 because the likelyhood that a time
// step succeeds at more than 14 Newton iteration is rather small
template
struct NewtonMaxIterations {
static constexpr int value = 14;
};
// also, reduce the target for the "optimum" number of Newton iterations to 6. Note that
// this is only relevant if the time step is reduced from the report step size for some
// reason. (because ebos first tries to do a report step using a single time step.)
template
struct NewtonTargetIterations {
static constexpr int value = 6;
};
// Disable the VTK output by default for this problem ...
template
struct EnableVtkOutput {
static constexpr bool value = false;
};
// ... but enable the ECL output by default
template
struct EnableEclOutput {
static constexpr bool value = true;
};
#ifdef HAVE_DAMARIS
//! Enable the Damaris output by default
template
struct EnableDamarisOutput {
static constexpr bool value = false;
};
// If Damaris is available, write specific variable output in parallel
template
struct EnableDamarisOutputCollective {
static constexpr bool value = true;
};
#endif
// If available, write the ECL output in a non-blocking manner
template
struct EnableAsyncEclOutput {
static constexpr bool value = true;
};
// Write ESMRY file for fast loading of summary data
template
struct EnableEsmry {
static constexpr bool value = false;
};
// By default, use single precision for the ECL formated results
template
struct EclOutputDoublePrecision {
static constexpr bool value = false;
};
// The default location for the ECL output files
template
struct OutputDir {
static constexpr auto value = ".";
};
// the cache for intensive quantities can be used for ECL problems and also yields a
// decent speedup...
template
struct EnableIntensiveQuantityCache {
static constexpr bool value = true;
};
// the cache for the storage term can also be used and also yields a decent speedup
template
struct EnableStorageCache {
static constexpr bool value = true;
};
// Use the "velocity module" which uses the Eclipse "NEWTRAN" transmissibilities
template
struct FluxModule {
using type = EclTransFluxModule;
};
// Use the dummy gradient calculator in order not to do unnecessary work.
template
struct GradientCalculator {
using type = EclDummyGradientCalculator;
};
// Use a custom Newton-Raphson method class for ebos in order to attain more
// sophisticated update and error computation mechanisms
template
struct NewtonMethod {
using type = EclNewtonMethod;
};
// The frequency of writing restart (*.ers) files. This is the number of time steps
// between writing restart files
template
struct RestartWritingInterval {
static constexpr int value = 0xffffff; // disable
};
// Drift compensation is an experimental feature, i.e., systematic errors in the
// conservation quantities are only compensated for
// as default if experimental mode is enabled.
template
struct EclEnableDriftCompensation {
static constexpr bool value = true;
};
// By default, we enable the debugging checks if we're compiled in debug mode
template
struct EnableDebuggingChecks {
static constexpr bool value = true;
};
// store temperature (but do not conserve energy, as long as EnableEnergy is false)
template
struct EnableTemperature {
static constexpr bool value = true;
};
// disable all extensions supported by black oil model. this should not really be
// necessary but it makes things a bit more explicit
template
struct EnablePolymer {
static constexpr bool value = false;
};
template
struct EnableSolvent {
static constexpr bool value = false;
};
template
struct EnableEnergy {
static constexpr bool value = false;
};
template
struct EnableFoam {
static constexpr bool value = false;
};
template
struct EnableExtbo {
static constexpr bool value = false;
};
template
struct EnableMICP {
static constexpr bool value = false;
};
// disable thermal flux boundaries by default
template
struct EnableThermalFluxBoundaries {
static constexpr bool value = false;
};
// By default, simulators derived from the EclBaseProblem are production simulators,
// i.e., experimental features must be explicitly enabled at compile time
template
struct EnableExperiments {
static constexpr bool value = false;
};
// set defaults for the time stepping parameters
template
struct EclMaxTimeStepSizeAfterWellEvent {
using type = GetPropType;
static constexpr type value = 3600*24*365.25;
};
template
struct EclRestartShrinkFactor {
using type = GetPropType;
static constexpr type value = 3;
};
template
struct EclEnableTuning {
static constexpr bool value = false;
};
template
struct OutputMode {
static constexpr auto value = "all";
};
} // namespace Opm::Properties
namespace Opm {
/*!
* \ingroup EclBlackOilSimulator
*
* \brief This problem simulates an input file given in the data format used by the
* commercial ECLiPSE simulator.
*/
template
class EclProblem : public GetPropType
, public EclGenericProblem,
GetPropType,
GetPropType>
{
using BaseType = EclGenericProblem,
GetPropType,
GetPropType>;
using ParentType = GetPropType;
using Implementation = GetPropType;
using Scalar = GetPropType;
using GridView = GetPropType;
using Stencil = GetPropType;
using FluidSystem = GetPropType;
using GlobalEqVector = GetPropType;
using EqVector = GetPropType;
using Vanguard = GetPropType;
// Grid and world dimension
enum { dim = GridView::dimension };
enum { dimWorld = GridView::dimensionworld };
// copy some indices for convenience
enum { numEq = getPropValue() };
enum { numPhases = FluidSystem::numPhases };
enum { numComponents = FluidSystem::numComponents };
enum { enableExperiments = getPropValue() };
enum { enableSolvent = getPropValue() };
enum { enablePolymer = getPropValue() };
enum { enableBrine = getPropValue() };
enum { enableSaltPrecipitation = getPropValue() };
enum { enablePolymerMolarWeight = getPropValue() };
enum { enableFoam = getPropValue() };
enum { enableExtbo = getPropValue() };
enum { enableTemperature = getPropValue() };
enum { enableEnergy = getPropValue() };
enum { enableDiffusion = getPropValue() };
enum { enableThermalFluxBoundaries = getPropValue() };
enum { enableApiTracking = getPropValue() };
enum { enableMICP = getPropValue() };
enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
enum { gasCompIdx = FluidSystem::gasCompIdx };
enum { oilCompIdx = FluidSystem::oilCompIdx };
enum { waterCompIdx = FluidSystem::waterCompIdx };
using PrimaryVariables = GetPropType;
using RateVector = GetPropType;
using BoundaryRateVector = GetPropType;
using Simulator = GetPropType;
using Element = typename GridView::template Codim<0>::Entity;
using ElementContext = GetPropType;
using EclMaterialLawManager = typename GetProp::EclMaterialLawManager;
using EclThermalLawManager = typename GetProp::EclThermalLawManager;
using MaterialLawParams = typename EclMaterialLawManager::MaterialLawParams;
using SolidEnergyLawParams = typename EclThermalLawManager::SolidEnergyLawParams;
using ThermalConductionLawParams = typename EclThermalLawManager::ThermalConductionLawParams;
using MaterialLaw = GetPropType;
using DofMapper = GetPropType;
using Evaluation = GetPropType;
using Indices = GetPropType;
using IntensiveQuantities = GetPropType;
using EclWellModel = GetPropType;
using EclAquiferModel = GetPropType;
using SolventModule = BlackOilSolventModule;
using PolymerModule = BlackOilPolymerModule;
using FoamModule = BlackOilFoamModule;
using BrineModule = BlackOilBrineModule;
using ExtboModule = BlackOilExtboModule;
using MICPModule = BlackOilMICPModule;
using InitialFluidState = typename EclEquilInitializer::ScalarFluidState;
using Toolbox = MathToolbox;
using DimMatrix = Dune::FieldMatrix;
using EclWriterType = EclWriter;
using TracerModel = EclTracerModel;
using DirectionalMobilityPtr = Opm::Utility::CopyablePtr>;
public:
using EclGenericProblem::briefDescription;
using EclGenericProblem::helpPreamble;
using EclGenericProblem::shouldWriteOutput;
using EclGenericProblem::shouldWriteRestartFile;
using EclGenericProblem::maxTimeIntegrationFailures;
using EclGenericProblem::minTimeStepSize;
using EclGenericProblem::rockCompressibility;
using EclGenericProblem