3.1-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
staggeredupwindfluxvariables.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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_NAVIERSTOKES_STAGGERED_UPWINDVARIABLES_HH
25#define DUMUX_NAVIERSTOKES_STAGGERED_UPWINDVARIABLES_HH
26
27#include <array>
28
29#include <dumux/common/math.hh>
33
36#include "velocitygradients.hh"
37
38namespace Dumux {
39
44template<class TypeTag, int upwindSchemeOrder>
46{
48
49 using GridVolumeVariables = typename GridVariables::GridVolumeVariables;
50 using ElementVolumeVariables = typename GridVolumeVariables::LocalView;
51 using VolumeVariables = typename GridVolumeVariables::VolumeVariables;
52
53 using GridFluxVariablesCache = typename GridVariables::GridFluxVariablesCache;
54 using FluxVariablesCache = typename GridFluxVariablesCache::FluxVariablesCache;
55
56 using GridFaceVariables = typename GridVariables::GridFaceVariables;
57 using ElementFaceVariables = typename GridFaceVariables::LocalView;
58 using FaceVariables = typename GridFaceVariables::FaceVariables;
59
62 using FVElementGeometry = typename GridGeometry::LocalView;
63 using GridView = typename GridGeometry::GridView;
64 using Element = typename GridView::template Codim<0>::Entity;
67 using Indices = typename ModelTraits::Indices;
68 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
69 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
70 using CellCenterPrimaryVariables = GetPropType<TypeTag, Properties::CellCenterPrimaryVariables>;
74
75 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
76 static constexpr bool useHigherOrder = upwindSchemeOrder > 1;
77
78public:
87 static FacePrimaryVariables computeUpwindedFrontalMomentum(const SubControlVolumeFace& scvf,
88 const ElementFaceVariables& elemFaceVars,
89 const ElementVolumeVariables& elemVolVars,
90 const GridFluxVariablesCache& gridFluxVarsCache,
91 const Scalar transportingVelocity)
92 {
93 const bool canHigherOrder = canFrontalSecondOrder_(scvf, transportingVelocity, std::integral_constant<bool, useHigherOrder>{});
94
95 if (canHigherOrder)
96 {
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);
100 }
101 else
102 {
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);
106 }
107 }
108
118 static FacePrimaryVariables computeUpwindedLateralMomentum(const Problem& problem,
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)
128 {
129 const auto eIdx = scvf.insideScvIdx();
130 const auto& lateralFace = fvGeometry.scvf(eIdx, scvf.pairData(localSubFaceIdx).localLateralFaceIdx);
131
132 // Get the transporting velocity, located at the scvf perpendicular to the current scvf where the dof
133 // of interest is located.
134 const Scalar transportingVelocity = faceVars.velocityLateralInside(localSubFaceIdx);
135
136 // Check whether the own or the neighboring element is upstream.
137 const bool selfIsUpstream = ( lateralFace.directionSign() == sign(transportingVelocity) );
138
139 const bool canHigherOrder = canLateralSecondOrder_(scvf, selfIsUpstream, localSubFaceIdx, std::integral_constant<bool, useHigherOrder>{});
140
141 if (canHigherOrder)
142 {
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);
147 }
148 else
149 {
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);
154 }
155 }
156
157private:
158
168 static bool canFrontalSecondOrder_(const SubControlVolumeFace& ownScvf,
169 const Scalar transportingVelocity,
170 std::false_type)
171 { return false; }
172
186 static bool canFrontalSecondOrder_(const SubControlVolumeFace& ownScvf,
187 const Scalar transportingVelocity,
188 std::true_type)
189 {
190 // Depending on selfIsUpstream I have to check if I have a forward or a backward neighbor to retrieve
191 const bool selfIsUpstream = ownScvf.directionSign() != sign(transportingVelocity);
192 return selfIsUpstream ? ownScvf.hasForwardNeighbor(0) : ownScvf.hasBackwardNeighbor(0);
193 }
194
204 static std::array<Scalar, 2> getFrontalUpwindingMomenta_(const SubControlVolumeFace& scvf,
205 const ElementFaceVariables& elemFaceVars,
206 const Scalar density,
207 const Scalar transportingVelocity,
208 std::false_type)
209 {
210 const Scalar momentumSelf = elemFaceVars[scvf].velocitySelf() * density;
211 const Scalar momentumOpposite = elemFaceVars[scvf].velocityOpposite() * density;
212 const bool selfIsUpstream = scvf.directionSign() != sign(transportingVelocity);
213
214 return selfIsUpstream ? std::array<Scalar, 2>{momentumOpposite, momentumSelf}
215 : std::array<Scalar, 2>{momentumSelf, momentumOpposite};
216 }
217
227 static std::array<Scalar, 3> getFrontalUpwindingMomenta_(const SubControlVolumeFace& scvf,
228 const ElementFaceVariables& elemFaceVars,
229 const Scalar density,
230 const Scalar transportingVelocity,
231 std::true_type)
232 {
233 const bool selfIsUpstream = scvf.directionSign() != sign(transportingVelocity);
234 std::array<Scalar, 3> momenta;
235
236 if (selfIsUpstream)
237 {
238 momenta[0] = elemFaceVars[scvf].velocityOpposite() * density;
239 momenta[1] = elemFaceVars[scvf].velocitySelf() * density;
240 momenta[2] = elemFaceVars[scvf].velocityForward(0) * density;
241 }
242 else
243 {
244 momenta[0] = elemFaceVars[scvf].velocitySelf() * density;
245 momenta[1] = elemFaceVars[scvf].velocityOpposite() * density;
246 momenta[2] = elemFaceVars[scvf].velocityBackward(0) * density;
247 }
248
249 return momenta;
250 }
251
260 static Scalar doFrontalMomentumUpwinding_(const SubControlVolumeFace& scvf,
261 const std::array<Scalar, 2>& momenta,
262 const Scalar transportingVelocity,
263 const GridFluxVariablesCache& gridFluxVarsCache)
264 {
265 const auto& upwindScheme = gridFluxVarsCache.staggeredUpwindMethods();
266 return upwindScheme.upwind(momenta[0], momenta[1]);
267 }
268
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)
282 {
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());
287 }
288
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)
298 {
299 // Depending on selfIsUpstream the downstream and the (up)upstream distances are saved.
300 // distances {upstream to downstream distance, up-upstream to upstream distance, downstream staggered cell size}
301 std::array<Scalar, 3> distances;
302
303 if (selfIsUpstream)
304 {
305 distances[0] = ownScvf.selfToOppositeDistance();
306 distances[1] = ownScvf.axisData().inAxisForwardDistances[0];
307 distances[2] = 0.5 * (ownScvf.axisData().selfToOppositeDistance + ownScvf.axisData().inAxisBackwardDistances[0]);
308 }
309 else
310 {
311 distances[0] = ownScvf.selfToOppositeDistance();
312 distances[1] = ownScvf.axisData().inAxisBackwardDistances[0];
313 distances[2] = 0.5 * (ownScvf.axisData().selfToOppositeDistance + ownScvf.axisData().inAxisForwardDistances[0]);
314 }
315 return distances;
316 }
317
329 static bool canLateralSecondOrder_(const SubControlVolumeFace& ownScvf,
330 const bool selfIsUpstream,
331 const int localSubFaceIdx,
332 std::true_type)
333 {
334 if (selfIsUpstream)
335 {
336 // The self velocity is upstream. The downstream velocity can be assigned or retrieved
337 // from the boundary, even if there is no parallel neighbor.
338 return true;
339 }
340 else
341 {
342 // The self velocity is downstream. If there is no parallel neighbor I cannot use a second order approximation.
343 return ownScvf.hasParallelNeighbor(localSubFaceIdx, 0);
344 }
345 }
346
351 static bool canLateralSecondOrder_(const SubControlVolumeFace& ownScvf,
352 const bool selfIsUpstream,
353 const int localSubFaceIdx,
354 std::false_type)
355 { return false; }
356
357
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,
373 std::true_type)
374 {
375 const SubControlVolumeFace& lateralFace = fvGeometry.scvf(ownScvf.insideScvIdx(), ownScvf.pairData(localSubFaceIdx).localLateralFaceIdx);
376
377 // Get the volume variables of the own and the neighboring element
378 const auto& insideVolVars = elemVolVars[lateralFace.insideScvIdx()];
379 const auto& outsideVolVars = elemVolVars[lateralFace.outsideScvIdx()];
380
381 // If the lateral face lies on a boundary, we assume that the parallel velocity on the boundary is actually known,
382 // thus we always use this value for the computation of the transported momentum.
383 if (!ownScvf.hasParallelNeighbor(localSubFaceIdx, 0))
384 {
385 const Scalar boundaryMomentum = getParallelVelocityFromBoundary_(problem, element, fvGeometry, ownScvf,
386 faceVars, currentScvfBoundaryTypes, lateralFaceBoundaryTypes,
387 localSubFaceIdx) * insideVolVars.density();
388
389 return std::array<Scalar, 3>{boundaryMomentum, boundaryMomentum, boundaryMomentum};
390 }
391
392 // Check whether the own or the neighboring element is upstream.
393 const bool selfIsUpstream = lateralFace.directionSign() == sign(transportingVelocity);
394
395 std::array<Scalar, 3> momenta;
396
397 if (selfIsUpstream)
398 {
399 momenta[1] = faceVars.velocitySelf() * insideVolVars.density();
400
401 if (ownScvf.hasParallelNeighbor(localSubFaceIdx, 0))
402 momenta[0] = faceVars.velocityParallel(localSubFaceIdx, 0) * insideVolVars.density();
403 else
404 momenta[0] = getParallelVelocityFromBoundary_(problem, element, fvGeometry, ownScvf,
405 faceVars, currentScvfBoundaryTypes, lateralFaceBoundaryTypes,
406 localSubFaceIdx) * insideVolVars.density();
407
408 // The local index of the faces that is opposite to localSubFaceIdx
409 const int oppositeSubFaceIdx = localSubFaceIdx % 2 ? localSubFaceIdx - 1 : localSubFaceIdx + 1;
410
411 // The "upstream-upstream" velocity is retrieved from the other parallel neighbor or from the boundary.
412 if (ownScvf.hasParallelNeighbor(oppositeSubFaceIdx, 0))
413 momenta[2] = faceVars.velocityParallel(oppositeSubFaceIdx, 0) * insideVolVars.density();
414 else
415 momenta[2] = getParallelVelocityFromOtherBoundary_(problem, fvGeometry, ownScvf,
416 oppositeSubFaceIdx, element,
417 (momenta[1]/insideVolVars.density())) * insideVolVars.density();
418 }
419 else
420 {
421 momenta[0] = faceVars.velocitySelf() * outsideVolVars.density();
422 momenta[1] = faceVars.velocityParallel(localSubFaceIdx, 0) * outsideVolVars.density();
423
424 // If there is another parallel neighbor I can assign the "upstream-upstream" velocity, otherwise I retrieve it from the boundary.
425 if (ownScvf.hasParallelNeighbor(localSubFaceIdx, 1))
426 momenta[2] = faceVars.velocityParallel(localSubFaceIdx, 1) * outsideVolVars.density();
427 else
428 {
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();
434 }
435 }
436
437 return momenta;
438 }
439
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,
455 std::false_type)
456 {
457 // Check whether the own or the neighboring element is upstream.
458 const SubControlVolumeFace& lateralFace = fvGeometry.scvf(ownScvf.insideScvIdx(), ownScvf.pairData(localSubFaceIdx).localLateralFaceIdx);
459
460 // Get the volume variables of the own and the neighboring element
461 const auto& insideVolVars = elemVolVars[lateralFace.insideScvIdx()];
462 const auto& outsideVolVars = elemVolVars[lateralFace.outsideScvIdx()];
463
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,
468 localSubFaceIdx)
469 * insideVolVars.density());
470
471 // If the lateral face lies on a boundary, we assume that the parallel velocity on the boundary is actually known,
472 // thus we always use this value for the computation of the transported momentum.
473 if (!ownScvf.hasParallelNeighbor(localSubFaceIdx, 0))
474 return std::array<Scalar, 2>{momentumParallel, momentumParallel};
475
476 const bool selfIsUpstream = lateralFace.directionSign() == sign(transportingVelocity);
477 const Scalar momentumSelf = faceVars.velocitySelf() * insideVolVars.density();
478
479 return selfIsUpstream ? std::array<Scalar, 2>{momentumParallel, momentumSelf}
480 : std::array<Scalar, 2>{momentumSelf, momentumParallel};
481 }
482
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)
494 {
495 return doFrontalMomentumUpwinding_(scvf, momenta, transportingVelocity, gridFluxVarsCache);
496 }
497
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)
513 {
514 const auto eIdx = scvf.insideScvIdx();
515 const auto& lateralFace = fvGeometry.scvf(eIdx, scvf.pairData(localSubFaceIdx).localLateralFaceIdx);
516
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());
521 }
522
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)
534 {
535 // distances {upstream to downstream distance, up-upstream to upstream distance, downstream staggered cell size}
536 std::array<Scalar, 3> distances;
537
538 if (selfIsUpstream)
539 {
540 // The local index of the faces that is opposite to localSubFaceIdx
541 const int oppositeSubFaceIdx = localSubFaceIdx % 2 ? localSubFaceIdx - 1 : localSubFaceIdx + 1;
542
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];
547 else
548 distances[2] = ownScvf.area() / 2.0;
549 }
550 else
551 {
552 distances[0] = ownScvf.parallelDofsDistance(localSubFaceIdx, 0);
553 distances[1] = ownScvf.parallelDofsDistance(localSubFaceIdx, 1);
554 distances[2] = ownScvf.pairData(localSubFaceIdx).parallelCellWidths[0];
555 }
556
557 return distances;
558 }
559
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)
580 {
581 // Find out what boundary type is set on the lateral face
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();
585
586 // If there is a Dirichlet condition for the pressure we assume zero gradient for the velocity,
587 // so the velocity at the boundary equal to that on the scvf.
588 if (lateralFaceHasDirichletPressure)
589 return velocitySelf;
590
591 if (lateralFaceHasBJS)
592 {
593 const auto eIdx = scvf.insideScvIdx();
594 const auto& lateralFace = fvGeometry.scvf(eIdx, scvf.pairData(localSubFaceIdx).localLateralFaceIdx);
595 const Scalar velocityGrad_ji = VelocityGradients::velocityGradJI(problem, element, fvGeometry, scvf, faceVars,
596 currentScvfBoundaryTypes, lateralFaceBoundaryTypes, localSubFaceIdx);
597
598 const SubControlVolume& scv = fvGeometry.scv(scvf.insideScvIdx());
599 return problem.beaversJosephVelocity(element, scv, lateralFace, velocitySelf, velocityGrad_ji);
600 }
601 else
602 {
603 // ________________
604 // ---------------o || frontal face of staggered half-control-volume
605 // | || # current scvf # ghostFace of interest, lies on boundary
606 // | || # x dof position
607 // | || x~~~~> vel.Self -- element boundaries
608 // | || # __ domain boundary
609 // | || # o position at which the boundary conditions will be evaluated
610 // ---------------#
611
612 const auto ghostFace = makeParallelGhostFace_(scvf, localSubFaceIdx);
613 return problem.dirichlet(element, ghostFace)[Indices::velocity(scvf.directionIndex())];
614 }
615 }
616
626 static Scalar getParallelVelocityFromOtherBoundary_(const Problem& problem,
627 const FVElementGeometry& fvGeometry,
628 const SubControlVolumeFace& scvf,
629 const int localIdx,
630 const Element& boundaryElement,
631 const Scalar parallelVelocity)
632 {
633 // A ghost subface at the boundary is created, featuring the location of the sub face's center
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;
637
638 // ________________
639 // --------####o### || frontal face of staggered half-control-volume
640 // | || | current scvf # lateralBoundaryFace of interest, lies on lateral boundary
641 // | || | x dof position
642 // | || x~~~~> vel.Self -- element boundaries
643 // | || | __ domain boundary
644 // | || | o position at which the boundary conditions will be evaluated
645 // ---------------- (lateralBoundaryFaceCenter)
646
647 const SubControlVolumeFace lateralBoundaryFace = lateralScvf.makeBoundaryFace(lateralBoundaryFaceCenter);
648
649 // The boundary condition is checked, in case of symmetry or Dirichlet for the pressure
650 // a gradient of zero is assumed in the direction normal to the bounadry, while if there is
651 // Dirichlet of BJS for the velocity the related values are exploited.
652 const auto bcTypes = problem.boundaryTypes(boundaryElement, lateralBoundaryFace);
653
654 if (bcTypes.isDirichlet(Indices::velocity(scvf.directionIndex())))
655 {
656 // ________________
657 // --------#######o || frontal face of staggered half-control-volume
658 // | || | current scvf # lateralBoundaryFace of interest, lies on lateral boundary
659 // | || | x dof position
660 // | || x~~~~> vel.Self -- element boundaries
661 // | || | __ domain boundary
662 // | || | o position at which the boundary conditions will be evaluated
663 // ----------------
664
665 const SubControlVolumeFace ghostFace = makeParallelGhostFace_(scvf, localIdx);
666 return problem.dirichlet(boundaryElement, ghostFace)[Indices::velocity(scvf.directionIndex())];
667 }
668 else if (bcTypes.isSymmetry() || bcTypes.isDirichlet(Indices::pressureIdx))
669 return parallelVelocity;
670 else if (bcTypes.isBJS(Indices::velocity(scvf.directionIndex())))
671 {
672 const SubControlVolume& scv = fvGeometry.scv(scvf.insideScvIdx());
673 return problem.bjsVelocity(boundaryElement, scv, lateralScvf, parallelVelocity);
674 }
675 else
676 {
677 // Neumann conditions are not well implemented
678 DUNE_THROW(Dune::InvalidStateException, "Something went wrong with the boundary conditions for the momentum equations at global position " << lateralBoundaryFaceCenter);
679 }
680 }
681
683 static SubControlVolumeFace makeParallelGhostFace_(const SubControlVolumeFace& ownScvf, const int localSubFaceIdx)
684 {
685 return ownScvf.makeBoundaryFace(ownScvf.pairData(localSubFaceIdx).lateralStaggeredFaceCenter);
686 };
687};
688
689} // end namespace Dumux
690
691#endif // DUMUX_NAVIERSTOKES_STAGGERED_UPWINDVARIABLES_HH
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 > &currentScvfBoundaryTypes, 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 > &currentScvfBoundaryTypes, 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.