version 3.8
fluxoversurface.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_FLUX_OVER_SURFACE_STAGGERED_HH
13#define DUMUX_FLUX_OVER_SURFACE_STAGGERED_HH
14
15#include <numeric>
16#include <functional>
17#include <type_traits>
18#include <vector>
19
20#include <dune/common/exceptions.hh>
21#include <dune/common/fvector.hh>
22#include <dune/geometry/type.hh>
23#include <dune/geometry/multilineargeometry.hh>
24
29
30namespace Dumux {
31
36template<class GridVariables, class SolutionVector, class ModelTraits, class LocalResidual>
38{
39 using Scalar = typename GridVariables::Scalar;
40 using GridGeometry = typename GridVariables::GridGeometry;
41 using FVElementGeometry = typename GridGeometry::LocalView;
42 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
43 using Extrusion = Extrusion_t<GridGeometry>;
44 using GridView = typename GridGeometry::GridView;
45 using VolumeVariables = typename GridVariables::VolumeVariables;
46 using Element = typename GridView::template Codim<0>::Entity;
47
48 using CellCenterPrimaryVariables = std::decay_t<decltype(std::declval<SolutionVector>()[GridGeometry::cellCenterIdx()][0])>;
49
50 enum {
51 // Grid and world dimension
52 dim = GridView::dimension,
53 dimWorld = GridView::dimensionworld
54 };
55
56 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
57
58 static constexpr auto surfaceDim = dimWorld - 1;
59 using SurfaceGeometryType = Dune::MultiLinearGeometry< Scalar, surfaceDim, dimWorld >;
60
64 template<int mydim, int coordDim, class Scalar=double>
65 class SurfaceData
66 {
67 using Geo = SurfaceGeometryType;
68 public:
69
70 SurfaceData() {}
71
72 SurfaceData(Geo&& geo)
73 {
74 values_.resize(1);
75 geometries_.push_back(std::move(geo));
76 }
77
78 SurfaceData(std::vector<Geo>&& geo)
79 {
80 values_.resize(geo.size());
81 geometries_ = std::forward<decltype(geo)>(geo);
82 }
83
84 void addValue(int surfaceIdx, const CellCenterPrimaryVariables& value)
85 {
86 values_[surfaceIdx] += value;
87 }
88
89 void addSubSurface(Geo&& geo)
90 {
91 values_.emplace_back(0.0);
92 geometries_.push_back(std::move(geo));
93 }
94
95 auto& subSurfaces() const
96 {
97 return geometries_;
98 }
99
100 CellCenterPrimaryVariables& value(int surfaceIdx) const
101 {
102 return values_[surfaceIdx];
103 }
104
105 auto& values() const
106 {
107 return values_;
108 }
109
110 void printSurfaceBoundaries(int surfaceIdx) const
111 {
112 const auto& geometry = geometries_[surfaceIdx];
113 for(int i = 0; i < geometry.corners(); ++i)
114 std::cout << "(" << geometry.corner(i) << ") ";
115 }
116
117 void resetValues()
118 {
119 std::fill(values_.begin(), values_.end(), CellCenterPrimaryVariables(0.0));
120 }
121
122 private:
123
124 std::vector<Geo> geometries_;
125 std::vector<CellCenterPrimaryVariables> values_;
126 };
127
128public:
129
130 using SurfaceList = std::vector<SurfaceGeometryType>;
131
135 template<class Sol>
136 FluxOverSurface(const GridVariables& gridVariables,
137 const Sol& sol)
138 : gridVariables_(gridVariables),
139 sol_(sol)
140 {
141 static_assert(std::is_same<Sol, SolutionVector>::value, "Make sure that sol has the same type as SolutionVector."
142 "Use StaggeredVtkOutputModule<GridVariables, decltype(sol)> when calling the constructor.");
143
144 verbose_ = getParamFromGroup<bool>(problem_().paramGroup(), "FluxOverSurface.Verbose", false);
145 }
146
153 void addSurface(const std::string& name, SurfaceList&& surfaces)
154 {
155 surfaces_[name] = SurfaceData<surfaceDim,dim>(std::forward<decltype(surfaces)>(surfaces));
156 }
157
166 void addSurface(const std::string& name, const GlobalPosition& p0, const GlobalPosition& p1)
167 {
168 surfaces_[name].addSubSurface(makeSurface(std::vector<GlobalPosition>{p0, p1}));
169 }
170
181 void addSurface(const std::string& name,
182 const GlobalPosition& p0,
183 const GlobalPosition& p1,
184 const GlobalPosition& p2,
185 const GlobalPosition& p3)
186 {
187 surfaces_[name].addSubSurface(makeSurface(std::vector<GlobalPosition>{p0, p1, p2, p3}));
188 }
189
195 static SurfaceGeometryType makeSurface(const std::vector<Dune::FieldVector<Scalar, 2>>& corners)
196 {
197 return SurfaceGeometryType(Dune::GeometryTypes::line, corners);
198 }
199
205 static SurfaceGeometryType makeSurface(const std::vector<Dune::FieldVector<Scalar, 3>>& corners)
206 {
207 return makeDuneQuadrilaterial(corners);
208 }
209
214 {
215 auto fluxType = [this](const auto& element,
216 const auto& fvGeometry,
217 const auto& elemVolVars,
218 const auto& elemFaceVars,
219 const auto& scvf,
220 const auto& elemFluxVarsCache)
221 {
222 LocalResidual localResidual(&problem_());
223
224 if (scvf.boundary())
225 return localResidual.computeBoundaryFluxForCellCenter(problem_(), element, fvGeometry, scvf, elemVolVars, elemFaceVars, /*elemBcTypes*/{}, elemFluxVarsCache);
226 else
227 return localResidual.computeFluxForCellCenter(problem_(), element, fvGeometry, elemVolVars, elemFaceVars, scvf, elemFluxVarsCache);
228 };
229
230 calculateFluxes(fluxType);
231 }
232
237 {
238 auto fluxType = [](const auto& element,
239 const auto& fvGeometry,
240 const auto& elemVolVars,
241 const auto& elemFaceVars,
242 const auto& scvf,
243 const auto& elemFluxVarsCache)
244 {
245 CellCenterPrimaryVariables result(0.0);
246 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
247 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
248 const Scalar extrusionFactor = harmonicMean(insideVolVars.extrusionFactor(), outsideVolVars.extrusionFactor());
249 result[0] = elemFaceVars[scvf].velocitySelf() * Extrusion::area(fvGeometry, scvf) * extrusionFactor * scvf.directionSign();
250 return result;
251 };
252
253 calculateFluxes(fluxType);
254 }
255
268 template<class FluxType>
269 void calculateFluxes(const FluxType& fluxType)
270 {
271 // make sure to reset all the values of the surfaces, in case this method has been called already before
272 for(auto&& surface : surfaces_)
273 surface.second.resetValues();
274
275 // make sure not to iterate over the same dofs twice
276 std::vector<bool> dofVisited(problem_().gridGeometry().numFaceDofs(), false);
277
278 auto fvGeometry = localView(problem_().gridGeometry());
279 auto elemVolVars = localView(gridVariables_.curGridVolVars());
280 auto elemFaceVars = localView(gridVariables_.curGridFaceVars());
281 auto elemFluxVarsCache = localView(gridVariables_.gridFluxVarsCache());
282
283 for(auto&& element : elements(problem_().gridGeometry().gridView()))
284 {
285 fvGeometry.bind(element);
286 elemVolVars.bind(element, fvGeometry, sol_);
287 elemFaceVars.bind(element, fvGeometry, sol_);
288 elemFluxVarsCache.bind(element, fvGeometry, elemVolVars);
289
290 for(auto && scvf : scvfs(fvGeometry))
291 {
292 const auto dofIdx = scvf.dofIndex();
293 // do nothing of the dof was already visited
294 if(dofVisited[dofIdx])
295 continue;
296
297 dofVisited[dofIdx] = true;
298
299 // iterate through all surfaces and check if the flux at the given position
300 // should be accounted for in the respective surface
301 for(auto&& surface : surfaces_)
302 {
303 const auto& subSurfaces = surface.second.subSurfaces();
304
305 for(int surfaceIdx = 0; surfaceIdx < subSurfaces.size(); ++surfaceIdx)
306 {
307 if(intersectsPointGeometry(scvf.center(), subSurfaces[surfaceIdx]))
308 {
309 const auto result = fluxType(element, fvGeometry, elemVolVars, elemFaceVars, scvf, elemFluxVarsCache);
310
311 surface.second.addValue(surfaceIdx, result);
312
313 if(verbose_)
314 {
315 std::cout << "Flux at face " << scvf.center() << " (" << surface.first << "): " << result;
316 std::cout << " (directionIndex: " << scvf.directionIndex() << "; surface boundaries: ";
317 surface.second.printSurfaceBoundaries(surfaceIdx);
318 std::cout << ", surfaceIdx " << surfaceIdx << ")" << std::endl;
319 }
320 }
321 }
322 }
323 }
324 }
325 }
326
332 auto& values(const std::string& name) const
333 {
334 return surfaces_.at(name).values();
335 }
336
342 auto netFlux(const std::string& name) const
343 {
344 const auto& surfaceResults = values(name);
345 return std::accumulate(surfaceResults.begin(), surfaceResults.end(), CellCenterPrimaryVariables(0.0));
346 }
347
348private:
349
350 const auto& problem_() const { return gridVariables_.curGridVolVars().problem(); }
351
352 std::map<std::string, SurfaceData<surfaceDim ,dim> > surfaces_;
353 const GridVariables& gridVariables_;
354 const SolutionVector& sol_;
355 bool verbose_;
356};
357
358} //end namespace
359
360#endif
Class used to calculate fluxes over surfaces. This only works for the staggered grid discretization.
Definition: fluxoversurface.hh:38
std::vector< SurfaceGeometryType > SurfaceList
Definition: fluxoversurface.hh:130
auto & values(const std::string &name) const
Return the fluxes of the individual sub surface of a given name.
Definition: fluxoversurface.hh:332
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:166
void calculateVolumeFluxes()
Calculate the volume fluxes over all surfaces.
Definition: fluxoversurface.hh:236
void addSurface(const std::string &name, SurfaceList &&surfaces)
Add a collection of sub surfaces under a given name.
Definition: fluxoversurface.hh:153
auto netFlux(const std::string &name) const
Return the cumulative net fluxes of a surface of a given name.
Definition: fluxoversurface.hh:342
static SurfaceGeometryType makeSurface(const std::vector< Dune::FieldVector< Scalar, 2 > > &corners)
Creates a geometrical surface object for (2D).
Definition: fluxoversurface.hh:195
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:181
void calculateMassOrMoleFluxes()
Calculate the mass or mole fluxes over all surfaces.
Definition: fluxoversurface.hh:213
FluxOverSurface(const GridVariables &gridVariables, const Sol &sol)
The constructor.
Definition: fluxoversurface.hh:136
static SurfaceGeometryType makeSurface(const std::vector< Dune::FieldVector< Scalar, 3 > > &corners)
Creates a geometrical surface object for (3D).
Definition: fluxoversurface.hh:205
void calculateFluxes(const FluxType &fluxType)
Calculate the fluxes over all surfaces for a given flux type.
Definition: fluxoversurface.hh:269
Helper classes to compute the integration elements.
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:57
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:26
auto makeDuneQuadrilaterial(const std::vector< Dune::FieldVector< CoordScalar, 3 > > &points)
Creates a dune quadrilateral geometry given 4 corner points.
Definition: makegeometry.hh:142
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:28
Detect if a point intersects a geometry.
Create Dune geometries from user-specified points.
constexpr Line line
Definition: couplingmanager1d3d_line.hh:31
constexpr Surface surface
Definition: couplingmanager1d3d_surface.hh:37
Definition: adapt.hh:17
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition: extrusion.hh:166
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.