24#ifndef DUMUX_NAVIERSTOKES_STAGGERED_UPWINDVARIABLES_HH
25#define DUMUX_NAVIERSTOKES_STAGGERED_UPWINDVARIABLES_HH
44template<
class TypeTag,
int upwindSchemeOrder>
49 using GridVolumeVariables =
typename GridVariables::GridVolumeVariables;
50 using ElementVolumeVariables =
typename GridVolumeVariables::LocalView;
51 using VolumeVariables =
typename GridVolumeVariables::VolumeVariables;
53 using GridFluxVariablesCache =
typename GridVariables::GridFluxVariablesCache;
54 using FluxVariablesCache =
typename GridFluxVariablesCache::FluxVariablesCache;
56 using GridFaceVariables =
typename GridVariables::GridFaceVariables;
57 using ElementFaceVariables =
typename GridFaceVariables::LocalView;
58 using FaceVariables =
typename GridFaceVariables::FaceVariables;
62 using FVElementGeometry =
typename GridGeometry::LocalView;
63 using GridView =
typename GridGeometry::GridView;
64 using Element =
typename GridView::template Codim<0>::Entity;
68 using SubControlVolume =
typename FVElementGeometry::SubControlVolume;
69 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
75 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
76 static constexpr bool useHigherOrder = upwindSchemeOrder > 1;
88 const ElementFaceVariables& elemFaceVars,
89 const ElementVolumeVariables& elemVolVars,
90 const GridFluxVariablesCache& gridFluxVarsCache,
91 const Scalar transportingVelocity)
93 const bool canHigherOrder = canFrontalSecondOrder_(scvf, transportingVelocity, std::integral_constant<bool, useHigherOrder>{});
97 const auto upwindingMomenta = getFrontalUpwindingMomenta_(scvf, elemFaceVars, elemVolVars[scvf.insideScvIdx()].density(),
98 transportingVelocity, std::integral_constant<bool, useHigherOrder>{});
99 return doFrontalMomentumUpwinding_(scvf, upwindingMomenta, transportingVelocity, gridFluxVarsCache);
103 const auto upwindingMomenta = getFrontalUpwindingMomenta_(scvf, elemFaceVars, elemVolVars[scvf.insideScvIdx()].density(),
104 transportingVelocity, std::integral_constant<bool, false>{});
105 return doFrontalMomentumUpwinding_(scvf, upwindingMomenta, transportingVelocity, gridFluxVarsCache);
119 const FVElementGeometry& fvGeometry,
120 const Element& element,
121 const SubControlVolumeFace& scvf,
122 const ElementVolumeVariables& elemVolVars,
123 const FaceVariables& faceVars,
124 const GridFluxVariablesCache& gridFluxVarsCache,
125 const int localSubFaceIdx,
126 const Dune::Std::optional<BoundaryTypes>& currentScvfBoundaryTypes,
127 const Dune::Std::optional<BoundaryTypes>& lateralFaceBoundaryTypes)
129 const auto eIdx = scvf.insideScvIdx();
130 const auto& lateralFace = fvGeometry.scvf(eIdx, scvf.pairData(localSubFaceIdx).localLateralFaceIdx);
134 const Scalar transportingVelocity = faceVars.velocityLateralInside(localSubFaceIdx);
137 const bool selfIsUpstream = ( lateralFace.directionSign() ==
sign(transportingVelocity) );
139 const bool canHigherOrder = canLateralSecondOrder_(scvf, selfIsUpstream, localSubFaceIdx, std::integral_constant<bool, useHigherOrder>{});
143 const auto parallelUpwindingMomenta = getLateralUpwindingMomenta_(problem, fvGeometry, element, scvf, elemVolVars, faceVars,
144 transportingVelocity, localSubFaceIdx, currentScvfBoundaryTypes,
145 lateralFaceBoundaryTypes, std::integral_constant<bool, useHigherOrder>{});
146 return doLateralMomentumUpwinding_(fvGeometry, scvf, parallelUpwindingMomenta, transportingVelocity, localSubFaceIdx, gridFluxVarsCache);
150 const auto parallelUpwindingMomenta = getLateralUpwindingMomenta_(problem, fvGeometry, element, scvf, elemVolVars, faceVars,
151 transportingVelocity, localSubFaceIdx, currentScvfBoundaryTypes,
152 lateralFaceBoundaryTypes, std::integral_constant<bool, false>{});
153 return doLateralMomentumUpwinding_(fvGeometry, scvf, parallelUpwindingMomenta, transportingVelocity, localSubFaceIdx, gridFluxVarsCache);
168 static bool canFrontalSecondOrder_(
const SubControlVolumeFace& ownScvf,
169 const Scalar transportingVelocity,
186 static bool canFrontalSecondOrder_(
const SubControlVolumeFace& ownScvf,
187 const Scalar transportingVelocity,
191 const bool selfIsUpstream = ownScvf.directionSign() !=
sign(transportingVelocity);
192 return selfIsUpstream ? ownScvf.hasForwardNeighbor(0) : ownScvf.hasBackwardNeighbor(0);
204 static std::array<Scalar, 2> getFrontalUpwindingMomenta_(
const SubControlVolumeFace& scvf,
205 const ElementFaceVariables& elemFaceVars,
207 const Scalar transportingVelocity,
210 const Scalar momentumSelf = elemFaceVars[scvf].velocitySelf() *
density;
211 const Scalar momentumOpposite = elemFaceVars[scvf].velocityOpposite() *
density;
212 const bool selfIsUpstream = scvf.directionSign() !=
sign(transportingVelocity);
214 return selfIsUpstream ? std::array<Scalar, 2>{momentumOpposite, momentumSelf}
215 : std::array<Scalar, 2>{momentumSelf, momentumOpposite};
227 static std::array<Scalar, 3> getFrontalUpwindingMomenta_(
const SubControlVolumeFace& scvf,
228 const ElementFaceVariables& elemFaceVars,
230 const Scalar transportingVelocity,
233 const bool selfIsUpstream = scvf.directionSign() !=
sign(transportingVelocity);
234 std::array<Scalar, 3> momenta;
238 momenta[0] = elemFaceVars[scvf].velocityOpposite() *
density;
239 momenta[1] = elemFaceVars[scvf].velocitySelf() *
density;
240 momenta[2] = elemFaceVars[scvf].velocityForward(0) *
density;
244 momenta[0] = elemFaceVars[scvf].velocitySelf() *
density;
245 momenta[1] = elemFaceVars[scvf].velocityOpposite() *
density;
246 momenta[2] = elemFaceVars[scvf].velocityBackward(0) *
density;
260 static Scalar doFrontalMomentumUpwinding_(
const SubControlVolumeFace& scvf,
261 const std::array<Scalar, 2>& momenta,
262 const Scalar transportingVelocity,
263 const GridFluxVariablesCache& gridFluxVarsCache)
265 const auto& upwindScheme = gridFluxVarsCache.staggeredUpwindMethods();
266 return upwindScheme.upwind(momenta[0], momenta[1]);
277 template<
bool enable = useHigherOrder, std::enable_if_t<enable,
int> = 0>
278 static Scalar doFrontalMomentumUpwinding_(
const SubControlVolumeFace& scvf,
279 const std::array<Scalar, 3>& momenta,
280 const Scalar transportingVelocity,
281 const GridFluxVariablesCache& gridFluxVarsCache)
283 const auto& upwindScheme = gridFluxVarsCache.staggeredUpwindMethods();
284 const bool selfIsUpstream = scvf.directionSign() !=
sign(transportingVelocity);
285 std::array<Scalar,3> distances = getFrontalDistances_(scvf, selfIsUpstream);
286 return upwindScheme.tvd(momenta, distances, selfIsUpstream, upwindScheme.tvdApproach());
295 template<
bool enable = useHigherOrder, std::enable_if_t<enable,
int> = 0>
296 static std::array<Scalar, 3> getFrontalDistances_(
const SubControlVolumeFace& ownScvf,
297 const bool selfIsUpstream)
301 std::array<Scalar, 3> distances;
305 distances[0] = ownScvf.selfToOppositeDistance();
306 distances[1] = ownScvf.axisData().inAxisForwardDistances[0];
307 distances[2] = 0.5 * (ownScvf.axisData().selfToOppositeDistance + ownScvf.axisData().inAxisBackwardDistances[0]);
311 distances[0] = ownScvf.selfToOppositeDistance();
312 distances[1] = ownScvf.axisData().inAxisBackwardDistances[0];
313 distances[2] = 0.5 * (ownScvf.axisData().selfToOppositeDistance + ownScvf.axisData().inAxisForwardDistances[0]);
329 static bool canLateralSecondOrder_(
const SubControlVolumeFace& ownScvf,
330 const bool selfIsUpstream,
331 const int localSubFaceIdx,
343 return ownScvf.hasParallelNeighbor(localSubFaceIdx, 0);
351 static bool canLateralSecondOrder_(
const SubControlVolumeFace& ownScvf,
352 const bool selfIsUpstream,
353 const int localSubFaceIdx,
363 static std::array<Scalar, 3> getLateralUpwindingMomenta_(
const Problem& problem,
364 const FVElementGeometry& fvGeometry,
365 const Element& element,
366 const SubControlVolumeFace& ownScvf,
367 const ElementVolumeVariables& elemVolVars,
368 const FaceVariables& faceVars,
369 const Scalar transportingVelocity,
370 const int localSubFaceIdx,
371 const Dune::Std::optional<BoundaryTypes>& currentScvfBoundaryTypes,
372 const Dune::Std::optional<BoundaryTypes>& lateralFaceBoundaryTypes,
375 const SubControlVolumeFace& lateralFace = fvGeometry.scvf(ownScvf.insideScvIdx(), ownScvf.pairData(localSubFaceIdx).localLateralFaceIdx);
378 const auto& insideVolVars = elemVolVars[lateralFace.insideScvIdx()];
379 const auto& outsideVolVars = elemVolVars[lateralFace.outsideScvIdx()];
383 if (!ownScvf.hasParallelNeighbor(localSubFaceIdx, 0))
385 const Scalar boundaryMomentum = getParallelVelocityFromBoundary_(problem, element, fvGeometry, ownScvf,
386 faceVars, currentScvfBoundaryTypes, lateralFaceBoundaryTypes,
387 localSubFaceIdx) * insideVolVars.density();
389 return std::array<Scalar, 3>{boundaryMomentum, boundaryMomentum, boundaryMomentum};
393 const bool selfIsUpstream = lateralFace.directionSign() ==
sign(transportingVelocity);
395 std::array<Scalar, 3> momenta;
399 momenta[1] = faceVars.velocitySelf() * insideVolVars.density();
401 if (ownScvf.hasParallelNeighbor(localSubFaceIdx, 0))
402 momenta[0] = faceVars.velocityParallel(localSubFaceIdx, 0) * insideVolVars.density();
404 momenta[0] = getParallelVelocityFromBoundary_(problem, element, fvGeometry, ownScvf,
405 faceVars, currentScvfBoundaryTypes, lateralFaceBoundaryTypes,
406 localSubFaceIdx) * insideVolVars.density();
409 const int oppositeSubFaceIdx = localSubFaceIdx % 2 ? localSubFaceIdx - 1 : localSubFaceIdx + 1;
412 if (ownScvf.hasParallelNeighbor(oppositeSubFaceIdx, 0))
413 momenta[2] = faceVars.velocityParallel(oppositeSubFaceIdx, 0) * insideVolVars.density();
415 momenta[2] = getParallelVelocityFromOtherBoundary_(problem, fvGeometry, ownScvf,
416 oppositeSubFaceIdx, element,
417 (momenta[1]/insideVolVars.density())) * insideVolVars.density();
421 momenta[0] = faceVars.velocitySelf() * outsideVolVars.density();
422 momenta[1] = faceVars.velocityParallel(localSubFaceIdx, 0) * outsideVolVars.density();
425 if (ownScvf.hasParallelNeighbor(localSubFaceIdx, 1))
426 momenta[2] = faceVars.velocityParallel(localSubFaceIdx, 1) * outsideVolVars.density();
429 const Element& elementParallel = fvGeometry.gridGeometry().element(lateralFace.outsideScvIdx());
430 const SubControlVolumeFace& firstParallelScvf = fvGeometry.scvf(lateralFace.outsideScvIdx(), ownScvf.localFaceIdx());
431 momenta[2] = getParallelVelocityFromOtherBoundary_(problem, fvGeometry, firstParallelScvf,
432 localSubFaceIdx, elementParallel,
433 (momenta[1]/outsideVolVars.density())) * outsideVolVars.density();
445 static std::array<Scalar, 2> getLateralUpwindingMomenta_(
const Problem& problem,
446 const FVElementGeometry& fvGeometry,
447 const Element& element,
448 const SubControlVolumeFace& ownScvf,
449 const ElementVolumeVariables& elemVolVars,
450 const FaceVariables& faceVars,
451 const Scalar transportingVelocity,
452 const int localSubFaceIdx,
453 const Dune::Std::optional<BoundaryTypes>& currentScvfBoundaryTypes,
454 const Dune::Std::optional<BoundaryTypes>& lateralFaceBoundaryTypes,
458 const SubControlVolumeFace& lateralFace = fvGeometry.scvf(ownScvf.insideScvIdx(), ownScvf.pairData(localSubFaceIdx).localLateralFaceIdx);
461 const auto& insideVolVars = elemVolVars[lateralFace.insideScvIdx()];
462 const auto& outsideVolVars = elemVolVars[lateralFace.outsideScvIdx()];
464 const Scalar momentumParallel = ownScvf.hasParallelNeighbor(localSubFaceIdx, 0)
465 ? faceVars.velocityParallel(localSubFaceIdx, 0) * outsideVolVars.density()
466 : (getParallelVelocityFromBoundary_(problem, element, fvGeometry, ownScvf,
467 faceVars, currentScvfBoundaryTypes, lateralFaceBoundaryTypes,
469 * insideVolVars.density());
473 if (!ownScvf.hasParallelNeighbor(localSubFaceIdx, 0))
474 return std::array<Scalar, 2>{momentumParallel, momentumParallel};
476 const bool selfIsUpstream = lateralFace.directionSign() ==
sign(transportingVelocity);
477 const Scalar momentumSelf = faceVars.velocitySelf() * insideVolVars.density();
479 return selfIsUpstream ? std::array<Scalar, 2>{momentumParallel, momentumSelf}
480 : std::array<Scalar, 2>{momentumSelf, momentumParallel};
488 static Scalar doLateralMomentumUpwinding_(
const FVElementGeometry& fvGeometry,
489 const SubControlVolumeFace& scvf,
490 const std::array<Scalar, 2>& momenta,
491 const Scalar transportingVelocity,
492 const int localSubFaceIdx,
493 const GridFluxVariablesCache& gridFluxVarsCache)
495 return doFrontalMomentumUpwinding_(scvf, momenta, transportingVelocity, gridFluxVarsCache);
507 static Scalar doLateralMomentumUpwinding_(
const FVElementGeometry& fvGeometry,
508 const SubControlVolumeFace& scvf,
509 const std::array<Scalar, 3>& momenta,
510 const Scalar transportingVelocity,
511 const int localSubFaceIdx,
512 const GridFluxVariablesCache& gridFluxVarsCache)
514 const auto eIdx = scvf.insideScvIdx();
515 const auto& lateralFace = fvGeometry.scvf(eIdx, scvf.pairData(localSubFaceIdx).localLateralFaceIdx);
517 const bool selfIsUpstream = ( lateralFace.directionSign() ==
sign(transportingVelocity) );
518 const auto& upwindScheme = gridFluxVarsCache.staggeredUpwindMethods();
519 std::array<Scalar,3> distances = getLateralDistances_(scvf, localSubFaceIdx, selfIsUpstream);
520 return upwindScheme.tvd(momenta, distances, selfIsUpstream, upwindScheme.tvdApproach());
530 template<
bool enable = useHigherOrder, std::enable_if_t<enable,
int> = 0>
531 static std::array<Scalar, 3> getLateralDistances_(
const SubControlVolumeFace& ownScvf,
532 const int localSubFaceIdx,
533 const bool selfIsUpstream)
536 std::array<Scalar, 3> distances;
541 const int oppositeSubFaceIdx = localSubFaceIdx % 2 ? localSubFaceIdx - 1 : localSubFaceIdx + 1;
543 distances[0] = ownScvf.parallelDofsDistance(localSubFaceIdx, 0);
544 distances[1] = ownScvf.parallelDofsDistance(oppositeSubFaceIdx, 0);
545 if (ownScvf.hasParallelNeighbor(localSubFaceIdx, 0))
546 distances[2] = ownScvf.pairData(localSubFaceIdx).parallelCellWidths[0];
548 distances[2] = ownScvf.area() / 2.0;
552 distances[0] = ownScvf.parallelDofsDistance(localSubFaceIdx, 0);
553 distances[1] = ownScvf.parallelDofsDistance(localSubFaceIdx, 1);
554 distances[2] = ownScvf.pairData(localSubFaceIdx).parallelCellWidths[0];
572 static Scalar getParallelVelocityFromBoundary_(
const Problem& problem,
573 const Element& element,
574 const FVElementGeometry& fvGeometry,
575 const SubControlVolumeFace& scvf,
576 const FaceVariables& faceVars,
577 const Dune::Std::optional<BoundaryTypes>& currentScvfBoundaryTypes,
578 const Dune::Std::optional<BoundaryTypes>& lateralFaceBoundaryTypes,
579 const int localSubFaceIdx)
582 const bool lateralFaceHasDirichletPressure = lateralFaceBoundaryTypes && lateralFaceBoundaryTypes->isDirichlet(Indices::pressureIdx);
583 const bool lateralFaceHasBJS = lateralFaceBoundaryTypes && lateralFaceBoundaryTypes->isBJS(Indices::velocity(scvf.directionIndex()));
584 const Scalar velocitySelf = faceVars.velocitySelf();
588 if (lateralFaceHasDirichletPressure)
591 if (lateralFaceHasBJS)
593 const auto eIdx = scvf.insideScvIdx();
594 const auto& lateralFace = fvGeometry.scvf(eIdx, scvf.pairData(localSubFaceIdx).localLateralFaceIdx);
596 currentScvfBoundaryTypes, lateralFaceBoundaryTypes, localSubFaceIdx);
598 const SubControlVolume& scv = fvGeometry.scv(scvf.insideScvIdx());
599 return problem.beaversJosephVelocity(element, scv, lateralFace, velocitySelf, velocityGrad_ji);
612 const auto ghostFace = makeParallelGhostFace_(scvf, localSubFaceIdx);
613 return problem.dirichlet(element, ghostFace)[Indices::velocity(scvf.directionIndex())];
626 static Scalar getParallelVelocityFromOtherBoundary_(
const Problem& problem,
627 const FVElementGeometry& fvGeometry,
628 const SubControlVolumeFace& scvf,
630 const Element& boundaryElement,
631 const Scalar parallelVelocity)
634 const SubControlVolumeFace& lateralScvf = fvGeometry.scvf(scvf.insideScvIdx(), scvf.pairData(localIdx).localLateralFaceIdx);
635 GlobalPosition lateralBoundaryFaceCenter = scvf.pairData(localIdx).lateralStaggeredFaceCenter + lateralScvf.center();
636 lateralBoundaryFaceCenter *= 0.5;
647 const SubControlVolumeFace lateralBoundaryFace = lateralScvf.makeBoundaryFace(lateralBoundaryFaceCenter);
652 const auto bcTypes = problem.boundaryTypes(boundaryElement, lateralBoundaryFace);
654 if (bcTypes.isDirichlet(Indices::velocity(scvf.directionIndex())))
665 const SubControlVolumeFace ghostFace = makeParallelGhostFace_(scvf, localIdx);
666 return problem.dirichlet(boundaryElement, ghostFace)[Indices::velocity(scvf.directionIndex())];
668 else if (bcTypes.isSymmetry() || bcTypes.isDirichlet(Indices::pressureIdx))
669 return parallelVelocity;
670 else if (bcTypes.isBJS(Indices::velocity(scvf.directionIndex())))
672 const SubControlVolume& scv = fvGeometry.scv(scvf.insideScvIdx());
673 return problem.bjsVelocity(boundaryElement, scv, lateralScvf, parallelVelocity);
678 DUNE_THROW(Dune::InvalidStateException,
"Something went wrong with the boundary conditions for the momentum equations at global position " << lateralBoundaryFaceCenter);
683 static SubControlVolumeFace makeParallelGhostFace_(
const SubControlVolumeFace& ownScvf,
const int localSubFaceIdx)
685 return ownScvf.makeBoundaryFace(ownScvf.pairData(localSubFaceIdx).lateralStaggeredFaceCenter);
Some exceptions thrown in DuMux
Define some often used mathematical functions.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
The available discretization methods in Dumux.
This file contains different higher order methods for approximating the velocity.
constexpr int sign(const ValueType &value) noexcept
Sign or signum function.
Definition: math.hh:618
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:149
Property tag Indices
Definition: porousmediumflow/sequential/properties.hh:59
std::string density(int phaseIdx) noexcept
I/O name of density for multiphase systems.
Definition: name.hh:65
The upwinding variables class for the Navier-Stokes model using the staggered grid discretization.
Definition: staggeredupwindfluxvariables.hh:46
static FacePrimaryVariables computeUpwindedFrontalMomentum(const SubControlVolumeFace &scvf, const ElementFaceVariables &elemFaceVars, const ElementVolumeVariables &elemVolVars, const GridFluxVariablesCache &gridFluxVarsCache, const Scalar transportingVelocity)
Returns the momentum in the frontal directon.
Definition: staggeredupwindfluxvariables.hh:87
static FacePrimaryVariables computeUpwindedLateralMomentum(const Problem &problem, const FVElementGeometry &fvGeometry, const Element &element, const SubControlVolumeFace &scvf, const ElementVolumeVariables &elemVolVars, const FaceVariables &faceVars, const GridFluxVariablesCache &gridFluxVarsCache, const int localSubFaceIdx, const Dune::Std::optional< BoundaryTypes > ¤tScvfBoundaryTypes, const Dune::Std::optional< BoundaryTypes > &lateralFaceBoundaryTypes)
Returns the momentum in the lateral directon.
Definition: staggeredupwindfluxvariables.hh:118
Helper class for calculating the velocity gradients for the Navier-Stokes model using the staggered g...
Definition: velocitygradients.hh:39
static Scalar velocityGradJI(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const SubControlVolumeFace &scvf, const FaceVariables &faceVars, const Dune::Std::optional< BoundaryTypes > ¤tScvfBoundaryTypes, const Dune::Std::optional< BoundaryTypes > &lateralFaceBoundaryTypes, const std::size_t localSubFaceIdx)
Returns the velocity gradient in line with our current scvf.
Definition: velocitygradients.hh:172
Declares all properties used in Dumux.