55 typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView,
56 typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView,
57 typename GetPropType<TypeTag, Properties::GridFluxVariablesCache>::LocalView>
61 using GridVolumeVariables =
typename GridVariables::GridVolumeVariables;
62 using ElementVolumeVariables =
typename GridVolumeVariables::LocalView;
63 using VolumeVariables =
typename GridVolumeVariables::VolumeVariables;
65 using GridFluxVariablesCache =
typename GridVariables::GridFluxVariablesCache;
66 using FluxVariablesCache =
typename GridFluxVariablesCache::FluxVariablesCache;
68 using GridFaceVariables =
typename GridVariables::GridFaceVariables;
69 using ElementFaceVariables =
typename GridFaceVariables::LocalView;
70 using FaceVariables =
typename GridFaceVariables::FaceVariables;
74 using FVElementGeometry =
typename GridGeometry::LocalView;
75 using GridView =
typename GridGeometry::GridView;
76 using Element =
typename GridView::template Codim<0>::Entity;
79 using Indices =
typename ModelTraits::Indices;
80 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
88 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
90 static constexpr auto cellCenterIdx = GridGeometry::cellCenterIdx();
91 static constexpr auto faceIdx = GridGeometry::faceIdx();
94 static constexpr bool useHigherOrder = upwindSchemeOrder > 1;
108 template<
class UpwindTerm>
111 const ElementFaceVariables& elemFaceVars,
112 const SubControlVolumeFace &scvf,
113 UpwindTerm upwindTerm)
115 const Scalar velocity = elemFaceVars[scvf].velocitySelf();
116 const bool insideIsUpstream = scvf.directionSign() ==
sign(velocity);
119 const auto& insideVolVars =
elemVolVars[scvf.insideScvIdx()];
120 const auto& outsideVolVars =
elemVolVars[scvf.outsideScvIdx()];
122 const auto& upstreamVolVars = insideIsUpstream ? insideVolVars : outsideVolVars;
123 const auto& downstreamVolVars = insideIsUpstream ? outsideVolVars : insideVolVars;
125 const Scalar flux = (upwindWeight * upwindTerm(upstreamVolVars) +
126 (1.0 - upwindWeight) * upwindTerm(downstreamVolVars))
127 * velocity * scvf.area() * scvf.directionSign();
151 const ElementFaceVariables& elemFaceVars,
152 const SubControlVolumeFace& scvf,
153 const FluxVariablesCache& fluxVarsCache)
156 auto upwindTerm = [](
const auto& volVars) {
return volVars.density(); };
159 CellCenterPrimaryVariables result(0.0);
170 const SubControlVolumeFace& scvf,
173 const ElementFaceVariables& elemFaceVars,
174 const GridFluxVariablesCache& gridFluxVarsCache)
199 const SubControlVolumeFace& scvf,
202 const ElementFaceVariables& elemFaceVars,
203 const GridFluxVariablesCache& gridFluxVarsCache)
205 FacePrimaryVariables frontalFlux(0.0);
208 const Scalar velocitySelf = elemFaceVars[scvf].velocitySelf();
209 const Scalar velocityOpposite = elemFaceVars[scvf].velocityOpposite();
212 if (
problem.enableInertiaTerms())
215 const Scalar transportingVelocity = (velocitySelf + velocityOpposite) * 0.5;
218 * transportingVelocity * -1.0 * scvf.directionSign();
223 const auto& insideVolVars =
elemVolVars[scvf.insideScvIdx()];
228 static const bool enableUnsymmetrizedVelocityGradient
230 const Scalar factor = enableUnsymmetrizedVelocityGradient ? 1.0 : 2.0;
231 frontalFlux -= factor * insideVolVars.effectiveViscosity() * velocityGrad_ii;
237 const Scalar pressure = normalizePressure ?
238 insideVolVars.pressure() -
problem.initial(scvf)[Indices::pressureIdx]
239 : insideVolVars.pressure();
243 frontalFlux += pressure * -1.0 * scvf.directionSign();
247 return frontalFlux * scvf.area() * insideVolVars.extrusionFactor();
269 const SubControlVolumeFace& scvf,
272 const ElementFaceVariables& elemFaceVars,
273 const GridFluxVariablesCache& gridFluxVarsCache)
275 FacePrimaryVariables lateralFlux(0.0);
276 const auto& faceVars = elemFaceVars[scvf];
277 const std::size_t numSubFaces = scvf.pairData().size();
281 std::optional<BoundaryTypes> currentScvfBoundaryTypes;
283 currentScvfBoundaryTypes.emplace(
problem.boundaryTypes(
element, scvf));
286 for (
int localSubFaceIdx = 0; localSubFaceIdx < numSubFaces; ++localSubFaceIdx)
288 const auto eIdx = scvf.insideScvIdx();
290 const auto& lateralScvf =
fvGeometry.scvf(eIdx, scvf.pairData(localSubFaceIdx).localLateralFaceIdx);
293 std::optional<BoundaryTypes> lateralFaceBoundaryTypes;
297 if (lateralScvf.boundary())
310 lateralFaceBoundaryTypes.emplace(
problem.boundaryTypes(
element, lateralScvf));
316 if (currentScvfBoundaryTypes)
319 if (currentScvfBoundaryTypes->isNeumann(Indices::velocity(lateralScvf.directionIndex())))
322 const auto& lateralStaggeredFaceCenter = lateralStaggeredFaceCenter_(scvf, localSubFaceIdx);
324 scvf.makeBoundaryFace(lateralStaggeredFaceCenter))[Indices::velocity(lateralScvf.directionIndex())]
325 * extrusionFactor_(
elemVolVars, lateralScvf) * lateralScvf.area() * 0.5
326 * lateralScvf.directionSign();
334 if (currentScvfBoundaryTypes->isBeaversJoseph(Indices::velocity(lateralScvf.directionIndex())) && lateralFaceBoundaryTypes &&
335 lateralFaceBoundaryTypes->isNeumann(Indices::velocity(scvf.directionIndex())))
337 const auto& lateralStaggeredFaceCenter = lateralStaggeredFaceCenter_(scvf, localSubFaceIdx);
339 lateralScvf.makeBoundaryFace(lateralStaggeredFaceCenter))[Indices::velocity(scvf.directionIndex())]
340 * extrusionFactor_(
elemVolVars, lateralScvf) * lateralScvf.area() * 0.5
341 * lateralScvf.directionSign();
348 if (lateralScvf.boundary())
352 if (lateralFaceBoundaryTypes->isSymmetry())
356 if (lateralFaceBoundaryTypes->isNeumann(Indices::velocity(scvf.directionIndex())))
360 const auto& lateralStaggeredFaceCenter = lateralStaggeredFaceCenter_(scvf, localSubFaceIdx);
361 const auto lateralBoundaryFace = lateralScvf.makeBoundaryFace(lateralStaggeredFaceCenter);
363 *
elemVolVars[lateralScvf.insideScvIdx()].extrusionFactor() * lateralScvf.area() * 0.5;
373 if (lateralFaceBoundaryTypes)
375 std::bitset<3> admittableBcTypes;
376 admittableBcTypes.set(0, lateralFaceBoundaryTypes->isDirichlet(Indices::pressureIdx));
377 admittableBcTypes.set(1, lateralFaceBoundaryTypes->isDirichlet(Indices::velocity(scvf.directionIndex())));
378 admittableBcTypes.set(2, lateralFaceBoundaryTypes->isBeaversJoseph(Indices::velocity(scvf.directionIndex())));
379 if (admittableBcTypes.count() != 1)
381 DUNE_THROW(Dune::InvalidStateException,
"Invalid boundary conditions for lateral scvf "
382 "for the momentum equations at global position " << lateralStaggeredFaceCenter_(scvf, localSubFaceIdx)
383 <<
", current scvf global position " << scvf.center());
388 if (
problem.enableInertiaTerms())
392 currentScvfBoundaryTypes, lateralFaceBoundaryTypes,
397 currentScvfBoundaryTypes, lateralFaceBoundaryTypes,
421 const SubControlVolumeFace& scvf,
423 const ElementFaceVariables& elemFaceVars)
const
425 FacePrimaryVariables inOrOutflow(0.0);
426 const auto& insideVolVars =
elemVolVars[scvf.insideScvIdx()];
429 if (
problem.enableInertiaTerms())
431 const Scalar velocitySelf = elemFaceVars[scvf].velocitySelf();
432 const auto& outsideVolVars =
elemVolVars[scvf.outsideScvIdx()];
433 const auto& upVolVars = (scvf.directionSign() ==
sign(velocitySelf)) ?
434 insideVolVars : outsideVolVars;
436 inOrOutflow += velocitySelf * velocitySelf * upVolVars.density();
440 const Scalar boundaryPressure = normalizePressure
442 problem.initial(scvf)[Indices::pressureIdx])
444 inOrOutflow += boundaryPressure;
447 return inOrOutflow * scvf.directionSign() * scvf.area() * insideVolVars.extrusionFactor();
473 FacePrimaryVariables computeAdvectivePartOfLateralMomentumFlux_(
const Problem& problem,
474 const FVElementGeometry& fvGeometry,
475 const Element& element,
476 const SubControlVolumeFace& scvf,
477 const ElementVolumeVariables& elemVolVars,
478 const FaceVariables& faceVars,
479 const GridFluxVariablesCache& gridFluxVarsCache,
480 const std::optional<BoundaryTypes>& currentScvfBoundaryTypes,
481 const std::optional<BoundaryTypes>& lateralFaceBoundaryTypes,
482 const int localSubFaceIdx)
484 const auto eIdx = scvf.insideScvIdx();
485 const auto& lateralFace = fvGeometry.scvf(eIdx, scvf.pairData(localSubFaceIdx).localLateralFaceIdx);
489 const Scalar transportingVelocity = [&]()
491 if (!scvf.boundary())
492 return faceVars.velocityLateralInside(localSubFaceIdx);
496 const BoundaryTypes bcTypes = problem.boundaryTypes(element, scvf);
498 if (bcTypes.
isDirichlet(Indices::velocity(lateralFace.directionIndex())))
502 const auto& lateralBoundaryFacePos = lateralStaggeredFaceCenter_(scvf, localSubFaceIdx);
503 return problem.dirichlet(element, scvf.makeBoundaryFace(lateralBoundaryFacePos))[Indices::velocity(lateralFace.directionIndex())];
505 else if (bcTypes.isBeaversJoseph(Indices::velocity(lateralFace.directionIndex())))
507 return VelocityGradients::beaversJosephVelocityAtCurrentScvf(problem, element, fvGeometry, scvf, faceVars,
508 currentScvfBoundaryTypes, lateralFaceBoundaryTypes, localSubFaceIdx);
511 return faceVars.velocityLateralInside(localSubFaceIdx);
516 gridFluxVarsCache, localSubFaceIdx, currentScvfBoundaryTypes, lateralFaceBoundaryTypes)
517 * transportingVelocity * lateralFace.directionSign() * lateralFace.area() * 0.5 * extrusionFactor_(elemVolVars, lateralFace);
542 FacePrimaryVariables computeDiffusivePartOfLateralMomentumFlux_(
const Problem& problem,
543 const FVElementGeometry& fvGeometry,
544 const Element& element,
545 const SubControlVolumeFace& scvf,
546 const ElementVolumeVariables& elemVolVars,
547 const FaceVariables& faceVars,
548 const std::optional<BoundaryTypes>& currentScvfBoundaryTypes,
549 const std::optional<BoundaryTypes>& lateralFaceBoundaryTypes,
550 const int localSubFaceIdx)
552 const auto eIdx = scvf.insideScvIdx();
553 const auto& lateralFace = fvGeometry.scvf(eIdx, scvf.pairData(localSubFaceIdx).localLateralFaceIdx);
555 FacePrimaryVariables lateralDiffusiveFlux(0.0);
557 static const bool enableUnsymmetrizedVelocityGradient
563 const auto& insideVolVars = elemVolVars[lateralFace.insideScvIdx()];
564 const auto& outsideVolVars = elemVolVars[lateralFace.outsideScvIdx()];
567 const Scalar muAvg = lateralFace.boundary()
568 ? insideVolVars.effectiveViscosity()
569 : (insideVolVars.effectiveViscosity() + outsideVolVars.effectiveViscosity()) * 0.5;
572 if (!enableUnsymmetrizedVelocityGradient)
574 if (!scvf.boundary() ||
575 currentScvfBoundaryTypes->isDirichlet(Indices::velocity(lateralFace.directionIndex())) ||
576 currentScvfBoundaryTypes->isBeaversJoseph(Indices::velocity(lateralFace.directionIndex())))
578 const Scalar velocityGrad_ji = VelocityGradients::velocityGradJI(problem, element, fvGeometry, scvf, faceVars, currentScvfBoundaryTypes, lateralFaceBoundaryTypes, localSubFaceIdx);
580 lateralDiffusiveFlux -= muAvg * velocityGrad_ji * lateralFace.directionSign();
587 if (!lateralFace.boundary() || !lateralFaceBoundaryTypes->isDirichlet(Indices::pressureIdx))
589 const Scalar velocityGrad_ij = VelocityGradients::velocityGradIJ(problem, element, fvGeometry, scvf, faceVars, currentScvfBoundaryTypes, lateralFaceBoundaryTypes, localSubFaceIdx);
590 lateralDiffusiveFlux -= muAvg * velocityGrad_ij * lateralFace.directionSign();
594 return lateralDiffusiveFlux * lateralFace.area() * 0.5 * extrusionFactor_(elemVolVars, lateralFace);
611 const GlobalPosition& lateralStaggeredFaceCenter_(
const SubControlVolumeFace& scvf,
const int localSubFaceIdx)
const
613 return scvf.pairData(localSubFaceIdx).lateralStaggeredFaceCenter;
617 static Scalar extrusionFactor_(
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace& scvf)
619 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
620 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
621 return harmonicMean(insideVolVars.extrusionFactor(), outsideVolVars.extrusionFactor());
625 template<
class ...Args,
bool turbulenceModel = ModelTraits::usesTurbulenceModel(), std::enable_if_t<!turbulenceModel, int> = 0>
626 bool incorporateWallFunction_(Args&&... args)
const
630 template<
bool turbulenceModel = ModelTraits::usesTurbulenceModel(), std::enable_if_t<turbulenceModel,
int> = 0>
631 bool incorporateWallFunction_(FacePrimaryVariables& lateralFlux,
632 const Problem& problem,
633 const Element& element,
634 const FVElementGeometry& fvGeometry,
635 const SubControlVolumeFace& scvf,
636 const ElementVolumeVariables& elemVolVars,
637 const ElementFaceVariables& elemFaceVars,
638 const std::size_t localSubFaceIdx)
const
640 const auto eIdx = scvf.insideScvIdx();
641 const auto& lateralScvf = fvGeometry.scvf(eIdx, scvf.pairData(localSubFaceIdx).localLateralFaceIdx);
643 if (problem.useWallFunction(element, lateralScvf, Indices::velocity(scvf.directionIndex())))
645 const auto& lateralStaggeredFaceCenter = lateralStaggeredFaceCenter_(scvf, localSubFaceIdx);
646 const auto lateralBoundaryFace = lateralScvf.makeBoundaryFace(lateralStaggeredFaceCenter);
647 lateralFlux += problem.wallFunction(element, fvGeometry, elemVolVars, elemFaceVars, scvf, lateralBoundaryFace)[Indices::velocity(scvf.directionIndex())]
648 * extrusionFactor_(elemVolVars, lateralScvf) * lateralScvf.area() * 0.5;