24#ifndef DUMUX_FLUX_OVER_SURFACE_STAGGERED_HH
25#define DUMUX_FLUX_OVER_SURFACE_STAGGERED_HH
32#include <dune/common/exceptions.hh>
33#include <dune/common/fvector.hh>
34#include <dune/geometry/type.hh>
35#include <dune/geometry/multilineargeometry.hh>
36#include <dune/geometry/referenceelements.hh>
48template<
class Gr
idVariables,
class SolutionVector,
class ModelTraits,
class LocalRes
idual>
51 using Scalar =
typename GridVariables::Scalar;
52 using GridGeometry =
typename GridVariables::GridGeometry;
53 using FVElementGeometry =
typename GridGeometry::LocalView;
54 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
55 using GridView =
typename GridGeometry::GridView;
56 using VolumeVariables =
typename GridVariables::VolumeVariables;
57 using Element =
typename GridView::template Codim<0>::Entity;
59 using CellCenterPrimaryVariables = std::decay_t<decltype(std::declval<SolutionVector>()[GridGeometry::cellCenterIdx()][0])>;
63 dim = GridView::dimension,
64 dimWorld = GridView::dimensionworld
67 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
69 static constexpr auto surfaceDim = dimWorld - 1;
70 using SurfaceGeometryType = Dune::MultiLinearGeometry< Scalar, surfaceDim, dimWorld >;
75 template<
int mydim,
int coordDim,
class Scalar=
double>
78 using Geo = SurfaceGeometryType;
83 SurfaceData(Geo&& geo)
86 geometries_.push_back(std::move(geo));
89 SurfaceData(std::vector<Geo>&& geo)
91 values_.resize(geo.size());
92 geometries_ = std::forward<decltype(geo)>(geo);
95 void addValue(
int surfaceIdx,
const CellCenterPrimaryVariables& value)
97 values_[surfaceIdx] += value;
100 void addSubSurface(Geo&& geo)
102 values_.emplace_back(0.0);
103 geometries_.push_back(std::move(geo));
106 auto& subSurfaces()
const
111 CellCenterPrimaryVariables& value(
int surfaceIdx)
const
113 return values_[surfaceIdx];
121 void printSurfaceBoundaries(
int surfaceIdx)
const
123 const auto& geometry = geometries_[surfaceIdx];
124 for(
int i = 0; i < geometry.corners(); ++i)
125 std::cout <<
"(" << geometry.corner(i) <<
") ";
130 std::fill(values_.begin(), values_.end(), CellCenterPrimaryVariables(0.0));
135 std::vector<Geo> geometries_;
136 std::vector<CellCenterPrimaryVariables> values_;
149 : gridVariables_(gridVariables),
152 static_assert(std::is_same<Sol, SolutionVector>::value,
"Make sure that sol has the same type as SolutionVector."
153 "Use StaggeredVtkOutputModule<GridVariables, decltype(sol)> when calling the constructor.");
155 verbose_ = getParamFromGroup<bool>(problem_().paramGroup(),
"FluxOverSurface.Verbose",
false);
166 surfaces_[name] = SurfaceData<surfaceDim,dim>(std::forward<
decltype(surfaces)>(surfaces));
177 void addSurface(
const std::string& name,
const GlobalPosition& p0,
const GlobalPosition& p1)
179 surfaces_[name].addSubSurface(
makeSurface(std::vector<GlobalPosition>{p0, p1}));
193 const GlobalPosition& p0,
194 const GlobalPosition& p1,
195 const GlobalPosition& p2,
196 const GlobalPosition& p3)
198 surfaces_[name].addSubSurface(
makeSurface(std::vector<GlobalPosition>{p0, p1, p2, p3}));
206 static SurfaceGeometryType
makeSurface(
const std::vector<Dune::FieldVector<Scalar, 2>>& corners)
208 return SurfaceGeometryType(Dune::GeometryTypes::line, corners);
216 static SurfaceGeometryType
makeSurface(
const std::vector<Dune::FieldVector<Scalar, 3>>& corners)
226 auto fluxType = [
this](
const auto& element,
227 const auto& fvGeometry,
228 const auto& elemVolVars,
229 const auto& elemFaceVars,
231 const auto& elemFluxVarsCache)
233 LocalResidual localResidual(&problem_());
236 return localResidual.computeBoundaryFluxForCellCenter(problem_(), element, fvGeometry, scvf, elemVolVars, elemFaceVars, {}, elemFluxVarsCache);
238 return localResidual.computeFluxForCellCenter(problem_(), element, fvGeometry, elemVolVars, elemFaceVars, scvf, elemFluxVarsCache);
249 auto fluxType = [](
const auto& element,
250 const auto& fvGeometry,
251 const auto& elemVolVars,
252 const auto& elemFaceVars,
254 const auto& elemFluxVarsCache)
256 CellCenterPrimaryVariables result(0.0);
257 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
258 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
259 const Scalar extrusionFactor =
harmonicMean(insideVolVars.extrusionFactor(), outsideVolVars.extrusionFactor());
260 result[0] = elemFaceVars[scvf].velocitySelf() * scvf.area() * extrusionFactor * scvf.directionSign();
279 template<
class FluxType>
283 for(
auto&& surface : surfaces_)
284 surface.second.resetValues();
287 std::vector<bool> dofVisited(problem_().gridGeometry().numFaceDofs(),
false);
289 auto elemVolVars =
localView(gridVariables_.curGridVolVars());
290 auto elemFluxVarsCache =
localView(gridVariables_.gridFluxVarsCache());
291 auto elemFaceVars =
localView(gridVariables_.curGridFaceVars());
293 for(
auto&& element : elements(problem_().gridGeometry().gridView()))
295 auto fvGeometry =
localView(problem_().gridGeometry());
296 fvGeometry.bind(element);
298 elemVolVars.bind(element, fvGeometry, sol_);
299 elemFaceVars.bind(element, fvGeometry, sol_);
300 elemFluxVarsCache.bind(element, fvGeometry, elemVolVars);
302 for(
auto && scvf : scvfs(fvGeometry))
304 const auto dofIdx = scvf.dofIndex();
306 if(dofVisited[dofIdx])
309 dofVisited[dofIdx] =
true;
313 for(
auto&& surface : surfaces_)
315 const auto& subSurfaces = surface.second.subSurfaces();
317 for(
int surfaceIdx = 0; surfaceIdx < subSurfaces.size(); ++surfaceIdx)
321 const auto result = fluxType(element, fvGeometry, elemVolVars, elemFaceVars, scvf, elemFluxVarsCache);
323 surface.second.addValue(surfaceIdx, result);
327 std::cout <<
"Flux at face " << scvf.center() <<
" (" << surface.first <<
"): " << result;
328 std::cout <<
" (directionIndex: " << scvf.directionIndex() <<
"; surface boundaries: ";
329 surface.second.printSurfaceBoundaries(surfaceIdx);
330 std::cout <<
", surfaceIdx " << surfaceIdx <<
")" << std::endl;
344 auto&
values(
const std::string& name)
const
346 return surfaces_.at(name).values();
356 const auto& surfaceResults =
values(name);
357 return std::accumulate(surfaceResults.begin(), surfaceResults.end(), CellCenterPrimaryVariables(0.0));
362 const auto& problem_()
const {
return gridVariables_.curGridVolVars().problem(); }
364 std::map<std::string, SurfaceData<surfaceDim ,dim> > surfaces_;
365 const GridVariables& gridVariables_;
366 const SolutionVector& sol_;
Detect if a point intersects a geometry.
Create Dune geometries from user-specified points.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
constexpr Scalar harmonicMean(Scalar x, Scalar y, Scalar wx=1.0, Scalar wy=1.0) noexcept
Calculate the (weighted) harmonic mean of two scalar values.
Definition: math.hh:68
auto makeDuneQuadrilaterial(const std::vector< Dune::FieldVector< CoordScalar, 3 > > &points)
Creates a dune quadrilateral geometry given 4 corner points.
Definition: makegeometry.hh:152
bool intersectsPointGeometry(const Dune::FieldVector< ctype, dimworld > &point, const Geometry &g)
Find out whether a point is inside a three-dimensional geometry.
Definition: intersectspointgeometry.hh:38
Class used to calculate fluxes over surfaces. This only works for the staggered grid discretization.
Definition: fluxoversurface.hh:50
std::vector< SurfaceGeometryType > SurfaceList
Definition: fluxoversurface.hh:141
auto & values(const std::string &name) const
Return the fluxes of the individual sub surface of a given name.
Definition: fluxoversurface.hh:344
void addSurface(const std::string &name, const GlobalPosition &p0, const GlobalPosition &p1)
Add a surface under a given name, specifying the surface's corner points. This is a specialization fo...
Definition: fluxoversurface.hh:177
void calculateVolumeFluxes()
Calculate the volume fluxes over all surfaces.
Definition: fluxoversurface.hh:247
void addSurface(const std::string &name, SurfaceList &&surfaces)
Add a collection of sub surfaces under a given name.
Definition: fluxoversurface.hh:164
auto netFlux(const std::string &name) const
Return the cumulative net fluxes of a surface of a given name.
Definition: fluxoversurface.hh:354
static SurfaceGeometryType makeSurface(const std::vector< Dune::FieldVector< Scalar, 2 > > &corners)
Creates a geometrical surface object for (2D).
Definition: fluxoversurface.hh:206
void addSurface(const std::string &name, const GlobalPosition &p0, const GlobalPosition &p1, const GlobalPosition &p2, const GlobalPosition &p3)
Add a surface under a given name, specifying the surface's corner points. This is a specialization fo...
Definition: fluxoversurface.hh:192
void calculateMassOrMoleFluxes()
Calculate the mass or mole fluxes over all surfaces.
Definition: fluxoversurface.hh:224
FluxOverSurface(const GridVariables &gridVariables, const Sol &sol)
The constructor.
Definition: fluxoversurface.hh:147
static SurfaceGeometryType makeSurface(const std::vector< Dune::FieldVector< Scalar, 3 > > &corners)
Creates a geometrical surface object for (3D).
Definition: fluxoversurface.hh:216
void calculateFluxes(const FluxType &fluxType)
Calculate the fluxes over all surfaces for a given flux type.
Definition: fluxoversurface.hh:280