Commit 7a7f10fa authored by Timo Koch's avatar Timo Koch
Browse files

[stencil] Improve flux stencils

Fix the flux stencil for every method independent of the stencils used
in the different flux laws. The matrix entries have to be reserved for all
possible occuring stencils if the method has parameter or solution dependent
stencils, otherwise the matrix needs to be rebuild every time. This implements
this unified flux stencil for box, cc, ccmpfa.
Remove a lot of duplicate code.
Separate the physical laws from the dicretization stencil.
parent cd1f020b
......@@ -64,7 +64,6 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::Box>
using Element = typename GridView::template Codim<0>::Entity;
using IndexType = typename GridView::IndexSet::IndexType;
using CoordScalar = typename GridView::ctype;
using Stencil = std::vector<IndexType>;
enum { dim = GridView::dimension};
enum { dimWorld = GridView::dimensionworld};
......@@ -137,14 +136,6 @@ public:
return -1.0*(KGradP*scvf.unitOuterNormal())*scvf.area();
}
// This is for compatibility with the cc methods. The flux stencil info is obsolete for the box method.
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{
return Stencil(0);
}
private:
static DimVector applyPermeability_(const DimWorldMatrix& K, const DimVector& gradI)
{
......
......@@ -65,7 +65,6 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::Box>
using ElementFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache);
using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
using IndexType = typename GridView::IndexSet::IndexType;
using Stencil = typename std::vector<IndexType>;
using Element = typename GridView::template Codim<0>::Entity;
......@@ -134,13 +133,6 @@ public:
return -1.0*(DGradX*scvf.unitOuterNormal())*scvf.area();
}
// This is for compatibility with the cc methods. The flux stencil info is obsolete for the box method.
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{ return Stencil(0); }
private:
static GlobalPosition applyDiffusionTensor_(const DimWorldMatrix& D, const GlobalPosition& gradI)
{
......
......@@ -65,7 +65,6 @@ class FouriersLawImplementation<TypeTag, DiscretizationMethods::Box>
using ElementFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache);
using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
using IndexType = typename GridView::IndexSet::IndexType;
using Stencil = typename std::vector<IndexType>;
using Element = typename GridView::template Codim<0>::Entity;
......@@ -123,13 +122,6 @@ public:
return -1.0*(lambdaGradT*scvf.unitOuterNormal())*scvf.area();
}
// This is for compatibility with the cc methods. The flux stencil info is obsolete for the box method.
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{ return Stencil(0); }
private:
static GlobalPosition applyHeatConductivityTensor_(const DimWorldMatrix& Lambda, const GlobalPosition& gradI)
{
......
......@@ -215,20 +215,6 @@ public:
flux + interiorNeumannFlux + fluxVarsCache.advectionNeumannFlux(phaseIdx);
}
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{
const auto& globalFvGeometry = problem.model().globalFvGeometry();
// return the scv (element) indices in the interaction region
if (globalFvGeometry.touchesInteriorOrDomainBoundary(scvf))
return globalFvGeometry.boundaryInteractionVolumeSeed(scvf).globalScvIndices();
else
return globalFvGeometry.interactionVolumeSeed(scvf).globalScvIndices();
}
private:
static Scalar interpolateDensity(const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace& scvf,
......
......@@ -61,7 +61,6 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCMpfa>
using Element = typename GridView::template Codim<0>::Entity;
using IndexType = typename GridView::IndexSet::IndexType;
using Stencil = std::vector<IndexType>;
static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases);
static constexpr bool useTpfaBoundary = GET_PROP_VALUE(TypeTag, UseTpfaBoundary);
......@@ -230,20 +229,6 @@ public:
flux + interiorNeumannFlux + fluxVarsCache.componentNeumannFlux(compIdx);
}
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{
const auto& globalFvGeometry = problem.model().globalFvGeometry();
// return the scv (element) indices in the interaction region
if (globalFvGeometry.touchesInteriorOrDomainBoundary(scvf))
return globalFvGeometry.boundaryInteractionVolumeSeed(scvf).globalScvIndices();
else
return globalFvGeometry.interactionVolumeSeed(scvf).globalScvIndices();
}
private:
template<typename GetRhoFunction>
static Scalar interpolateDensity(const ElementVolumeVariables& elemVolVars,
......
......@@ -57,7 +57,6 @@ class FouriersLawImplementation<TypeTag, DiscretizationMethods::CCMpfa>
using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
using Element = typename GridView::template Codim<0>::Entity;
using IndexType = typename GridView::IndexSet::IndexType;
using Stencil = typename std::vector<IndexType>;
static constexpr bool facetCoupling = GET_PROP_VALUE(TypeTag, MpfaFacetCoupling);
static constexpr bool useTpfaBoundary = GET_PROP_VALUE(TypeTag, UseTpfaBoundary);
......@@ -166,20 +165,6 @@ public:
flux + interiorNeumannFlux :
flux + interiorNeumannFlux + fluxVarsCache.heatNeumannFlux();
}
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{
const auto& globalFvGeometry = problem.model().globalFvGeometry();
// return the scv (element) indices in the interaction region
if (globalFvGeometry.touchesInteriorOrDomainBoundary(scvf))
return globalFvGeometry.boundaryInteractionVolumeSeed(scvf).globalScvIndices();
else
return globalFvGeometry.interactionVolumeSeed(scvf).globalScvIndices();
}
};
} // end namespace Dumux
......
......@@ -63,7 +63,6 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCTpfa>
using Element = typename GridView::template Codim<0>::Entity;
using IndexType = typename GridView::IndexSet::IndexType;
using Stencil = std::vector<IndexType>;
static const int dim = GridView::dimension;
static const int dimWorld = GridView::dimensionworld;
......@@ -198,24 +197,6 @@ public:
}
}
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{
if (scvf.boundary())
return Stencil({scvf.insideScvIdx()});
else if (scvf.numOutsideScvs() > 1)
{
Stencil stencil({scvf.insideScvIdx()});
for (unsigned int i = 0; i < scvf.numOutsideScvs(); ++i)
stencil.push_back(scvf.outsideScvIdx(i));
return stencil;
}
else
return Stencil({scvf.insideScvIdx(), scvf.outsideScvIdx()});
}
// The flux variables cache has to be bound to an element prior to flux calculations
// During the binding, the transmissibilities will be computed and stored using the method below.
static Scalar calculateTransmissibilities(const Problem& problem,
......
......@@ -56,7 +56,6 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCTpfa >
using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
using IndexType = typename GridView::IndexSet::IndexType;
using Stencil = typename std::vector<IndexType>;
using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
......@@ -109,17 +108,6 @@ public:
return rho*tij*(xInside - xOutside);
}
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{
if (!scvf.boundary())
return Stencil({scvf.insideScvIdx(), scvf.outsideScvIdx()});
else
return Stencil({scvf.insideScvIdx()});
}
private:
//! compute the mole/mass fraction at branching facets for network grids
......
......@@ -53,7 +53,6 @@ class FouriersLawImplementation<TypeTag, DiscretizationMethods::CCTpfa>
using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
using IndexType = typename GridView::IndexSet::IndexType;
using Stencil = typename std::vector<IndexType>;
using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
using Element = typename GridView::template Codim<0>::Entity;
......@@ -89,17 +88,6 @@ public:
return tij*(tInside - tOutside);
}
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{
if (!scvf.boundary())
return Stencil({scvf.insideScvIdx(), scvf.outsideScvIdx()});
else
return Stencil({scvf.insideScvIdx()});
}
private:
//! compute the temperature at branching facets for network grids
......
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*****************************************************************************
* See the file COPYING for full copying permissions. *
* *
* This program 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. *
* *
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>. *
*****************************************************************************/
/*!
* \file
* \brief Base class the flux stencil
*/
#ifndef DUMUX_DISCRETIZATION_FLUXSTENCIL_HH
#define DUMUX_DISCRETIZATION_FLUXSTENCIL_HH
#include <dumux/implicit/properties.hh>
#include <dumux/discretization/methods.hh>
namespace Dumux
{
//! Forward declaration of the upwind scheme implementation
template<class TypeTag, DiscretizationMethods Method>
class FluxStencilImplementation;
/*!
* \ingroup Discretization
* \brief The flux stencil specialized for each discretization method
* \note There might be different stencils used for e.g. advection and diffusion for schemes
* where the stencil depends on variables. Also schemes might even have solution dependent
* stencil. However, we always reserve the stencil or all DOFs that are possibly involved
* since we use the flux stencil for matrix and assembly. This might lead to some zeros stored
* in the matrix.
*/
template<class TypeTag>
using FluxStencil = FluxStencilImplementation<TypeTag, GET_PROP_VALUE(TypeTag, DiscretizationMethod)>;
//! Flux stencil for the box method
template<class TypeTag>
class FluxStencilImplementation<TypeTag, DiscretizationMethods::Box>
{
using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
using Element = typename GridView::template Codim<0>::Entity;
using IndexType = typename GridView::IndexSet::IndexType;
using Stencil = std::vector<IndexType>;
public:
// This is for compatibility with the cc methods. The flux stencil info is obsolete for the box method.
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{
return Stencil();
}
};
//! Flux stencil for the cell-centered TPFA scheme
template<class TypeTag>
class FluxStencilImplementation<TypeTag, DiscretizationMethods::CCTpfa>
{
using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
using Element = typename GridView::template Codim<0>::Entity;
using IndexType = typename GridView::IndexSet::IndexType;
using Stencil = std::vector<IndexType>;
public:
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{
if (scvf.boundary())
return Stencil({scvf.insideScvIdx()});
else if (scvf.numOutsideScvs() > 1)
{
Stencil stencil({scvf.insideScvIdx()});
for (unsigned int i = 0; i < scvf.numOutsideScvs(); ++i)
stencil.push_back(scvf.outsideScvIdx(i));
return stencil;
}
else
return Stencil({scvf.insideScvIdx(), scvf.outsideScvIdx()});
}
};
//! Specialization for cell-centered MPFA schemes
template<class TypeTag>
class FluxStencilImplementation<TypeTag, DiscretizationMethods::CCMpfa>
{
using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
using Element = typename GridView::template Codim<0>::Entity;
using IndexType = typename GridView::IndexSet::IndexType;
using Stencil = std::vector<IndexType>;
public:
static Stencil stencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{
const auto& globalFvGeometry = problem.model().globalFvGeometry();
// return the scv (element) indices in the interaction region
if (globalFvGeometry.touchesInteriorOrDomainBoundary(scvf))
return globalFvGeometry.boundaryInteractionVolumeSeed(scvf).globalScvIndices();
else
return globalFvGeometry.interactionVolumeSeed(scvf).globalScvIndices();
}
};
} // end namespace Dumux
#endif
......@@ -26,15 +26,23 @@
#include <dumux/implicit/properties.hh>
#include <dumux/discretization/methods.hh>
#include <dumux/discretization/cellcentered/mpfa/facetypes.hh>
#include <dumux/discretization/fluxstencil.hh>
#include <dumux/discretization/upwindscheme.hh>
namespace Dumux
{
namespace Properties
{
// forward declaration
}
template<class TypeTag, class UpwindScheme, class FluxStencil>
class FluxVariablesBaseImplementation;
/*!
* \ingroup Discretization
* \brief The flux variables base class class
* The upwind scheme is chosen depending on the discretization method
*/
template<class TypeTag>
using FluxVariablesBase = FluxVariablesBaseImplementation<TypeTag, UpwindScheme<TypeTag>, FluxStencil<TypeTag>>;
/*!
* \ingroup Discretization
* \brief Implementation of the base class of the flux variables
......@@ -42,7 +50,7 @@ namespace Properties
* \param TypeTag The type tag
* \param UpwindScheme The type used for the upwinding of the advective fluxes
*/
template<class TypeTag, class UpwindScheme>
template<class TypeTag, class UpwindScheme, class FluxStencil>
class FluxVariablesBaseImplementation
{
using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
......@@ -99,8 +107,15 @@ public:
return UpwindScheme::apply(*this, upwindTerm, flux, phaseIdx);
}
Stencil computeStencil(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace)
{ DUNE_THROW(Dune::InvalidStateException, "computeStencil() routine is not provided by the implementation."); }
static Stencil computeStencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvf)
{
//! Give the upwind scheme access to the cached variables
//! Forward to the discretization specific implementation
return FluxStencil::stencil(problem, element, fvGeometry, scvf);
}
private:
const Problem* problemPtr_; //! Pointer to the problem
......@@ -111,14 +126,6 @@ private:
const ElementFluxVariablesCache* elemFluxVarsCachePtr_;
};
/*!
* \ingroup Discretization
* \brief The flux variables base class class
* The upwind scheme is chosen depending on the discretization method
*/
template<class TypeTag>
using FluxVariablesBase = FluxVariablesBaseImplementation<TypeTag, UpwindScheme<TypeTag>>;
} // end namespace
} // end namespace Dumux
#endif
......@@ -65,7 +65,6 @@ class PorousMediumFluxVariablesImpl<TypeTag, true, false, false> : public FluxVa
using Element = typename GridView::template Codim<0>::Entity;
using IndexType = typename GridView::IndexSet::IndexType;
using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
using Stencil = std::vector<IndexType>;
using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
using AdvectionType = typename GET_PROP_TYPE(TypeTag, AdvectionType);
......@@ -101,12 +100,6 @@ public:
return this->applyUpwindScheme(upwindTerm, flux, phaseIdx);
}
Stencil computeStencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvFace)
{ return AdvectionType::stencil(problem, element, fvGeometry, scvFace); }
};
......@@ -120,7 +113,6 @@ class PorousMediumFluxVariablesImpl<TypeTag, true, true, false> : public FluxVar
using Element = typename GridView::template Codim<0>::Entity;
using IndexType = typename GridView::IndexSet::IndexType;
using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
using Stencil = std::vector<IndexType>;
using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
......@@ -177,28 +169,6 @@ public:
return flux;
}
Stencil computeStencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvFace)
{
// In the case of cctpfa or box the stencils for all laws are the same...
if (GET_PROP_VALUE(TypeTag, DiscretizationMethod) == DiscretizationMethods::CCTpfa
|| GET_PROP_VALUE(TypeTag, DiscretizationMethod) == DiscretizationMethods::Box)
{
return AdvectionType::stencil(problem, element, fvGeometry, scvFace);
}
// ...in general: unifiy advective and diffusive stencil
Stencil stencil = AdvectionType::stencil(problem, element, fvGeometry, scvFace);
Stencil diffusionStencil = MolecularDiffusionType::stencil(problem, element, fvGeometry, scvFace);
stencil.insert(stencil.end(), diffusionStencil.begin(), diffusionStencil.end());
std::sort(stencil.begin(), stencil.end());
stencil.erase(std::unique(stencil.begin(), stencil.end()), stencil.end());
return stencil;
}
private:
//! simple caching if advection flux is used twice with different upwind function
std::bitset<numPhases> advFluxCached_;
......@@ -215,7 +185,6 @@ class PorousMediumFluxVariablesImpl<TypeTag, true, false, true> : public FluxVar
using Element = typename GridView::template Codim<0>::Entity;
using IndexType = typename GridView::IndexSet::IndexType;
using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
using Stencil = std::vector<IndexType>;
using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
......@@ -269,29 +238,6 @@ public:
return flux;
}
Stencil computeStencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvFace)
{
// In the case of cctpfa or box the stencils for all laws are the same...
if (GET_PROP_VALUE(TypeTag, DiscretizationMethod) == DiscretizationMethods::CCTpfa
|| GET_PROP_VALUE(TypeTag, DiscretizationMethod) == DiscretizationMethods::Box)
{
return AdvectionType::stencil(problem, element, fvGeometry, scvFace);
}
// ...in general: unifiy advective and heat conduction stencil
Stencil stencil = AdvectionType::stencil(problem, element, fvGeometry, scvFace);
Stencil energyStencil = HeatConductionType::stencil(problem, element, fvGeometry, scvFace);
stencil.insert(stencil.end(), energyStencil.begin(), energyStencil.end());
std::sort(stencil.begin(), stencil.end());
stencil.erase(std::unique(stencil.begin(), stencil.end()), stencil.end());
return stencil;
}
private:
//! simple caching if advection flux is used twice with different upwind function
std::bitset<numPhases> advFluxCached_;
......@@ -308,7 +254,6 @@ class PorousMediumFluxVariablesImpl<TypeTag, true, true, true> : public FluxVari
using Element = typename GridView::template Codim<0>::Entity;
using IndexType = typename GridView::IndexSet::IndexType;
using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
using Stencil = std::vector<IndexType>;
using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
......@@ -375,31 +320,6 @@ public:
return flux;
}
Stencil computeStencil(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const SubControlVolumeFace& scvFace)
{
// In the case of cctpfa or box the stencils for all laws are the same...
if (GET_PROP_VALUE(TypeTag, DiscretizationMethod) == DiscretizationMethods::CCTpfa
|| GET_PROP_VALUE(TypeTag, DiscretizationMethod) == DiscretizationMethods::Box)
{
return AdvectionType::stencil(problem, element, fvGeometry, scvFace);
}
// ...in general: unifiy advective, diffusive and heat conduction stencil
Stencil stencil = AdvectionType::stencil(problem, element, fvGeometry, scvFace);
Stencil diffusionStencil = MolecularDiffusionType::stencil(problem, element, fvGeometry, scvFace);
Stencil energyStencil = HeatConductionType::stencil(problem, element, fvGeometry, scvFace);
stencil.insert(stencil.end(), diffusionStencil.begin(), diffusionStencil.end());
stencil.insert(stencil.end(), energyStencil.begin(), energyStencil.end());
std::sort(stencil.begin(), stencil.end());
stencil.erase(std::unique(stencil.begin(), stencil.end()), stencil.end());
return stencil;
}
private:
//! simple caching if advection flux is used twice with different upwind function
std::bitset<numPhases> advFluxCached_;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment