Commit 30db5a36 authored by Timo Koch's avatar Timo Koch
Browse files

[fluxcache] Simplify and at the same time implement all combinations of caches

parent 66e11283
......@@ -66,6 +66,33 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCMpfa>
static constexpr int dim = GridView::dimension;
static constexpr int dimWorld = GridView::dimensionworld;
//! Class that fills the cache corresponding to mpfa Darcy's Law
class MpfaDarcysLawCacheFiller
{
public:
//! Function to fill an MpfaDarcysLawCache of a given scvf
//! This interface has to be met by any advection-related cache filler class
template<class FluxVariablesCacheFiller>
static void fill(FluxVariablesCache& scvfFluxVarsCache,
const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace& scvf,
const FluxVariablesCacheFiller& fluxVarsCacheFiller)
{
// get interaction volume from the flux vars cache filler & upate the cache
if (fvGeometry.fvGridGeometry().vertexUsesSecondaryInteractionVolume(scvf.vertexIndex()))
scvfFluxVarsCache.updateAdvection(fluxVarsCacheFiller.secondaryInteractionVolume(),
fluxVarsCacheFiller.dataHandle(),
scvf);
else
scvfFluxVarsCache.updateAdvection(fluxVarsCacheFiller.primaryInteractionVolume(),
fluxVarsCacheFiller.dataHandle(),
scvf);
}
};
//! The cache used in conjunction with the mpfa Darcy's Law
class MpfaDarcysLawCache
{
......@@ -74,6 +101,9 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCMpfa>
using DirichletDataContainer = typename PrimaryInteractionVolume::DirichletDataContainer;
public:
// export the filler type
using Filler = MpfaDarcysLawCacheFiller;
//! update cached objects
template<class InteractionVolume>
void updateAdvection(const InteractionVolume& iv, const DataHandle& dataHandle, const SubControlVolumeFace &scvf)
......@@ -120,40 +150,12 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCMpfa>
const DirichletDataContainer* advectionDirichletData_;
};
//! Class that fills the cache corresponding to mpfa Darcy's Law
class MpfaDarcysLawCacheFiller
{
public:
//! Function to fill an MpfaDarcysLawCache of a given scvf
//! This interface has to be met by any advection-related cache filler class
template<class FluxVariablesCacheFiller>
static void fill(FluxVariablesCache& scvfFluxVarsCache,
const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace& scvf,
const FluxVariablesCacheFiller& fluxVarsCacheFiller)
{
// get interaction volume from the flux vars cache filler & upate the cache
if (fvGeometry.fvGridGeometry().vertexUsesSecondaryInteractionVolume(scvf.vertexIndex()))
scvfFluxVarsCache.updateAdvection(fluxVarsCacheFiller.secondaryInteractionVolume(),
fluxVarsCacheFiller.dataHandle(),
scvf);
else
scvfFluxVarsCache.updateAdvection(fluxVarsCacheFiller.primaryInteractionVolume(),
fluxVarsCacheFiller.dataHandle(),
scvf);
}
};
public:
// state the discretization method this implementation belongs to
static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::CCMpfa;
// state the type for the corresponding cache and its filler
// export the type for the corresponding cache
using Cache = MpfaDarcysLawCache;
using CacheFiller = MpfaDarcysLawCacheFiller;
static Scalar flux(const Problem& problem,
const Element& element,
......
......@@ -74,14 +74,41 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCMpfa>
static constexpr bool enableInteriorBoundaries = GET_PROP_VALUE(TypeTag, EnableInteriorBoundaries);
using ComponentFluxVector = Dune::FieldVector<Scalar, numComponents>;
//! Class that fills the cache corresponding to mpfa Darcy's Law
class MpfaFicksLawCacheFiller
{
public:
//! Function to fill an MpfaFicksLawCache of a given scvf
//! This interface has to be met by any diffusion-related cache filler class
template<class FluxVariablesCacheFiller>
static void fill(FluxVariablesCache& scvfFluxVarsCache,
unsigned int phaseIdx, unsigned int compIdx,
const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace& scvf,
const FluxVariablesCacheFiller& fluxVarsCacheFiller)
{
// get interaction volume from the flux vars cache filler & upate the cache
if (problem.model().fvGridGeometry().isInBoundaryInteractionVolume(scvf))
scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.boundaryInteractionVolume(), scvf, phaseIdx, compIdx);
else
scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.interactionVolume(), scvf, phaseIdx, compIdx);
}
};
//! The cache used in conjunction with the mpfa Fick's Law
class MpfaFicksLawCache
{
// We always use the dynamic types here to be compatible on the boundary
// We always use the dynamic types here to be compatible on the boundary
using Stencil = typename BoundaryInteractionVolume::GlobalIndexSet;
using PositionVector = typename BoundaryInteractionVolume::PositionVector;
public:
// export filler type
using Filler = MpfaFicksLawCacheFiller;
//! The constructor. Initializes the Neumann flux to zero
MpfaFicksLawCache() { componentNeumannFluxes_.fill(0.0); }
......@@ -133,37 +160,12 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCMpfa>
std::array<Scalar, numComponents> componentNeumannFluxes_;
};
//! Class that fills the cache corresponding to mpfa Darcy's Law
class MpfaFicksLawCacheFiller
{
public:
//! Function to fill an MpfaFicksLawCache of a given scvf
//! This interface has to be met by any diffusion-related cache filler class
template<class FluxVariablesCacheFiller>
static void fill(FluxVariablesCache& scvfFluxVarsCache,
unsigned int phaseIdx, unsigned int compIdx,
const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace& scvf,
const FluxVariablesCacheFiller& fluxVarsCacheFiller)
{
// get interaction volume from the flux vars cache filler & upate the cache
if (problem.model().fvGridGeometry().isInBoundaryInteractionVolume(scvf))
scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.boundaryInteractionVolume(), scvf, phaseIdx, compIdx);
else
scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.interactionVolume(), scvf, phaseIdx, compIdx);
}
};
public:
// state the discretization method this implementation belongs to
static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::CCMpfa;
// state the type for the corresponding cache and its filler
using Cache = MpfaFicksLawCache;
using CacheFiller = MpfaFicksLawCacheFiller;
static ComponentFluxVector flux (const Problem& problem,
const Element& element,
......
......@@ -254,7 +254,7 @@ private:
const std::vector<FluxVariablesCache*>& ivFluxVarCaches)
{
using AdvectionType = typename GET_PROP_TYPE(TypeTag, AdvectionType);
using AdvectionFiller = typename AdvectionType::CacheFiller;
using AdvectionFiller = typename AdvectionType::Cache::Filler;
static constexpr auto AdvectionMethod = AdvectionType::myDiscretizationMethod;
using LambdaFactory = TensorLambdaFactory<TypeTag, AdvectionMethod>;
......@@ -296,7 +296,7 @@ private:
const std::vector<FluxVariablesCache*>& ivFluxVarCaches)
{
using DiffusionType = typename GET_PROP_TYPE(TypeTag, MolecularDiffusionType);
using DiffusionFiller = typename DiffusionType::CacheFiller;
using DiffusionFiller = typename DiffusionType::Cache::Filler;
static constexpr auto DiffusionMethod = DiffusionType::myDiscretizationMethod;
using LambdaFactory = TensorLambdaFactory<TypeTag, DiffusionMethod>;
......@@ -352,7 +352,7 @@ private:
const std::vector<FluxVariablesCache*>& ivFluxVarCaches)
{
using HeatConductionType = typename GET_PROP_TYPE(TypeTag, HeatConductionType);
using HeatConductionFiller = typename HeatConductionType::CacheFiller;
using HeatConductionFiller = typename HeatConductionType::Cache::Filler;
static constexpr auto HeatConductionMethod = HeatConductionType::myDiscretizationMethod;
using LambdaFactory = TensorLambdaFactory<TypeTag, HeatConductionMethod>;
......
......@@ -66,11 +66,37 @@ class FouriersLawImplementation<TypeTag, DiscretizationMethods::CCMpfa>
static constexpr int energyEqIdx = GET_PROP_TYPE(TypeTag, Indices)::energyEqIdx;
//! Class that fills the cache corresponding to mpfa Darcy's Law
class MpfaFouriersLawCacheFiller
{
public:
//! Function to fill an MpfaDarcysLawCache of a given scvf
//! This interface has to be met by any cache filler class for heat conduction quantities
template<class FluxVariablesCacheFiller>
static void fill(FluxVariablesCache& scvfFluxVarsCache,
const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace& scvf,
const FluxVariablesCacheFiller& fluxVarsCacheFiller)
{
// get interaction volume from the flux vars cache filler & upate the cache
if (problem.model().fvGridGeometry().isInBoundaryInteractionVolume(scvf))
scvfFluxVarsCache.updateHeatConduction(fluxVarsCacheFiller.boundaryInteractionVolume(), scvf);
else
scvfFluxVarsCache.updateHeatConduction(fluxVarsCacheFiller.interactionVolume(), scvf);
}
};
//! The cache used in conjunction with the mpfa Fourier's Law
class MpfaFouriersLawCache
{
using Stencil = typename BoundaryInteractionVolume::GlobalIndexSet;
public:
// export filler type
using Filler = MpfaFouriersLawCacheFiller;
// update cached objects for heat conduction
template<typename InteractionVolume>
void updateHeatConduction(const InteractionVolume& iv, const SubControlVolumeFace &scvf)
......@@ -104,36 +130,12 @@ class FouriersLawImplementation<TypeTag, DiscretizationMethods::CCMpfa>
Scalar heatNeumannFlux_;
};
//! Class that fills the cache corresponding to mpfa Darcy's Law
class MpfaFouriersLawCacheFiller
{
public:
//! Function to fill an MpfaDarcysLawCache of a given scvf
//! This interface has to be met by any cache filler class for heat conduction quantities
template<class FluxVariablesCacheFiller>
static void fill(FluxVariablesCache& scvfFluxVarsCache,
const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace& scvf,
const FluxVariablesCacheFiller& fluxVarsCacheFiller)
{
// get interaction volume from the flux vars cache filler & upate the cache
if (problem.model().fvGridGeometry().isInBoundaryInteractionVolume(scvf))
scvfFluxVarsCache.updateHeatConduction(fluxVarsCacheFiller.boundaryInteractionVolume(), scvf);
else
scvfFluxVarsCache.updateHeatConduction(fluxVarsCacheFiller.interactionVolume(), scvf);
}
};
public:
// state the discretization method this implementation belongs to
static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::CCMpfa;
// state the type for the corresponding cache and its filler
using Cache = MpfaFouriersLawCache;
using CacheFiller = MpfaFouriersLawCacheFiller;
static Scalar flux(const Problem& problem,
const Element& element,
......
......@@ -65,25 +65,6 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCTpfa>
using DimWorldMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
class TpfaDarcysLawCache
{
public:
void updateAdvection(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace &scvf)
{
tij_ = Implementation::calculateTransmissibilities(problem, element, fvGeometry, elemVolVars, scvf);
}
const Scalar& advectionTij() const
{ return tij_; }
private:
Scalar tij_;
};
//! Class that fills the cache corresponding to tpfa Darcy's Law
class TpfaDarcysLawCacheFiller
{
......@@ -103,13 +84,33 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCTpfa>
}
};
class TpfaDarcysLawCache
{
public:
using Filler = TpfaDarcysLawCacheFiller;
void updateAdvection(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace &scvf)
{
tij_ = Implementation::calculateTransmissibilities(problem, element, fvGeometry, elemVolVars, scvf);
}
const Scalar& advectionTij() const
{ return tij_; }
private:
Scalar tij_;
};
public:
// state the discretization method this implementation belongs to
static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::CCTpfa;
// state the type for the corresponding cache and its filler
// state the type for the corresponding cache
using Cache = TpfaDarcysLawCache;
using CacheFiller = TpfaDarcysLawCacheFiller;
static Scalar flux(const Problem& problem,
const Element& element,
......
......@@ -74,9 +74,32 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCTpfa >
using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
using ComponentFluxVector = Dune::FieldVector<Scalar, numComponents>;
//! Class that fills the cache corresponding to tpfa Fick's Law
class TpfaFicksLawCacheFiller
{
public:
//! Function to fill a TpfaFicksLawCache of a given scvf
//! This interface has to be met by any diffusion-related cache filler class
template<class FluxVariablesCacheFiller>
static void fill(FluxVariablesCache& scvfFluxVarsCache,
unsigned int phaseIdx, unsigned int compIdx,
const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace& scvf,
const FluxVariablesCacheFiller& fluxVarsCacheFiller)
{
scvfFluxVarsCache.updateDiffusion(problem, element, fvGeometry, elemVolVars, scvf, phaseIdx, compIdx);
}
};
//! Class that caches the transmissibility
class TpfaFicksLawCache
{
public:
using Filler = TpfaFicksLawCacheFiller;
void updateDiffusion(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
......@@ -95,33 +118,12 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCTpfa >
std::array< std::array<Scalar, numComponents>, numPhases> tij_;
};
//! Class that fills the cache corresponding to tpfa Fick's Law
class TpfaFicksLawCacheFiller
{
public:
//! Function to fill a TpfaFicksLawCache of a given scvf
//! This interface has to be met by any diffusion-related cache filler class
template<class FluxVariablesCacheFiller>
static void fill(FluxVariablesCache& scvfFluxVarsCache,
unsigned int phaseIdx, unsigned int compIdx,
const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace& scvf,
const FluxVariablesCacheFiller& fluxVarsCacheFiller)
{
scvfFluxVarsCache.updateDiffusion(problem, element, fvGeometry, elemVolVars, scvf, phaseIdx, compIdx);
}
};
public:
// state the discretization method this implementation belongs to
static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::CCTpfa;
//! state the type for the corresponding cache and its filler
using Cache = TpfaFicksLawCache;
using CacheFiller = TpfaFicksLawCacheFiller;
static ComponentFluxVector flux(const Problem& problem,
const Element& element,
......
......@@ -114,7 +114,7 @@ private:
const SubControlVolumeFace& scvf)
{
using AdvectionType = typename GET_PROP_TYPE(TypeTag, AdvectionType);
using AdvectionFiller = typename AdvectionType::CacheFiller;
using AdvectionFiller = typename AdvectionType::Cache::Filler;
// forward to the filler for the advective quantities
AdvectionFiller::fill(scvfFluxVarsCache, problem(), element, fvGeometry, elemVolVars, scvf, *this);
......@@ -140,7 +140,7 @@ private:
const SubControlVolumeFace& scvf)
{
using DiffusionType = typename GET_PROP_TYPE(TypeTag, MolecularDiffusionType);
using DiffusionFiller = typename DiffusionType::CacheFiller;
using DiffusionFiller = typename DiffusionType::Cache::Filler;
using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases);
......@@ -173,7 +173,7 @@ private:
const SubControlVolumeFace& scvf)
{
using HeatConductionType = typename GET_PROP_TYPE(TypeTag, HeatConductionType);
using HeatConductionFiller = typename HeatConductionType::CacheFiller;
using HeatConductionFiller = typename HeatConductionType::Cache::Filler;
// forward to the filler of the diffusive quantities
HeatConductionFiller::fill(scvfFluxVarsCache, problem(), element, fvGeometry, elemVolVars, scvf, *this);
......
......@@ -71,10 +71,9 @@ public:
// state the discretization method this implementation belongs to
static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::CCTpfa;
//! state the type for the corresponding cache and its filler
//! state the type for the corresponding cache
//! We don't cache anything for this law
using Cache = FluxVariablesCaching::EmptyHeatConductionCache;
using CacheFiller = FluxVariablesCaching::EmptyCacheFiller<TypeTag>;
using Cache = FluxVariablesCaching::EmptyHeatConductionCache<TypeTag>;
static Scalar flux(const Problem& problem,
const Element& element,
......
......@@ -26,19 +26,7 @@
namespace Dumux
{
namespace FluxVariablesCaching
{
class _EmptyCache {};
/*!
* \ingroup ImplicitModel
* \brief Empty caches to use in a law/process, e.g. Darcy's law
* \note Never use the _EmptyCache directly as it lead to ambiguous definitions
*/
class EmptyAdvectionCache : public _EmptyCache {};
class EmptyDiffusionCache : public _EmptyCache {};
class EmptyHeatConductionCache : public _EmptyCache {};
namespace FluxVariablesCaching {
//! The empty filler class corresponding to EmptyCache
template<class TypeTag>
......@@ -76,6 +64,19 @@ public:
{}
};
// an empty cache filler
template<class TypeTag> struct _EmptyCache
{ using Filler = EmptyCacheFiller<TypeTag>; };
/*!
* \ingroup ImplicitModel
* \brief Empty caches to use in a law/process, e.g. Darcy's law
* \note Never use the _EmptyCache directly as it lead to ambiguous definitions
*/
template<class TypeTag> class EmptyAdvectionCache : public _EmptyCache<TypeTag> {};
template<class TypeTag> class EmptyDiffusionCache : public _EmptyCache<TypeTag> {};
template<class TypeTag> class EmptyHeatConductionCache : public _EmptyCache<TypeTag> {};
} // end namespace FluxVariablesCaching
} // end namespace Dumux
......
......@@ -86,10 +86,9 @@ public:
// state the discretization method this implementation belongs to
static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::Staggered;
//! state the type for the corresponding cache and its filler
//! state the type for the corresponding cache
//! We don't cache anything for this law
using Cache = FluxVariablesCaching::EmptyDiffusionCache;
using CacheFiller = FluxVariablesCaching::EmptyCacheFiller<TypeTag>;
using Cache = FluxVariablesCaching::EmptyDiffusionCache<TypeTag>;
static CellCenterPrimaryVariables diffusiveFluxForCellCenter(const Problem& problem,
const FVElementGeometry& fvGeometry,
......
......@@ -55,10 +55,9 @@ public:
// state the discretization method this implementation belongs to
static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::Staggered;
//! state the type for the corresponding cache and its filler
//! state the type for the corresponding cache
//! We don't cache anything for this law
using Cache = FluxVariablesCaching::EmptyDiffusionCache;
using CacheFiller = FluxVariablesCaching::EmptyCacheFiller<TypeTag>;
using Cache = FluxVariablesCaching::EmptyDiffusionCache<TypeTag>;
static Scalar diffusiveFluxForCellCenter(const Problem& problem,
const Element& element,
......
......@@ -49,10 +49,9 @@ public:
// state the discretization method this implementation belongs to
static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::None;
//! state the type for the corresponding cache and its filler
//! state the type for the corresponding cache
//! We don't cache anything for this law
using Cache = FluxVariablesCaching::EmptyAdvectionCache;
using CacheFiller = FluxVariablesCaching::EmptyCacheFiller<TypeTag>;
using Cache = FluxVariablesCaching::EmptyAdvectionCache<TypeTag>;
static Scalar flux(const Problem& problem,
const Element& element,
......
......@@ -25,6 +25,7 @@
#include <dune/localfunctions/lagrange/pqkfactory.hh>
#include <dumux/discretization/methods.hh>
#include <dumux/discretization/fluxvariablescaching.hh>
namespace Dumux
{
......@@ -125,67 +126,36 @@ private:
JacobianInverseTransposed jacInvT_;
};
// forward declaration of the base class of the tpfa flux variables cache
template<class TypeTag, bool EnableAdvection, bool EnableMolecularDiffusion, bool EnableEnergyBalance>
class CCTpfaPorousMediumFluxVariablesCache : public GET_PROP_TYPE(TypeTag, AdvectionType)::Cache,
public GET_PROP_TYPE(TypeTag, MolecularDiffusionType)::Cache,
public GET_PROP_TYPE(TypeTag, HeatConductionType)::Cache {};
// the following classes choose the cache type: empty if the law disabled and the law's cache if it's enabled
// if advections is disabled the advection type is still instatiated if we use std::conditional_t and has to be a full type
// in order to prevent that instead of std::conditional_t we use this helper type is only dependent on the advection type
// if advection is enabled otherwise its an empty cache type
template<class TypeTag, bool EnableAdvection> class AdvectionCacheChooser : public FluxVariablesCaching::EmptyAdvectionCache<TypeTag> {};
template<class TypeTag> class AdvectionCacheChooser<TypeTag, true> : public GET_PROP_TYPE(TypeTag, AdvectionType)::Cache {};
template<class TypeTag, bool EnableMolecularDiffusion> class DiffusionCacheChooser : public FluxVariablesCaching::EmptyDiffusionCache<TypeTag> {};
template<class TypeTag> class DiffusionCacheChooser<TypeTag, true> : public GET_PROP_TYPE(TypeTag, MolecularDiffusionType)::Cache {};
template<class TypeTag, bool EnableEnergyBalance> class EnergyCacheChooser : public FluxVariablesCaching::EmptyHeatConductionCache<TypeTag> {};
template<class TypeTag> class EnergyCacheChooser<TypeTag, true> : public GET_PROP_TYPE(TypeTag, HeatConductionType)::Cache {};
// specialization for the cell centered tpfa method
template<class TypeTag>
class PorousMediumFluxVariablesCacheImplementation<TypeTag, DiscretizationMethods::CCTpfa>
: public CCTpfaPorousMediumFluxVariablesCache<TypeTag, GET_PROP_VALUE(TypeTag, EnableAdvection),
GET_PROP_VALUE(TypeTag, EnableMolecularDiffusion),
GET_PROP_VALUE(TypeTag, EnableEnergyBalance)> {};
// // specialization for the case of pure advection
// TODO ALL THESE SHOULDNOT BE NECESSARY AND ALWAYS DERIVE FROM ALL CACHES!
template<class TypeTag>
class CCTpfaPorousMediumFluxVariablesCache<TypeTag, true, false, false> : public GET_PROP_TYPE(TypeTag, AdvectionType)::Cache,
public GET_PROP_TYPE(TypeTag, MolecularDiffusionType)::Cache {};
// specialization for the case of advection & diffusion
template<class TypeTag>
class CCTpfaPorousMediumFluxVariablesCache<TypeTag, true, true, false> : public GET_PROP_TYPE(TypeTag, AdvectionType)::Cache,
public GET_PROP_TYPE(TypeTag, MolecularDiffusionType)::Cache {};
// specialization for the case of advection & heat conduction
template<class TypeTag>
class CCTpfaPorousMediumFluxVariablesCache<TypeTag, true, false, true> : public GET_PROP_TYPE(TypeTag, AdvectionType)::Cache,
public GET_PROP_TYPE(TypeTag, MolecularDiffusionType)::Cache,
public GET_PROP_TYPE(TypeTag, HeatConductionType)::Cache {};
// specialization for the case of advection, diffusion & heat conduction
template<class TypeTag>
class CCTpfaPorousMediumFluxVariablesCache<TypeTag, true, true, true> : public GET_PROP_TYPE(TypeTag, AdvectionType)::Cache,
public GET_PROP_TYPE(TypeTag, MolecularDiffusionType)::Cache,
public GET_PROP_TYPE(TypeTag, HeatConductionType)::Cache {};
// TODO further specializations
// forward declaration of the base class of the mpfa flux variables cache
template<class TypeTag, bool EnableAdvection, bool EnableMolecularDiffusion, bool EnableEnergyBalance>
class CCMpfaPorousMediumFluxVariablesCache;
: public AdvectionCacheChooser<TypeTag, GET_PROP_VALUE(TypeTag, EnableAdvection)>
, public DiffusionCacheChooser<TypeTag, GET_PROP_VALUE(TypeTag