25#ifndef DUMUX_POROUSMEDIUMFLOW_VELOCITY_HH
26#define DUMUX_POROUSMEDIUMFLOW_VELOCITY_HH
31#include <dune/common/fvector.hh>
32#include <dune/common/float_cmp.hh>
33#include <dune/geometry/referenceelements.hh>
46template<
class Gr
idVariables,
class FluxVariables>
49 using GridGeometry =
typename GridVariables::GridGeometry;
50 using FVElementGeometry =
typename GridGeometry::LocalView;
51 using SubControlVolume =
typename GridGeometry::SubControlVolume;
52 using SubControlVolumeFace =
typename GridGeometry::SubControlVolumeFace;
53 using GridView =
typename GridGeometry::GridView;
54 using Element =
typename GridView::template Codim<0>::Entity;
55 using GridVolumeVariables =
typename GridVariables::GridVolumeVariables;
56 using ElementFluxVarsCache =
typename GridVariables::GridFluxVariablesCache::LocalView;
57 using VolumeVariables =
typename GridVariables::VolumeVariables;
58 using ElementVolumeVariables =
typename GridVolumeVariables::LocalView;
59 using FluidSystem =
typename VolumeVariables::FluidSystem;
60 using Scalar =
typename GridVariables::Scalar;
62 using AdvectionType =
typename FluxVariables::AdvectionType;
64 static constexpr int dim = GridView::dimension;
65 static constexpr int dimWorld = GridView::dimensionworld;
67 static constexpr int dofCodim = isBox ? dim : 0;
70 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
71 using ReferenceElements = Dune::ReferenceElements<typename GridView::ctype, dim>;
73 using Problem =
typename GridVolumeVariables::Problem;
74 using BoundaryTypes =
typename Problem::Traits::BoundaryTypes;
86 : problem_(gridVariables.curGridVolVars().problem())
87 , gridGeometry_(gridVariables.gridGeometry())
88 , gridVariables_(gridVariables)
94 cellNum_.assign(gridGeometry_.gridView().size(dim), 0);
96 for (
const auto& element : elements(gridGeometry_.gridView()))
97 for (
unsigned int vIdx = 0; vIdx < element.subEntities(dim); ++vIdx)
98 ++cellNum_[gridGeometry_.vertexMapper().subIndex(element, vIdx, dim)];
105 const Element& element,
106 const FVElementGeometry& fvGeometry,
107 const ElementVolumeVariables& elemVolVars,
108 const ElementFluxVarsCache& elemFluxVarsCache,
111 using Velocity =
typename VelocityVector::value_type;
113 const auto geometry = element.geometry();
114 const Dune::GeometryType geomType = geometry.type();
117 auto upwindTerm = [phaseIdx](
const auto& volVars) {
return volVars.mobility(phaseIdx); };
119 if(isBox && dim == 1)
121 Velocity tmpVelocity(0.0);
122 tmpVelocity = (geometry.corner(1) - geometry.corner(0));
123 tmpVelocity /= tmpVelocity.two_norm();
125 for (
auto&& scvf : scvfs(fvGeometry))
131 FluxVariables fluxVars;
132 fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
136 Scalar localArea = scvfReferenceArea_(geomType, scvf.index());
137 Scalar flux = fluxVars.advectiveFlux(phaseIdx, upwindTerm) / localArea;
138 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
139 flux /= insideVolVars.extrusionFactor();
142 const int eIdxGlobal = gridGeometry_.elementMapper().index(element);
143 velocity[eIdxGlobal] = tmpVelocity;
149 const auto referenceElement = ReferenceElements::general(geomType);
150 const auto& localPos = referenceElement.position(0, 0);
151 const auto jacobianT2 = geometry.jacobianTransposed(localPos);
155 using ScvVelocities = Dune::BlockVector<Velocity>;
156 ScvVelocities scvVelocities(fvGeometry.numScv());
159 for (
auto&& scvf : scvfs(fvGeometry))
165 const auto localPosIP = geometry.local(scvf.ipGlobal());
168 const auto jacobianT1 = geometry.jacobianTransposed(localPosIP);
169 const auto globalNormal = scvf.unitOuterNormal();
170 GlobalPosition localNormal(0);
171 jacobianT1.mv(globalNormal, localNormal);
172 localNormal /= localNormal.two_norm();
175 FluxVariables fluxVars;
176 fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
180 Scalar localArea = scvfReferenceArea_(geomType, scvf.index());
181 Scalar flux = fluxVars.advectiveFlux(phaseIdx, upwindTerm) / localArea;
182 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
183 flux /= insideVolVars.extrusionFactor();
186 Velocity tmpVelocity = localNormal;
189 scvVelocities[scvf.insideScvIdx()] += tmpVelocity;
190 scvVelocities[scvf.outsideScvIdx()] += tmpVelocity;
194 for (
auto&& scv : scvs(fvGeometry))
196 int vIdxGlobal = scv.dofIndex();
199 Velocity scvVelocity(0);
201 jacobianT2.mtv(scvVelocities[scv.indexInElement()], scvVelocity);
202 scvVelocity /= geometry.integrationElement(localPos)*cellNum_[vIdxGlobal];
204 velocity[vIdxGlobal] += scvVelocity;
213 const int numScvfsPerFace = isMpfa ? element.template subEntity<1>(0).geometry().corners() : 1;
215 if (fvGeometry.numScvf() != element.subEntities(1)*numScvfsPerFace)
216 DUNE_THROW(Dune::NotImplemented,
"Velocity output for non-conforming grids");
218 if (!geomType.isCube() && !geomType.isSimplex())
219 DUNE_THROW(Dune::NotImplemented,
"Velocity output for other geometry types than cube and simplex");
225 std::vector<bool> handledScvf;
227 handledScvf.resize(element.subEntities(1),
false);
230 std::vector<unsigned int> scvfIndexInInside(fvGeometry.numScvf());
231 int localScvfIdx = 0;
232 for (
const auto& intersection : intersections(gridGeometry_.gridView(), element))
235 if (handledScvf[intersection.indexInInside()])
238 if (intersection.neighbor() || intersection.boundary())
240 for (
int i = 0; i < numScvfsPerFace; ++i)
241 scvfIndexInInside[localScvfIdx++] = intersection.indexInInside();
245 handledScvf[intersection.indexInInside()] =
true;
249 std::vector<Scalar> scvfFluxes(element.subEntities(1), 0.0);
251 for (
auto&& scvf : scvfs(fvGeometry))
253 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
254 if (!scvf.boundary())
256 FluxVariables fluxVars;
257 fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
258 scvfFluxes[scvfIndexInInside[localScvfIdx]] += fluxVars.advectiveFlux(phaseIdx, upwindTerm)/insideVolVars.extrusionFactor();
262 auto bcTypes = problemBoundaryTypes_(element, scvf);
263 if (bcTypes.hasOnlyDirichlet())
265 FluxVariables fluxVars;
266 fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
267 scvfFluxes[scvfIndexInInside[localScvfIdx]] += fluxVars.advectiveFlux(phaseIdx, upwindTerm)/insideVolVars.extrusionFactor();
282 for (
auto&& scvf : scvfs(fvGeometry))
286 auto bcTypes = problemBoundaryTypes_(element, scvf);
287 if (bcTypes.hasNeumann())
293 if (stationaryVelocityField)
295 const auto flux = AdvectionType::flux(problem_, element, fvGeometry, elemVolVars,
296 scvf, phaseIdx, elemFluxVarsCache);
298 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
299 scvfFluxes[scvfIndexInInside[localScvfIdx]] += flux / insideVolVars.extrusionFactor();
304 const auto neumannFlux = problem_.neumann(element, fvGeometry, elemVolVars, elemFluxVarsCache, scvf);
305 using NumEqVector = std::decay_t<
decltype(neumannFlux)>;
306 if (Dune::FloatCmp::eq<NumEqVector, Dune::FloatCmp::CmpStyle::absolute>(neumannFlux, NumEqVector(0.0), 1e-30))
307 scvfFluxes[scvfIndexInInside[localScvfIdx]] = 0;
311 else if (dim == 1 || geomType.isCube())
313 const auto fIdx = scvfIndexInInside[localScvfIdx];
314 const auto fIdxOpposite = fIdx%2 ? fIdx-1 : fIdx+1;
315 scvfFluxes[fIdx] = -scvfFluxes[fIdxOpposite];
319 else if (geomType.isSimplex())
320 scvfFluxes[scvfIndexInInside[localScvfIdx]] = 0;
323 DUNE_THROW(Dune::NotImplemented,
"Velocity computation at Neumann boundaries for cell-centered and prism/pyramid");
333 Velocity refVelocity;
336 if (dim == 1 || geomType.isCube())
338 for (
int i = 0; i < dim; i++)
339 refVelocity[i] = 0.5 * (scvfFluxes[2*i + 1] - scvfFluxes[2*i]);
342 else if (geomType.isSimplex())
344 for (
int dimIdx = 0; dimIdx < dim; dimIdx++)
346 refVelocity[dimIdx] = -scvfFluxes[dim - 1 - dimIdx];
347 for (
int fIdx = 0; fIdx < dim + 1; fIdx++)
348 refVelocity[dimIdx] += scvfFluxes[fIdx]/(dim + 1);
353 DUNE_THROW(Dune::NotImplemented,
"Velocity computation for cell-centered and prism/pyramid");
355 Velocity scvVelocity(0);
356 jacobianT2.mtv(refVelocity, scvVelocity);
358 scvVelocity /= geometry.integrationElement(localPos);
360 int eIdxGlobal = gridGeometry_.elementMapper().index(element);
362 velocity[eIdxGlobal] = scvVelocity;
371 static Scalar scvfReferenceArea_(Dune::GeometryType geomType,
int fIdx)
373 if (dim == 1 || geomType.isCube())
375 return 1.0/(1 << (dim-1));
377 else if (geomType.isTriangle())
379 static const Scalar faceToArea[] = {0.372677996249965,
382 return faceToArea[fIdx];
384 else if (geomType.isTetrahedron())
386 static const Scalar faceToArea[] = {0.102062072615966,
392 return faceToArea[fIdx];
394 else if (geomType.isPyramid())
396 static const Scalar faceToArea[] = {0.130437298687488,
404 return faceToArea[fIdx];
406 else if (geomType.isPrism())
408 static const Scalar faceToArea[] = {0.166666666666667,
417 return faceToArea[fIdx];
420 DUNE_THROW(Dune::NotImplemented,
"scvf area for unknown GeometryType");
439 template <
bool enable = isBox,
typename std::enable_if_t<!enable,
int> = 0>
440 BoundaryTypes problemBoundaryTypes_(
const Element& element,
const SubControlVolumeFace& scvf)
const
441 {
return problem_.boundaryTypes(element, scvf); }
444 template <
bool enable = isBox,
typename std::enable_if_t<enable,
int> = 0>
445 BoundaryTypes problemBoundaryTypes_(
const Element& element,
const SubControlVolumeFace& scvf)
const
446 {
return BoundaryTypes(); }
448 const Problem& problem_;
449 const GridGeometry& gridGeometry_;
450 const GridVariables& gridVariables_;
452 std::vector<int> cellNum_;
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Element solution classes and factory functions.
The available discretization methods in Dumux.
Traits of a flux variables type.
Definition: flux/traits.hh:44
static constexpr bool hasStationaryVelocityField()
Definition: flux/traits.hh:45
Velocity computation for implicit (porous media) models.
Definition: velocity.hh:48
void calculateVelocity(VelocityVector &velocity, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const ElementFluxVarsCache &elemFluxVarsCache, int phaseIdx) const
Definition: velocity.hh:104
PorousMediumFlowVelocity(const GridVariables &gridVariables)
Constructor initializes the static data with the initial solution.
Definition: velocity.hh:85
std::vector< Dune::FieldVector< Scalar, dimWorld > > VelocityVector
Definition: velocity.hh:78
static constexpr int numFluidPhases
Definition: velocity.hh:77