GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/freeflow/navierstokes/momentum/fluxvariables.hh
Date: 2025-04-12 19:19:20
Exec Total Coverage
Lines: 132 154 85.7%
Functions: 144 194 74.2%
Branches: 88 219 40.2%

Line Branch Exec Source
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-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 /*!
8 * \file
9 * \ingroup NavierStokesModel
10 * \copydoc Dumux::NavierStokesFluxVariablesImpl
11 */
12 #ifndef DUMUX_NAVIERSTOKES_MOMENTUM_FLUXVARIABLES_HH
13 #define DUMUX_NAVIERSTOKES_MOMENTUM_FLUXVARIABLES_HH
14
15 #include <array>
16
17 #include <dumux/common/numeqvector.hh>
18 #include <dumux/common/math.hh>
19 #include <dumux/common/exceptions.hh>
20 #include <dumux/common/parameters.hh>
21 #include <dumux/common/properties.hh>
22
23 #include <dumux/discretization/extrusion.hh>
24 #include <dumux/discretization/method.hh>
25
26 // #include "staggeredupwindhelper.hh"
27 #include "velocitygradients.hh"
28
29 namespace Dumux {
30
31 /*!
32 * \ingroup NavierStokesModel
33 * \brief The flux variables class for the Navier-Stokes model using the staggered grid discretization.
34 */
35 template<class TypeTag>
36 class NavierStokesMomentumFluxVariables
37 {
38 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
39
40 using GridVolumeVariables = typename GridVariables::GridVolumeVariables;
41 using ElementVolumeVariables = typename GridVolumeVariables::LocalView;
42 using VolumeVariables = typename GridVolumeVariables::VolumeVariables;
43
44 using GridFluxVariablesCache = typename GridVariables::GridFluxVariablesCache;
45 using ElementFluxVariablesCache = typename GridFluxVariablesCache::LocalView;
46 using FluxVariablesCache = typename GridFluxVariablesCache::FluxVariablesCache;
47
48 using GridGeometry = typename GridVariables::GridGeometry;
49 using FVElementGeometry = typename GridGeometry::LocalView;
50 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
51 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
52
53 using ElementBoundaryTypes = GetPropType<TypeTag, Properties::ElementBoundaryTypes>;
54
55 using Problem = GetPropType<TypeTag, Properties::Problem>;
56 using GridView = typename GridGeometry::GridView;
57 using Element = typename GridView::template Codim<0>::Entity;
58 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
59 using ModelTraits = GetPropType<TypeTag, Properties::ModelTraits>;
60 using Indices = typename ModelTraits::Indices;
61 using VelocityGradients = StaggeredVelocityGradients;
62
63 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
64 using Extrusion = Extrusion_t<GridGeometry>;
65
66 using NumEqVector = Dumux::NumEqVector<GetPropType<TypeTag, Properties::PrimaryVariables>>;
67
68 public:
69
70 307628348 NavierStokesMomentumFluxVariables(const Problem& problem,
71 const Element& element,
72 const FVElementGeometry& fvGeometry,
73 const SubControlVolumeFace& scvFace,
74 const ElementVolumeVariables& elemVolVars,
75 const ElementFluxVariablesCache& elemFluxVarsCache,
76 const ElementBoundaryTypes& elemBcTypes)
77 307628348 : problemPtr_(&problem)
78 307628348 , elementPtr_(&element)
79 307628348 , fvGeometryPtr_(&fvGeometry)
80 307628348 , scvFacePtr_(&scvFace)
81 307628348 , elemVolVarsPtr_(&elemVolVars)
82 307628348 , elemFluxVarsCachePtr_(&elemFluxVarsCache)
83 307628348 , elemBcTypesPtr_(&elemBcTypes)
84 {
85 static_assert(
86 std::decay_t<decltype(problem.dirichlet(element, scvFace))>::size()
87 == static_cast<std::size_t>(GridView::dimension),
88 "Expects problem.dirichlet to return an array with as many entries as dimensions."
89 );
90 }
91
92 1257876040 const Problem& problem() const
93 1146778280 { return *problemPtr_; }
94
95 242857288 const Element& element() const
96 423740086 { return *elementPtr_; }
97
98 1632753040 const SubControlVolumeFace& scvFace() const
99 1633444136 { return *scvFacePtr_; }
100
101 918473696 const FVElementGeometry& fvGeometry() const
102 67109058 { return *fvGeometryPtr_; }
103
104 611771108 const ElementVolumeVariables& elemVolVars() const
105 102677388 { return *elemVolVarsPtr_; }
106
107 const ElementFluxVariablesCache& elemFluxVarsCache() const
108 { return *elemFluxVarsCachePtr_; }
109
110 206751854 const ElementBoundaryTypes& elemBcTypes() const
111 206751854 { return *elemBcTypesPtr_; }
112
113 /*!
114 * \brief Returns the diffusive momentum flux due to viscous forces
115 */
116 307628348 NumEqVector advectiveMomentumFlux() const
117 {
118
2/2
✓ Branch 0 taken 106162976 times.
✓ Branch 1 taken 201465372 times.
307628348 if (!this->problem().enableInertiaTerms())
119 106162976 return NumEqVector(0.0);
120
121
2/2
✓ Branch 0 taken 67109058 times.
✓ Branch 1 taken 134356314 times.
201465372 if (this->scvFace().isFrontal())
122 67109058 return frontalAdvectiveMomentumFlux();
123 else
124 134356314 return lateralAdvectiveMomentumFlux();
125 }
126
127 /*!
128 * \brief Returns the diffusive momentum flux due to viscous forces
129 */
130 307628348 NumEqVector diffusiveMomentumFlux() const
131 {
132
2/2
✓ Branch 0 taken 102677388 times.
✓ Branch 1 taken 204950960 times.
307628348 if (this->scvFace().isFrontal())
133 102677388 return frontalDiffusiveMomentumFlux();
134 else
135 204950960 return lateralDiffusiveMomentumFlux();
136 }
137
138 /*!
139 * \brief Returns the frontal part of the momentum flux.
140 * This treats the flux over the staggered face at the center of an element,
141 * parallel to the current scvf where the velocity dof of interest lives.
142 *
143 * \verbatim
144 * scvf
145 * ---------======= == and # staggered half-control-volume
146 * | # | current scv
147 * | # | # staggered face over which fluxes are calculated
148 * vel.Opp |~~> O~~~> x~~~~> vel.Self
149 * | # | x dof position
150 * | # |
151 * --------======== -- element
152 * scvf
153 * O integration point
154 * \endverbatim
155 */
156 102677388 NumEqVector frontalDiffusiveMomentumFlux() const
157 {
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102677388 times.
102677388 const auto& scvf = this->scvFace();
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102677388 times.
102677388 assert(scvf.isFrontal());
160
161 102677388 NumEqVector result(0.0);
162 102677388 const auto& fvGeometry = this->fvGeometry();
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102677388 times.
102677388 const auto& elemVolVars = this->elemVolVars();
164
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102677388 times.
102677388 if (scvf.boundary())
166 return result;
167
168 // get the velocity gradient at the normal face's integration point
169 102677388 const auto velGradII = VelocityGradients::velocityGradII(fvGeometry, scvf, elemVolVars);
170
171
4/4
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 102677314 times.
✓ Branch 3 taken 71 times.
✓ Branch 4 taken 3 times.
102677459 static const bool enableUnsymmetrizedVelocityGradient
172
1/2
✓ Branch 1 taken 71 times.
✗ Branch 2 not taken.
142 = getParamFromGroup<bool>(this->problem().paramGroup(), "FreeFlow.EnableUnsymmetrizedVelocityGradient", false);
173
4/6
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 102677317 times.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 71 times.
✗ Branch 6 not taken.
102677459 static const Scalar factor = enableUnsymmetrizedVelocityGradient ? 1.0 : 2.0;
174
175 102677388 const auto mu = this->problem().effectiveViscosity(this->element(), this->fvGeometry(), this->scvFace());
176
2/2
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 102677308 times.
102677388 result -= factor * mu * velGradII * Extrusion::area(fvGeometry, scvf) * elemVolVars[scvf.insideScvIdx()].extrusionFactor() * scvf.directionSign();
177
178
5/6
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 102677308 times.
✓ Branch 3 taken 71 times.
✓ Branch 4 taken 9 times.
✓ Branch 6 taken 71 times.
✗ Branch 7 not taken.
102677388 static const bool enableDilatationTerm = getParamFromGroup<bool>(this->problem().paramGroup(), "FreeFlow.EnableDilatationTerm", false);
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102677388 times.
102677388 if (enableDilatationTerm)
180 {
181 Scalar divergence = velGradII;
182 for (const auto& scv : scvs(fvGeometry))
183 {
184 const auto otherFrontalScvf = *(scvfs(fvGeometry, scv).begin());
185 assert(otherFrontalScvf.isFrontal() && !otherFrontalScvf.boundary());
186 if (otherFrontalScvf.index() != scvf.index())
187 divergence += VelocityGradients::velocityGradII(fvGeometry, otherFrontalScvf, elemVolVars);
188 }
189
190 result += 2.0/3.0 * mu * divergence * scvf.directionSign() * Extrusion::area(fvGeometry, scvf) * elemVolVars[scvf.insideScvIdx()].extrusionFactor();
191 }
192
193 102677388 return result;
194 }
195
196 /*!
197 * \brief Returns the diffusive momentum flux over the staggered face perpendicular to the scvf
198 * where the velocity dof of interest lives (coinciding with the element's scvfs).
199 *
200 * \verbatim
201 * ----------------
202 * | |vel.
203 * | in.norm. |Parallel
204 * | vel. |~~~~>
205 * | ^ | ^ out.norm.vel.
206 * | | | |
207 * scvf ---------#######::::::::: || and # staggered half-control-volume (own element)
208 * | || | curr. ::
209 * | || | scvf :: :: staggered half-control-volume (neighbor element)
210 * | || x~~~~> ::
211 * | || | vel. :: # lateral staggered faces over which fluxes are calculated
212 * scvf | || | Self ::
213 * ---------#######::::::::: x dof position
214 * scvf
215 * -- elements
216 * \endverbatim
217 */
218 204950960 NumEqVector lateralDiffusiveMomentumFlux() const
219 {
220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 204950960 times.
204950960 const auto& scvf = this->scvFace();
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 204950960 times.
204950960 assert(scvf.isLateral());
222
223 204950960 NumEqVector result(0.0);
224 204950960 const auto& fvGeometry = this->fvGeometry();
225 204950960 const auto& elemVolVars = this->elemVolVars();
226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200877856 times.
204950960 const auto& problem = this->problem();
227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200877856 times.
204950960 const auto& scv = fvGeometry.scv(scvf.insideScvIdx());
228
229
4/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 204950888 times.
✓ Branch 3 taken 70 times.
✓ Branch 4 taken 2 times.
204951030 static const bool enableUnsymmetrizedVelocityGradient
230
1/2
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
140 = getParamFromGroup<bool>(problem.paramGroup(), "FreeFlow.EnableUnsymmetrizedVelocityGradient", false);
231
232 204950960 const auto mu = this->problem().effectiveViscosity(this->element(), this->fvGeometry(), this->scvFace());
233
234 // get the velocity gradient at the lateral face's integration point
235 204950960 const auto gradV = VelocityGradients::velocityGradient(fvGeometry, scvf, elemVolVars, this->elemBcTypes(), false);
236
237 // Consider the shear stress caused by the gradient of the velocities parallel to our face of interest.
238 204950960 GlobalPosition gradVn(0.0);
239
1/2
✓ Branch 0 taken 204950960 times.
✗ Branch 1 not taken.
409901920 gradV.mv(scvf.unitOuterNormal(), gradVn);
240
1/2
✓ Branch 0 taken 204950960 times.
✗ Branch 1 not taken.
204950960 const Scalar velocityGrad_ij = gradVn[scv.dofAxis()];
241
1/2
✓ Branch 0 taken 204950960 times.
✗ Branch 1 not taken.
204950960 result -= mu * velocityGrad_ij;
242
243 // Consider the shear stress caused by the gradient of the velocities normal to our face of interest.
244
1/2
✓ Branch 0 taken 204950960 times.
✗ Branch 1 not taken.
204950960 if (!enableUnsymmetrizedVelocityGradient)
245 {
246
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
204950960 GlobalPosition gradVTransposedN(0.0);
247
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
204950960 gradV.mtv(scvf.unitOuterNormal(), gradVTransposedN);
248 204950960 const Scalar velocityGrad_ji = gradVTransposedN[scv.dofAxis()];
249 204950960 result -= mu * velocityGrad_ji;
250 }
251
252 // Account for the area of the staggered lateral face.
253 204950960 return result * Extrusion::area(fvGeometry, scvf) * elemVolVars[scvf.insideScvIdx()].extrusionFactor();
254 }
255
256 /*!
257 * \brief Returns the frontal pressure contribution.
258 *
259 * \verbatim
260 *
261 * ---------======= == and # staggered half-control-volume
262 * | # | current scv
263 * | # | # frontal staggered face for which pressure contribution is calculated
264 * | P x
265 * | # | x dof position
266 * | # |
267 * --------======== -- element
268 *
269 * P integration point, pressure DOF lives here
270 * \endverbatim
271 */
272 307628348 NumEqVector pressureContribution() const
273 {
274 307628348 NumEqVector result(0.0);
275
2/2
✓ Branch 0 taken 102677388 times.
✓ Branch 1 taken 204950960 times.
307628348 const auto& scvf = this->scvFace();
276
3/4
✓ Branch 0 taken 102677388 times.
✓ Branch 1 taken 204950960 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 102677388 times.
307628348 if (scvf.isLateral() || scvf.boundary())
277 204950960 return result;
278
279 // The pressure force needs to take the extruded scvf area into account.
280 102677388 const auto pressure = this->problem().pressure(this->element(), this->fvGeometry(), scvf);
281 102677388 result = pressure*Extrusion::area(this->fvGeometry(), scvf)*this->elemVolVars()[scvf.insideScvIdx()].extrusionFactor();
282
283 // The pressure contribution calculated above might have a much larger numerical value compared to the viscous or inertial forces.
284 // This may lead to numerical inaccuracies due to loss of significance (cancellantion) for the final residual value.
285 // In the end, we are only interested in a pressure difference between the two relevant faces so we can
286 // subtract a reference value from the actual pressure contribution. Assuming an axisparallel cartesian grid,
287 // scvf.area() will have the same value at both opposing faces such that the reference pressure contribution
288 // cancels out in the final residual which combines the pressure contribution of two adjacent elements
289 // We explicitly do extrude the area here because that might yield different results in both elements.
290 // The multiplication by scvf.area() aims at having a reference value of the same order of magnitude as the actual pressure contribution.
291 102677388 const auto referencePressure = this->problem().referencePressure(this->element(), this->fvGeometry(), scvf);
292 102677388 result -= referencePressure*scvf.area();
293
294 // Account for the orientation of the face.
295 102677388 result *= scvf.directionSign();
296 102677388 return result;
297 }
298
299 /*!
300 * \brief Returns the frontal part of the momentum flux.
301 * This treats the flux over the staggered face at the center of an element,
302 * parallel to the current scvf where the velocity dof of interest lives.
303 *
304 * \verbatim
305 * scvf
306 * ---------======= == and # staggered half-control-volume
307 * | # | current scv
308 * | # | # staggered face over which fluxes are calculated
309 * vel.Opp |~~> O~~~> x~~~~> vel.Self
310 * | # | x dof position
311 * | # |
312 * --------======== -- element
313 * scvf
314 * O integration point
315 * \endverbatim
316 */
317 67109058 NumEqVector frontalAdvectiveMomentumFlux() const
318 {
319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67109058 times.
67109058 const auto& scvf = this->scvFace();
320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67109058 times.
67109058 assert(scvf.isFrontal());
321
322 67109058 const auto& problem = this->problem();
323 67109058 const auto& elemVolVars = this->elemVolVars();
324 67109058 const auto velocitySelf = elemVolVars[scvf.insideScvIdx()].velocity();
325
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
67109058 const auto velocityOpposite = elemVolVars[scvf.outsideScvIdx()].velocity();
326
327 // Get the average velocity at the center of the element (i.e. the location of the staggered face).
328 67109058 const Scalar transportingVelocity = (velocitySelf + velocityOpposite) * 0.5;
329
2/3
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 67109032 times.
✗ Branch 0 not taken.
67109058 const Scalar density = this->problem().density(this->element(), this->fvGeometry(), scvf);
330
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 67109032 times.
67109058 const bool selfIsUpstream = scvf.directionSign() == sign(transportingVelocity);
331
332 // TODO use higher order helper
333
4/6
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 67109032 times.
✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 26 times.
✗ Branch 7 not taken.
67109058 static const auto upwindWeight = getParamFromGroup<Scalar>(problem.paramGroup(), "Flux.UpwindWeight");
334
2/2
✓ Branch 0 taken 29874645 times.
✓ Branch 1 taken 37234413 times.
67109058 const Scalar transportedMomentum = selfIsUpstream ? (upwindWeight * velocitySelf + (1.0 - upwindWeight) * velocityOpposite) * density
335 37234413 : (upwindWeight * velocityOpposite + (1.0 - upwindWeight) * velocitySelf) * density;
336
337 67109058 return transportingVelocity * transportedMomentum * scvf.directionSign() * Extrusion::area(this->fvGeometry(), scvf) * extrusionFactor_(elemVolVars, scvf);
338 }
339
340 /*!
341 * \brief Returns the advective momentum flux over the staggered face perpendicular to the scvf
342 * where the velocity dof of interest lives (coinciding with the element's scvfs).
343 *
344 * \verbatim
345 * ----------------
346 * | inner |
347 * | transp. |
348 * | vel. |~~~~> outer vel.
349 * | ^ |
350 * | | |
351 * ---------######O || and # staggered half-control-volume
352 * | || | scv
353 * | || | # lateral staggered faces over which fluxes are calculated
354 * | || x~~~~> inner vel.
355 * | || | x dof position
356 * | || |
357 * ---------####### -- elements
358 *
359 * O integration point
360 * \endverbatim
361 */
362 134356314 NumEqVector lateralAdvectiveMomentumFlux() const
363 {
364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 134356314 times.
134356314 const auto& scvf = this->scvFace();
365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 134356314 times.
134356314 assert(scvf.isLateral());
366
367 134356314 const auto& problem = this->problem();
368 134356314 const auto& elemVolVars = this->elemVolVars();
369 134356314 const auto fvGeometry = this->fvGeometry();
370
371 // get the transporting velocity which is perpendicular to our own (inner) velocity
372 403068942 const Scalar transportingVelocity = [&]()
373 {
374 134356314 const auto& orthogonalScvf = fvGeometry.lateralOrthogonalScvf(scvf);
375
2/2
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 134356289 times.
134356314 const Scalar innerTransportingVelocity = elemVolVars[orthogonalScvf.insideScvIdx()].velocity();
376
377
4/6
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 134356289 times.
✓ Branch 3 taken 25 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 25 times.
✗ Branch 7 not taken.
134356314 static const bool useOldScheme = getParam<bool>("FreeFlow.UseOldTransportingVelocity", true); // TODO how to deprecate?
378
379
1/2
✓ Branch 0 taken 134356314 times.
✗ Branch 1 not taken.
134356314 if (useOldScheme)
380 {
381
5/6
✓ Branch 0 taken 1800894 times.
✓ Branch 1 taken 132555420 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1725742 times.
✓ Branch 4 taken 75152 times.
✓ Branch 5 taken 1725742 times.
134356314 if (scvf.boundary() && fvGeometry.scv(scvf.insideScvIdx()).boundary())
382 {
383 if (this->elemBcTypes()[scvf.localIndex()].isDirichlet(scvf.normalAxis()))
384 return problem.dirichlet(this->element(), scvf)[scvf.normalAxis()];
385 }
386 else
387 return innerTransportingVelocity;
388 }
389
390 // use the Dirichlet velocity as transporting velocity if the lateral face is on a Dirichlet boundary
391 if (scvf.boundary())
392 {
393 if (this->elemBcTypes()[scvf.localIndex()].isDirichlet(scvf.normalAxis()))
394 return 0.5*(problem.dirichlet(this->element(), scvf)[scvf.normalAxis()] + innerTransportingVelocity);
395 }
396
397 if (orthogonalScvf.boundary())
398 {
399 if (this->elemBcTypes()[orthogonalScvf.localIndex()].isDirichlet(scvf.normalAxis()))
400 return 0.5*(problem.dirichlet(this->element(), scvf)[scvf.normalAxis()] + innerTransportingVelocity);
401 else
402 return innerTransportingVelocity; // fallback value, should actually never be called
403 }
404
405 // average the transporting velocity by weighting with the scv volumes
406 const auto insideVolume = fvGeometry.scv(orthogonalScvf.insideScvIdx()).volume();
407 const auto outsideVolume = fvGeometry.scv(orthogonalScvf.outsideScvIdx()).volume();
408 const auto outerTransportingVelocity = elemVolVars[orthogonalScvf.outsideScvIdx()].velocity();
409 return (insideVolume*innerTransportingVelocity + outsideVolume*outerTransportingVelocity) / (insideVolume + outsideVolume);
410 134356314 }();
411
412 403068942 const Scalar transportedMomentum = [&]()
413 {
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 130581290 times.
134356314 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
415
416 136252136 auto getDirichletMomentumFlux = [&]()
417 {
418
2/2
✓ Branch 0 taken 61740 times.
✓ Branch 1 taken 185220 times.
2325058 return problem.dirichlet(this->element(), scvf)[insideScv.dofAxis()] * this->problem().density(this->element(), insideScv);
419 };
420
421 // use the Dirichlet velocity as for transported momentum if the lateral face is on a Dirichlet boundary
422
2/2
✓ Branch 0 taken 1800894 times.
✓ Branch 1 taken 132555420 times.
134356314 if (scvf.boundary())
423 {
424
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1800894 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1800894 if (!this->elemBcTypes()[scvf.localIndex()].isDirichlet(insideScv.dofAxis()))
425 DUNE_THROW(Dune::InvalidStateException, "Neither Dirichlet nor Neumann BC set at " << scvf.ipGlobal());
426
427 1800894 return getDirichletMomentumFlux();
428 }
429 else
430 {
431
2/3
✓ Branch 1 taken 128036056 times.
✓ Branch 2 taken 4519364 times.
✗ Branch 0 not taken.
132555420 if (fvGeometry.scvfIntegrationPointInConcaveCorner(scvf))
432 {
433 // TODO: we could put this into an assert, as the construction of outsideScvfWithSameIntegrationPoint is quite expensive
434 94928 const auto& outsideScvfWithSameIntegrationPoint = fvGeometry.outsideScvfWithSameIntegrationPoint(scvf);
435
1/4
✓ Branch 0 taken 94928 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
94928 if (!this->problem().boundaryTypes(this->element(), outsideScvfWithSameIntegrationPoint).isDirichlet(insideScv.dofAxis()))
436 DUNE_THROW(Dune::InvalidStateException, "Neither Dirichlet nor Neumann BC set at " << outsideScvfWithSameIntegrationPoint.ipGlobal());
437
438 94928 return getDirichletMomentumFlux();
439 }
440 }
441
442 132460492 const bool selfIsUpstream = scvf.directionSign() == sign(transportingVelocity);
443
444 132460492 const auto innerVelocity = elemVolVars[scvf.insideScvIdx()].velocity();
445
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
132460492 const auto outerVelocity = elemVolVars[scvf.outsideScvIdx()].velocity();
446
447
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
132460492 const auto rho = this->problem().insideAndOutsideDensity(this->element(), fvGeometry, scvf);
448
449 132460492 const auto insideMomentum = innerVelocity * rho.first;
450 132460492 const auto outsideMomentum = outerVelocity * rho.second;
451
452 // TODO use higher order helper
453
4/6
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 132460467 times.
✓ Branch 3 taken 25 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 25 times.
✗ Branch 7 not taken.
132460492 static const auto upwindWeight = getParamFromGroup<Scalar>(problem.paramGroup(), "Flux.UpwindWeight");
454
455
2/2
✓ Branch 0 taken 58172368 times.
✓ Branch 1 taken 74288124 times.
132460492 return selfIsUpstream ? (upwindWeight * insideMomentum + (1.0 - upwindWeight) * outsideMomentum)
456 74288124 : (upwindWeight * outsideMomentum + (1.0 - upwindWeight) * insideMomentum);
457 134356314 }();
458
459 134356314 return transportingVelocity * transportedMomentum * scvf.directionSign() * Extrusion::area(fvGeometry, scvf) * extrusionFactor_(elemVolVars, scvf);
460 }
461
462 private:
463
464 template<class ElementVolumeVariables, class SubControlVolumeFace>
465 201465372 Scalar extrusionFactor_(const ElementVolumeVariables& elemVolVars, const SubControlVolumeFace& scvf) const
466 {
467 201465372 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
468
1/2
✓ Branch 1 taken 201465372 times.
✗ Branch 2 not taken.
201465372 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
469
1/2
✓ Branch 0 taken 201465372 times.
✗ Branch 1 not taken.
201465372 return harmonicMean(insideVolVars.extrusionFactor(), outsideVolVars.extrusionFactor());
470 }
471
472
473 const Problem* problemPtr_; //!< Pointer to the problem
474 const Element* elementPtr_; //!< Pointer to the element at hand
475 const FVElementGeometry* fvGeometryPtr_; //!< Pointer to the current FVElementGeometry
476 const SubControlVolumeFace* scvFacePtr_; //!< Pointer to the sub control volume face for which the flux variables are created
477 const ElementVolumeVariables* elemVolVarsPtr_; //!< Pointer to the current element volume variables
478 const ElementFluxVariablesCache* elemFluxVarsCachePtr_; //!< Pointer to the current element flux variables cache
479 const ElementBoundaryTypes* elemBcTypesPtr_; //!< Pointer to element boundary types
480 };
481
482 } // end namespace Dumux
483
484 #endif // DUMUX_NAVIERSTOKES_STAGGERED_FLUXVARIABLES_HH
485