version 3.11-dev
felocalresidual.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// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_NAVIERSTOKES_MOMENTUM_CVFE_FE_LOCAL_RESIDUAL_HELPER_HH
13#define DUMUX_NAVIERSTOKES_MOMENTUM_CVFE_FE_LOCAL_RESIDUAL_HELPER_HH
14
15#include <dune/geometry/quadraturerules.hh>
16#include <dumux/common/typetraits/localdofs_.hh>
20
21#include "flux.hh"
22
23namespace Dumux {
24
29template<class Scalar, class NumEqVector, class LocalBasis, class Extrusion>
31{
32 using RangeType = typename LocalBasis::Traits::RangeType;
33
34public:
45 template<class ResidualVector, class Problem, class FVElementGeometry, class ElementVariables>
46 static void addStorageTerms(ResidualVector& residual,
47 const Problem& problem,
48 const FVElementGeometry& fvGeometry,
49 const ElementVariables& prevElemVars,
50 const ElementVariables& curElemVars,
51 const Scalar timeStepSize)
52 {
53 if constexpr (Detail::LocalDofs::hasNonCVLocalDofsInterface<FVElementGeometry>())
54 {
55 // Make sure we don't iterate over quadrature points if there are no hybrid dofs
56 if (nonCVLocalDofs(fvGeometry).empty())
57 return;
58
59 const auto& localBasis = fvGeometry.feLocalBasis();
60 std::vector<RangeType> integralShapeFunctions(localBasis.size(), RangeType(0.0));
61
62 // We apply mass lumping such that we only need to calculate the integral of basis functions
63 const auto& geometry = fvGeometry.elementGeometry();
64 const auto& element = fvGeometry.element();
65 using GlobalPosition = typename FVElementGeometry::GridGeometry::GlobalCoordinate;
67
68 for (const auto& qpData : CVFE::quadratureRule(fvGeometry, element))
69 {
70 const auto& ipData = qpData.ipData();
71 // Obtain and store shape function values and gradients at the current quad point
72 FeIpData feIpData(geometry, ipData.local(), ipData.global(), localBasis);
73
74 // get density from the problem
75 for (const auto& localDof : nonCVLocalDofs(fvGeometry))
76 integralShapeFunctions[localDof.index()] += qpData.weight() * feIpData.shapeValue(localDof.index());
77 }
78
79 for (const auto& localDof : nonCVLocalDofs(fvGeometry))
80 {
81 const auto localDofIdx = localDof.index();
82 const auto& data = ipData(fvGeometry, localDof);
83 const auto curDensity = problem.density(element, fvGeometry, data, false);
84 const auto prevDensity = problem.density(element, fvGeometry, data, true);
85 const auto curVelocity = curElemVars[localDofIdx].velocity();
86 const auto prevVelocity = prevElemVars[localDofIdx].velocity();
87 auto timeDeriv = (curDensity*curVelocity - prevDensity*prevVelocity);
88 timeDeriv /= timeStepSize;
89
90 // add storage to residual
91 for (int eqIdx = 0; eqIdx < NumEqVector::dimension; ++eqIdx)
92 residual[localDofIdx][eqIdx] += integralShapeFunctions[localDofIdx]*timeDeriv[eqIdx];
93 }
94 }
95 }
96
107 template<class ResidualVector, class Problem, class FVElementGeometry,
108 class ElementVariables, class ElementFluxVariablesCache, class ElementBoundaryTypes>
109 [[deprecated("This function is deprecated and will be removed after release 3.11. "
110 "Use addFluxAndSourceTerms(residual, problem, fvGeometry, elemVars, elemBcTypes) instead.")]]
111 static void addFluxAndSourceTerms(ResidualVector& residual,
112 const Problem& problem,
113 const FVElementGeometry& fvGeometry,
114 const ElementVariables& elemVars,
115 const ElementFluxVariablesCache& elemFluxVarsCache,
116 const ElementBoundaryTypes& elemBcTypes)
117 {
118 if constexpr (Detail::LocalDofs::hasNonCVLocalDofsInterface<FVElementGeometry>())
119 {
120 // Make sure we don't iterate over quadrature points if there are no hybrid dofs
121 if (nonCVLocalDofs(fvGeometry).empty())
122 return;
123
124 if (!problem.pointSourceMap().empty())
125 DUNE_THROW(Dune::NotImplemented, "Point sources are not implemented for hybrid momentum schemes.");
126
127 static const bool enableUnsymmetrizedVelocityGradient
128 = getParamFromGroup<bool>(problem.paramGroup(), "FreeFlow.EnableUnsymmetrizedVelocityGradient", false);
129
130 const auto& element = fvGeometry.element();
131 using FluxVariablesCache = typename ElementFluxVariablesCache::FluxVariablesCache;
133 for (const auto& qpData : CVFE::quadratureRule(fvGeometry, element))
134 {
135 const auto& ipData = qpData.ipData();
136 // Obtain and store shape function values and gradients at the current quad point
137 const auto& cache = elemFluxVarsCache[ipData];
138 FluxFunctionContext context(problem, fvGeometry, elemVars, cache);
139 const auto& v = context.velocity();
140 const auto& gradV = context.gradVelocity();
141
142 // get viscosity from the problem
143 const Scalar mu = problem.effectiveViscosity(element, fvGeometry, ipData);
144 // get density from the problem
145 const Scalar density = problem.density(element, fvGeometry, ipData);
146
147 for (const auto& localDof : nonCVLocalDofs(fvGeometry))
148 {
149 const auto localDofIdx = localDof.index();
150 NumEqVector fluxAndSourceTerm(0.0);
151 // add advection term
152 if (problem.enableInertiaTerms())
153 fluxAndSourceTerm -= density*(v*cache.gradN(localDofIdx))*v;
154
155 // add diffusion term
156 fluxAndSourceTerm += enableUnsymmetrizedVelocityGradient ?
157 mu*mv(gradV, cache.gradN(localDofIdx))
158 : mu*mv(gradV + getTransposed(gradV), cache.gradN(localDofIdx));
159
160 // add pressure term
161 fluxAndSourceTerm -= problem.pressure(element, fvGeometry, ipData) * cache.gradN(localDofIdx);
162
163 // finally add source and flux boundary terms and add everything to residual
164 auto sourceAtIp = problem.source(fvGeometry, elemVars, ipData);
165 // add gravity term rho*g (note that gravity might be zero in case it's disabled in the problem)
166 sourceAtIp += density * problem.gravity();
167
168 const auto& shapeValues = cache.shapeValues();
169 for (int eqIdx = 0; eqIdx < NumEqVector::dimension; ++eqIdx)
170 {
171 fluxAndSourceTerm[eqIdx] -= shapeValues[localDofIdx] * sourceAtIp[eqIdx];
172 residual[localDofIdx][eqIdx] += qpData.weight()*fluxAndSourceTerm[eqIdx];
173 }
174 }
175 }
176
177 if (elemBcTypes.hasFluxBoundary())
178 addBoundaryFluxes(residual, problem, fvGeometry, elemVars, elemFluxVarsCache, elemBcTypes);
179 }
180 }
181
192 template<class ResidualVector, class Problem, class FVElementGeometry,
193 class ElementVariables, class ElementFluxVariablesCache, class ElementBoundaryTypes>
194 [[deprecated("This function is deprecated and will be removed after release 3.11. "
195 "Use addBoundaryFluxes(residual, problem, fvGeometry, elemVars, elemBcTypes) instead.")]]
196 static void addBoundaryFluxes(ResidualVector& residual,
197 const Problem& problem,
198 const FVElementGeometry& fvGeometry,
199 const ElementVariables& elemVars,
200 const ElementFluxVariablesCache& elemFluxVarsCache,
201 const ElementBoundaryTypes& elemBcTypes)
202 {
203 ResidualVector flux(0.0);
204
205 const auto& element = fvGeometry.element();
206 for (const auto& boundaryFace : boundaryFaces(fvGeometry))
207 {
208 const auto& bcTypes = elemBcTypes.get(fvGeometry, boundaryFace);
209 if (!bcTypes.hasFluxBoundary())
210 continue;
211
212 problem.addBoundaryFluxIntegrals(flux, fvGeometry, elemVars, elemFluxVarsCache, boundaryFace, bcTypes);
213 }
214 residual += flux;
215 }
216
226 template<class ResidualVector, class Problem, class FVElementGeometry,
227 class ElementVariables, class ElementBoundaryTypes>
228 static void addFluxAndSourceTerms(ResidualVector& residual,
229 const Problem& problem,
230 const FVElementGeometry& fvGeometry,
231 const ElementVariables& elemVars,
232 const ElementBoundaryTypes& elemBcTypes)
233 {
234 if constexpr (Detail::LocalDofs::hasNonCVLocalDofsInterface<FVElementGeometry>())
235 {
236 // Make sure we don't iterate over quadrature points if there are no hybrid dofs
237 if (nonCVLocalDofs(fvGeometry).empty())
238 return;
239
240 if (!problem.pointSourceMap().empty())
241 DUNE_THROW(Dune::NotImplemented, "Point sources are not implemented for hybrid momentum schemes.");
242
243 static const bool enableUnsymmetrizedVelocityGradient
244 = getParamFromGroup<bool>(problem.paramGroup(), "FreeFlow.EnableUnsymmetrizedVelocityGradient", false);
245
246 const auto& element = fvGeometry.element();
247 using Cache = typename ElementVariables::InterpolationPointData;
249 for (const auto& qpData : CVFE::quadratureRule(fvGeometry, element))
250 {
251 const auto& ipData = qpData.ipData();
252 // Obtain and store shape function values and gradients at the current quad point
253 const auto& ipCache = cache(elemVars, ipData);
254 FluxFunctionContext context(problem, fvGeometry, elemVars, ipCache);
255 const auto& v = context.velocity();
256 const auto& gradV = context.gradVelocity();
257
258 // get viscosity from the problem
259 const Scalar mu = problem.effectiveViscosity(element, fvGeometry, ipData);
260 // get density from the problem
261 const Scalar density = problem.density(element, fvGeometry, ipData);
262
263 for (const auto& localDof : nonCVLocalDofs(fvGeometry))
264 {
265 const auto localDofIdx = localDof.index();
266 NumEqVector fluxAndSourceTerm(0.0);
267 // add advection term
268 if (problem.enableInertiaTerms())
269 fluxAndSourceTerm -= density*(v*ipCache.gradN(localDofIdx))*v;
270
271 // add diffusion term
272 fluxAndSourceTerm += enableUnsymmetrizedVelocityGradient ?
273 mu*mv(gradV, ipCache.gradN(localDofIdx))
274 : mu*mv(gradV + getTransposed(gradV), ipCache.gradN(localDofIdx));
275
276 // add pressure term
277 fluxAndSourceTerm -= problem.pressure(element, fvGeometry, ipData) * ipCache.gradN(localDofIdx);
278
279 // finally add source and flux boundary term and add everything to residual
280 auto sourceAtIp = problem.source(fvGeometry, elemVars, ipData);
281 // add gravity term rho*g (note that gravity might be zero in case it's disabled in the problem)
282 sourceAtIp += density * problem.gravity();
283
284 const auto& shapeValues = ipCache.shapeValues();
285 for (int eqIdx = 0; eqIdx < NumEqVector::dimension; ++eqIdx)
286 {
287 fluxAndSourceTerm[eqIdx] -= shapeValues[localDofIdx] * sourceAtIp[eqIdx];
288 residual[localDofIdx][eqIdx] += qpData.weight()*fluxAndSourceTerm[eqIdx];
289 }
290 }
291 }
292
293 if (elemBcTypes.hasFluxBoundary())
294 addBoundaryFluxes(residual, problem, fvGeometry, elemVars, elemBcTypes);
295 }
296 }
297
307 template<class ResidualVector, class Problem, class FVElementGeometry,
308 class ElementVariables, class ElementBoundaryTypes>
309 static void addBoundaryFluxes(ResidualVector& residual,
310 const Problem& problem,
311 const FVElementGeometry& fvGeometry,
312 const ElementVariables& elemVars,
313 const ElementBoundaryTypes& elemBcTypes)
314 {
315 ResidualVector flux(0.0);
316
317 const auto& element = fvGeometry.element();
318 for (const auto& boundaryFace : boundaryFaces(fvGeometry))
319 {
320 const auto& bcTypes = elemBcTypes.get(fvGeometry, boundaryFace);
321 if (!bcTypes.hasFluxBoundary())
322 continue;
323
324 problem.addBoundaryFluxIntegrals(flux, fvGeometry, elemVars, boundaryFace, bcTypes);
325 }
326 residual += flux;
327 }
328};
329
330} // end namespace Dumux
331
332#endif
Boundary flag to store e.g. in sub control volume faces.
Definition: fem/interpolationpointdata.hh:21
Helper class for evaluating FE-based local residuals.
Definition: felocalresidual.hh:31
static void addFluxAndSourceTerms(ResidualVector &residual, const Problem &problem, const FVElementGeometry &fvGeometry, const ElementVariables &elemVars, const ElementFluxVariablesCache &elemFluxVarsCache, const ElementBoundaryTypes &elemBcTypes)
Add flux and source residual contribution for non-CV local dofs.
Definition: felocalresidual.hh:111
static void addBoundaryFluxes(ResidualVector &residual, const Problem &problem, const FVElementGeometry &fvGeometry, const ElementVariables &elemVars, const ElementFluxVariablesCache &elemFluxVarsCache, const ElementBoundaryTypes &elemBcTypes)
Evaluate flux boundary contributions.
Definition: felocalresidual.hh:196
static void addFluxAndSourceTerms(ResidualVector &residual, const Problem &problem, const FVElementGeometry &fvGeometry, const ElementVariables &elemVars, const ElementBoundaryTypes &elemBcTypes)
Add flux and source residual contribution for non-CV local dofs.
Definition: felocalresidual.hh:228
static void addBoundaryFluxes(ResidualVector &residual, const Problem &problem, const FVElementGeometry &fvGeometry, const ElementVariables &elemVars, const ElementBoundaryTypes &elemBcTypes)
Evaluate flux boundary contributions.
Definition: felocalresidual.hh:309
static void addStorageTerms(ResidualVector &residual, const Problem &problem, const FVElementGeometry &fvGeometry, const ElementVariables &prevElemVars, const ElementVariables &curElemVars, const Scalar timeStepSize)
Add storage residual contribution for non-CV local dofs.
Definition: felocalresidual.hh:46
Context for interpolating data on interpolation points.
Definition: flux.hh:99
Helper classes to compute the integration elements.
Shape functions and gradients at an interpolation point.
Dune::DenseVector< V >::derived_type mv(const Dune::DenseMatrix< MAT > &M, const Dune::DenseVector< V > &v)
Returns the result of the projection of a vector v with a Matrix M.
Definition: math.hh:829
Dune::FieldMatrix< Scalar, n, m > getTransposed(const Dune::FieldMatrix< Scalar, m, n > &M)
Transpose a FieldMatrix.
Definition: math.hh:712
typename NumEqVectorTraits< PrimaryVariables >::type NumEqVector
A vector with the same size as numbers of equations This is the default implementation and has to be ...
Definition: numeqvector.hh:34
auto quadratureRule(const FVElementGeometry &fvGeometry, const typename FVElementGeometry::SubControlVolume &scv, QuadratureRules::MidpointQuadrature)
Midpoint quadrature for scv.
Definition: quadraturerules.hh:159
std::string density(int phaseIdx) noexcept
I/O name of density for multiphase systems.
Definition: name.hh:53
Definition: adapt.hh:17