3.5-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
freeflow/navierstokes/staggered/localresidual.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_STAGGERED_NAVIERSTOKES_LOCAL_RESIDUAL_HH
25#define DUMUX_STAGGERED_NAVIERSTOKES_LOCAL_RESIDUAL_HH
26
27#include <dune/common/hybridutilities.hh>
28
34
35namespace Dumux {
36
37namespace Impl {
38template<class T>
39static constexpr bool isRotationalExtrusion = false;
40
41template<int radialAxis>
42static constexpr bool isRotationalExtrusion<RotationalExtrusion<radialAxis>> = true;
43} // end namespace Impl
44
50// forward declaration
51template<class TypeTag, class DiscretizationMethod>
53
54template<class TypeTag>
55class NavierStokesResidualImpl<TypeTag, DiscretizationMethods::Staggered>
56: public StaggeredLocalResidual<TypeTag>
57{
59 friend class StaggeredLocalResidual<TypeTag>;
60
62
63 using GridVolumeVariables = typename GridVariables::GridVolumeVariables;
64 using ElementVolumeVariables = typename GridVolumeVariables::LocalView;
65 using VolumeVariables = typename GridVolumeVariables::VolumeVariables;
66
67 using GridFluxVariablesCache = typename GridVariables::GridFluxVariablesCache;
68 using ElementFluxVariablesCache = typename GridFluxVariablesCache::LocalView;
69
70 using GridFaceVariables = typename GridVariables::GridFaceVariables;
71 using ElementFaceVariables = typename GridFaceVariables::LocalView;
72
77 using FVElementGeometry = typename GridGeometry::LocalView;
78 using GridView = typename GridGeometry::GridView;
79 using Element = typename GridView::template Codim<0>::Entity;
80 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
81 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
82 using Extrusion = Extrusion_t<GridGeometry>;
84 using CellCenterPrimaryVariables = GetPropType<TypeTag, Properties::CellCenterPrimaryVariables>;
88
89 static constexpr bool normalizePressure = getPropValue<TypeTag, Properties::NormalizePressure>();
90
91 using CellCenterResidual = CellCenterPrimaryVariables;
92 using FaceResidual = FacePrimaryVariables;
93
95
96public:
97 using EnergyLocalResidual = FreeFlowEnergyLocalResidual<GridGeometry, FluxVariables, ModelTraits::enableEnergyBalance(), (ModelTraits::numFluidComponents() > 1)>;
98
99 // account for the offset of the cell center privars within the PrimaryVariables container
100 static constexpr auto cellCenterOffset = ModelTraits::numEq() - CellCenterPrimaryVariables::dimension;
101 static_assert(cellCenterOffset == ModelTraits::dim(), "cellCenterOffset must equal dim for staggered NavierStokes");
102
104 using ParentType::ParentType;
105
107 CellCenterPrimaryVariables computeFluxForCellCenter(const Problem& problem,
108 const Element &element,
109 const FVElementGeometry& fvGeometry,
110 const ElementVolumeVariables& elemVolVars,
111 const ElementFaceVariables& elemFaceVars,
112 const SubControlVolumeFace &scvf,
113 const ElementFluxVariablesCache& elemFluxVarsCache) const
114 {
115 FluxVariables fluxVars;
116 CellCenterPrimaryVariables flux = fluxVars.computeMassFlux(problem, element, fvGeometry, elemVolVars,
117 elemFaceVars, scvf, elemFluxVarsCache[scvf]);
118
119 EnergyLocalResidual::heatFlux(flux, problem, element, fvGeometry, elemVolVars, elemFaceVars, scvf);
120
121 return flux;
122 }
123
125 CellCenterPrimaryVariables computeSourceForCellCenter(const Problem& problem,
126 const Element &element,
127 const FVElementGeometry& fvGeometry,
128 const ElementVolumeVariables& elemVolVars,
129 const ElementFaceVariables& elemFaceVars,
130 const SubControlVolume &scv) const
131 {
132 CellCenterPrimaryVariables result(0.0);
133
134 // get the values from the problem
135 const auto sourceValues = problem.source(element, fvGeometry, elemVolVars, elemFaceVars, scv);
136
137 // copy the respective cell center related values to the result
138 for (int i = 0; i < result.size(); ++i)
139 result[i] = sourceValues[i + cellCenterOffset];
140
141 return result;
142 }
143
144
146 CellCenterPrimaryVariables computeStorageForCellCenter(const Problem& problem,
147 const SubControlVolume& scv,
148 const VolumeVariables& volVars) const
149 {
150 CellCenterPrimaryVariables storage;
151 storage[Indices::conti0EqIdx - ModelTraits::dim()] = volVars.density();
152
153 EnergyLocalResidual::fluidPhaseStorage(storage, volVars);
154
155 return storage;
156 }
157
159 FacePrimaryVariables computeStorageForFace(const Problem& problem,
160 const SubControlVolumeFace& scvf,
161 const VolumeVariables& volVars,
162 const ElementFaceVariables& elemFaceVars) const
163 {
164 FacePrimaryVariables storage(0.0);
165 const Scalar velocity = elemFaceVars[scvf].velocitySelf();
166 storage[0] = volVars.density() * velocity;
167 return storage;
168 }
169
171 FacePrimaryVariables computeSourceForFace(const Problem& problem,
172 const Element& element,
173 const FVElementGeometry& fvGeometry,
174 const SubControlVolumeFace& scvf,
175 const ElementVolumeVariables& elemVolVars,
176 const ElementFaceVariables& elemFaceVars) const
177 {
178 FacePrimaryVariables source(0.0);
179 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
180 source += problem.gravity()[scvf.directionIndex()] * insideVolVars.density();
181 source += problem.source(element, fvGeometry, elemVolVars, elemFaceVars, scvf)[Indices::velocity(scvf.directionIndex())];
182
183 // Axisymmetric problems in 2D feature an extra source terms arising from the transformation to cylindrical coordinates.
184 // See Ferziger/Peric: Computational methods for fluid dynamics chapter 8.
185 // https://doi.org/10.1007/978-3-540-68228-8 (page 301)
186 if constexpr (ModelTraits::dim() == 2 && Impl::isRotationalExtrusion<Extrusion>)
187 {
188 if (scvf.directionIndex() == Extrusion::radialAxis)
189 {
190 // Velocity term
191 const auto r = scvf.center()[scvf.directionIndex()];
192 source -= -2.0*insideVolVars.effectiveViscosity() * elemFaceVars[scvf].velocitySelf() / (r*r);
193
194 // Pressure term (needed because we incorporate pressure in terms of a surface integral).
195 // grad(p) becomes div(pI) + (p/r)*n_r in cylindrical coordinates. The second term
196 // is new with respect to Cartesian coordinates and handled below as a source term.
197 const Scalar pressure =
198 normalizePressure ? insideVolVars.pressure() - problem.initial(scvf)[Indices::pressureIdx]
199 : insideVolVars.pressure();
200
201 source += pressure/r;
202 }
203 }
204
205 return source;
206 }
207
209 FacePrimaryVariables computeFluxForFace(const Problem& problem,
210 const Element& element,
211 const SubControlVolumeFace& scvf,
212 const FVElementGeometry& fvGeometry,
213 const ElementVolumeVariables& elemVolVars,
214 const ElementFaceVariables& elemFaceVars,
215 const ElementFluxVariablesCache& elemFluxVarsCache) const
216 {
217 FluxVariables fluxVars;
218 return fluxVars.computeMomentumFlux(problem, element, scvf, fvGeometry, elemVolVars, elemFaceVars, elemFluxVarsCache.gridFluxVarsCache());
219 }
220
224 CellCenterResidual computeBoundaryFluxForCellCenter(const Problem& problem,
225 const Element& element,
226 const FVElementGeometry& fvGeometry,
227 const SubControlVolumeFace& scvf,
228 const ElementVolumeVariables& elemVolVars,
229 const ElementFaceVariables& elemFaceVars,
230 const ElementBoundaryTypes& elemBcTypes,
231 const ElementFluxVariablesCache& elemFluxVarsCache) const
232 {
233 CellCenterResidual result(0.0);
234
235 if (scvf.boundary())
236 {
237 const auto bcTypes = problem.boundaryTypes(element, scvf);
238
239 // no fluxes occur over symmetry boundaries
240 if (bcTypes.isSymmetry())
241 return result;
242
243 // treat Dirichlet and outflow BCs
244 result = computeFluxForCellCenter(problem, element, fvGeometry, elemVolVars, elemFaceVars, scvf, elemFluxVarsCache);
245
246 // treat Neumann BCs, i.e. overwrite certain fluxes by user-specified values
247 static constexpr auto numEqCellCenter = CellCenterResidual::dimension;
248 if (bcTypes.hasNeumann())
249 {
250 const auto extrusionFactor = elemVolVars[scvf.insideScvIdx()].extrusionFactor();
251 const auto neumannFluxes = problem.neumann(element, fvGeometry, elemVolVars, elemFaceVars, scvf);
252
253 for (int eqIdx = 0; eqIdx < numEqCellCenter; ++eqIdx)
254 {
255 if (bcTypes.isNeumann(eqIdx + cellCenterOffset))
256 result[eqIdx] = neumannFluxes[eqIdx + cellCenterOffset] * extrusionFactor * Extrusion::area(scvf);
257 }
258 }
259
260 // account for wall functions, if used
261 incorporateWallFunction_(result, problem, element, fvGeometry, scvf, elemVolVars, elemFaceVars);
262 }
263 return result;
264 }
265
269 void evalDirichletBoundariesForFace(FaceResidual& residual,
270 const Problem& problem,
271 const Element& element,
272 const FVElementGeometry& fvGeometry,
273 const SubControlVolumeFace& scvf,
274 const ElementVolumeVariables& elemVolVars,
275 const ElementFaceVariables& elemFaceVars,
276 const ElementBoundaryTypes& elemBcTypes,
277 const ElementFluxVariablesCache& elemFluxVarsCache) const
278 {
279 if (scvf.boundary())
280 {
281 // handle the actual boundary conditions:
282 const auto bcTypes = problem.boundaryTypes(element, scvf);
283
284 if(bcTypes.isDirichlet(Indices::velocity(scvf.directionIndex())))
285 {
286 // set a fixed value for the velocity for Dirichlet boundary conditions
287 const Scalar velocity = elemFaceVars[scvf].velocitySelf();
288 const Scalar dirichletValue = problem.dirichlet(element, scvf)[Indices::velocity(scvf.directionIndex())];
289 residual = velocity - dirichletValue;
290 }
291 else if(bcTypes.isSymmetry())
292 {
293 // for symmetry boundary conditions, there is no flow accross the boundary and
294 // we therefore treat it like a Dirichlet boundary conditions with zero velocity
295 const Scalar velocity = elemFaceVars[scvf].velocitySelf();
296 const Scalar fixedValue = 0.0;
297 residual = velocity - fixedValue;
298 }
299 }
300 }
301
305 FaceResidual computeBoundaryFluxForFace(const Problem& problem,
306 const Element& element,
307 const FVElementGeometry& fvGeometry,
308 const SubControlVolumeFace& scvf,
309 const ElementVolumeVariables& elemVolVars,
310 const ElementFaceVariables& elemFaceVars,
311 const ElementBoundaryTypes& elemBcTypes,
312 const ElementFluxVariablesCache& elemFluxVarsCache) const
313 {
314 FaceResidual result(0.0);
315
316 if (scvf.boundary())
317 {
318 FluxVariables fluxVars;
319
320 // handle the actual boundary conditions:
321 const auto bcTypes = problem.boundaryTypes(element, scvf);
322 if (bcTypes.isNeumann(Indices::velocity(scvf.directionIndex())))
323 {
324 // the source term has already been accounted for, here we
325 // add a given Neumann flux for the face on the boundary itself ...
326 const auto extrusionFactor = elemVolVars[scvf.insideScvIdx()].extrusionFactor();
327 result = problem.neumann(element, fvGeometry, elemVolVars, elemFaceVars, scvf)[Indices::velocity(scvf.directionIndex())]
328 * extrusionFactor * Extrusion::area(scvf);
329
330 // ... and treat the fluxes of the remaining (frontal and lateral) faces of the staggered control volume
331 result += fluxVars.computeMomentumFlux(problem, element, scvf, fvGeometry, elemVolVars, elemFaceVars, elemFluxVarsCache.gridFluxVarsCache());
332 }
333 else if(bcTypes.isDirichlet(Indices::pressureIdx))
334 {
335 // we are at an "fixed pressure" boundary for which the resdiual of the momentum balance needs to be assembled
336 // as if it where inside the domain and not on the boundary (source term has already been acounted for)
337 result = fluxVars.computeMomentumFlux(problem, element, scvf, fvGeometry, elemVolVars, elemFaceVars, elemFluxVarsCache.gridFluxVarsCache());
338
339 // incorporate the inflow or outflow contribution
340 result += fluxVars.inflowOutflowBoundaryFlux(problem, element, scvf, elemVolVars, elemFaceVars);
341 }
342 }
343 return result;
344 }
345
346private:
347
349 template<class ...Args, bool turbulenceModel = ModelTraits::usesTurbulenceModel(), std::enable_if_t<!turbulenceModel, int> = 0>
350 void incorporateWallFunction_(Args&&... args) const
351 {}
352
354 template<bool turbulenceModel = ModelTraits::usesTurbulenceModel(), std::enable_if_t<turbulenceModel, int> = 0>
355 void incorporateWallFunction_(CellCenterResidual& boundaryFlux,
356 const Problem& problem,
357 const Element& element,
358 const FVElementGeometry& fvGeometry,
359 const SubControlVolumeFace& scvf,
360 const ElementVolumeVariables& elemVolVars,
361 const ElementFaceVariables& elemFaceVars) const
362 {
363 static constexpr auto numEqCellCenter = CellCenterResidual::dimension;
364 const auto extrusionFactor = elemVolVars[scvf.insideScvIdx()].extrusionFactor();
365
366 // account for wall functions, if used
367 for(int eqIdx = 0; eqIdx < numEqCellCenter; ++eqIdx)
368 {
369 // use a wall function
370 if(problem.useWallFunction(element, scvf, eqIdx + cellCenterOffset))
371 {
372 boundaryFlux[eqIdx] = problem.wallFunction(element, fvGeometry, elemVolVars, elemFaceVars, scvf)[eqIdx]
373 * extrusionFactor * Extrusion::area(scvf);
374 }
375 }
376 }
377
379 Implementation &asImp_()
380 { return *static_cast<Implementation *>(this); }
381
383 const Implementation &asImp_() const
384 { return *static_cast<const Implementation *>(this); }
385};
386
387} // end namespace Dumux
388
389#endif
Calculates the element-wise residual for the staggered FV scheme.
Helper classes to compute the integration elements.
The available discretization methods in Dumux.
Definition: adapt.hh:29
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition: extrusion.hh:177
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:150
std::string pressure(int phaseIdx) noexcept
I/O name of pressure for multiphase systems.
Definition: name.hh:34
Calculates the element-wise residual for the staggered FV scheme.
Definition: staggeredlocalresidual.hh:41
Element-wise calculation of the Navier-Stokes residual for models using the staggered discretization.
Definition: freeflow/navierstokes/localresidual.hh:35
FacePrimaryVariables computeFluxForFace(const Problem &problem, const Element &element, const SubControlVolumeFace &scvf, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars, const ElementFluxVariablesCache &elemFluxVarsCache) const
Evaluate the momentum flux for the face control volume.
Definition: freeflow/navierstokes/staggered/localresidual.hh:209
void evalDirichletBoundariesForFace(FaceResidual &residual, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const SubControlVolumeFace &scvf, const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars, const ElementBoundaryTypes &elemBcTypes, const ElementFluxVariablesCache &elemFluxVarsCache) const
Evaluate Dirichlet (fixed value) boundary conditions for a face dof.
Definition: freeflow/navierstokes/staggered/localresidual.hh:269
FacePrimaryVariables computeStorageForFace(const Problem &problem, const SubControlVolumeFace &scvf, const VolumeVariables &volVars, const ElementFaceVariables &elemFaceVars) const
Evaluate the storage term for the face control volume.
Definition: freeflow/navierstokes/staggered/localresidual.hh:159
FacePrimaryVariables computeSourceForFace(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const SubControlVolumeFace &scvf, const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars) const
Evaluate the source term for the face control volume.
Definition: freeflow/navierstokes/staggered/localresidual.hh:171
FaceResidual computeBoundaryFluxForFace(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const SubControlVolumeFace &scvf, const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars, const ElementBoundaryTypes &elemBcTypes, const ElementFluxVariablesCache &elemFluxVarsCache) const
Evaluate boundary fluxes for a face dof.
Definition: freeflow/navierstokes/staggered/localresidual.hh:305
CellCenterResidual computeBoundaryFluxForCellCenter(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const SubControlVolumeFace &scvf, const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars, const ElementBoundaryTypes &elemBcTypes, const ElementFluxVariablesCache &elemFluxVarsCache) const
Evaluate boundary conditions for a cell center dof.
Definition: freeflow/navierstokes/staggered/localresidual.hh:224
CellCenterPrimaryVariables computeFluxForCellCenter(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars, const SubControlVolumeFace &scvf, const ElementFluxVariablesCache &elemFluxVarsCache) const
Evaluate fluxes entering or leaving the cell center control volume.
Definition: freeflow/navierstokes/staggered/localresidual.hh:107
CellCenterPrimaryVariables computeStorageForCellCenter(const Problem &problem, const SubControlVolume &scv, const VolumeVariables &volVars) const
Evaluate the storage term for the cell center control volume.
Definition: freeflow/navierstokes/staggered/localresidual.hh:146
CellCenterPrimaryVariables computeSourceForCellCenter(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars, const SubControlVolume &scv) const
Evaluate the source term for the cell center control volume.
Definition: freeflow/navierstokes/staggered/localresidual.hh:125
Definition: freeflow/nonisothermal/localresidual.hh:34
Declares all properties used in Dumux.