version 3.11-dev
Loading...
Searching...
No Matches
assembly/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// 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_BASE_LOCAL_RESIDUAL_HH
13#define DUMUX_BASE_LOCAL_RESIDUAL_HH
14
15#include <cassert>
16
17#include <dune/common/exceptions.hh>
18
19#include <dumux/common/typetraits/localdofs_.hh>
28
29namespace Dumux::Experimental {
30
37template<class TypeTag>
39{
44 using Element = typename GridView::template Codim<0>::Entity;
45 using ElementDiscretization = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;
47 using GridDiscretization = GetPropType<TypeTag, Properties::GridGeometry>;
48 using Extrusion = Extrusion_t<GridDiscretization>;
50 using GridVariablesCache = typename GridVariables::GridVariablesCache;
51 using ElementVariables = typename GridVariablesCache::LocalView;
52 using TimeLoop = TimeLoopBase<Scalar>;
53
54public:
57
59 LocalResidual(const Problem* problem,
60 const TimeLoop* timeLoop = nullptr)
61 : problem_(problem)
62 , timeLoop_(timeLoop)
63 {}
64
69 // \{
70
80 const ElementDiscretization& elemDisc,
81 const ElementVariables& elemVars) const
82 {
83 checkStorageHook_();
84
85 ElementResidualVector storage(Dumux::Detail::LocalDofs::numLocalDofs(elemDisc));
86
88 for (const auto& scv : scvs(elemDisc))
89 storage[scv.localDofIndex()] =
90 this->asImp().storageIntegral(elemDisc, elemVars, scv, /*isPreviousTimeLevel=*/false);
91
92 // allow models to contribute additional storage terms (e.g. hybrid CVFE/FE)
93 this->asImp().addToElementStorage(storage, this->problem(), element, elemDisc, elemVars, /*isPreviousTimeLevel=*/false);
94
95 return storage;
96 }
97
98 ElementResidualVector evalStorage(const Element& element,
99 const ElementDiscretization& elemDisc,
100 const ElementVariables& prevElemVars,
101 const ElementVariables& curElemVars) const
102 {
103 assert(!this->isStationary() && "no time loop set for storage term evaluation");
104
105 // initialize the residual vector for all local dofs in this element
106 ElementResidualVector residual(Dumux::Detail::LocalDofs::numLocalDofs(elemDisc));
107
108 // evaluate the volume terms (storage + source terms)
109 // forward to the local residual specialized for the discretization methods
111 {
112 for (const auto& scv : scvs(elemDisc))
113 this->asImp().evalStorage(residual, this->problem(), element, elemDisc, prevElemVars, curElemVars, scv);
114 }
115
116 // allow for additional contributions (e.g. hybrid CVFE / FE schemes)
117 // discretized in time in the same way as the scv storage terms
118 checkStorageHook_();
119 ElementResidualVector additionalStorage(residual.size());
120 ElementResidualVector additionalPrevStorage(residual.size());
121 this->asImp().addToElementStorage(additionalStorage, this->problem(), element, elemDisc, curElemVars, /*isPreviousTimeLevel=*/false);
122 this->asImp().addToElementStorage(additionalPrevStorage, this->problem(), element, elemDisc, prevElemVars, /*isPreviousTimeLevel=*/true);
123 additionalStorage -= additionalPrevStorage;
124 additionalStorage /= timeLoop_->timeStepSize();
125 residual += additionalStorage;
126
127 return residual;
128 }
129
139 const ElementDiscretization& elemDisc,
140 const ElementVariables& elemVars) const
141 {
142 // initialize the residual vector for all local dofs in this element
143 ElementResidualVector residual(Dumux::Detail::LocalDofs::numLocalDofs(elemDisc));
144
146 {
147 // evaluate the volume terms (storage + source terms)
148 // forward to the local residual specialized for the discretization methods
149 for (const auto& scv : scvs(elemDisc))
150 this->asImp().evalSource(residual, this->problem(), element, elemDisc, elemVars, scv);
151
152 // forward to the local residual specialized for the discretization methods
153 // TODO: Provide scvfs range only over interior scvfs
154 for (auto&& scvf : scvfs(elemDisc))
155 if(!scvf.boundary())
156 this->asImp().evalFlux(residual, this->problem(), element, elemDisc, elemVars, scvf);
157 }
158
159 // allow for additional contributions (e.g. hybrid CVFE / FE schemes)
160 this->asImp().addToElementFluxAndSourceResidual(residual, this->problem(), element, elemDisc, elemVars);
161
162 // add boundary flux contributions
163 this->asImp().addBoundaryFluxIntegral(residual, this->problem(), elemDisc, elemVars);
164
165 return residual;
166 }
167
181 const Problem& problem,
182 const Element& element,
183 const ElementDiscretization& elemDisc,
184 const ElementVariables& elemVars,
185 bool isPreviousTimeLevel) const
186 {}
187
190 const Problem& problem,
191 const Element& element,
192 const ElementDiscretization& elemDisc,
193 const ElementVariables& curElemVars) const
194 {}
195
198 const Problem& problem,
199 const ElementDiscretization& elemDisc,
200 const ElementVariables& elemVars) const
201 {
202 if(!elemDisc.hasBoundaryFaces())
203 return;
204
205 for (const auto& boundaryFace : boundaryFaces(elemDisc))
206 {
207 const auto& bcTypes = problem.boundaryTypes(elemDisc, boundaryFace);
208 if(!bcTypes.hasFluxBoundary())
209 continue;
210
213 problem.addFEBoundaryFluxIntegral(residual, elemDisc, elemVars, boundaryFace, bcTypes);
214
216 for(const auto& scvf : scvfs(elemDisc, boundaryFace))
217 problem.addFVBoundaryFluxIntegral(residual, elemDisc, elemVars, scvf, bcTypes);
218 }
219 }
220
221 // \}
222
227 // \{
228
239 template<class SubControlVolume>
240 NumEqVector storageIntegral(const ElementDiscretization& elemDisc,
241 const ElementVariables& elemVars,
242 const SubControlVolume& scv,
243 bool isPreviousTimeLevel) const
244 {
245 DUNE_THROW(Dune::NotImplemented, "This model does not implement a storageIntegral method!");
246 }
247
258 template<class SubControlVolume>
259 NumEqVector sourceIntegral(const ElementDiscretization& elemDisc,
260 const ElementVariables& elemVars,
261 const SubControlVolume& scv) const
262 {
263 NumEqVector source(0.0);
264
265 const auto& problem = this->asImp().problem();
266 for (const auto& qpData : CVFE::quadratureRule(elemDisc, scv))
267 source += qpData.weight() * problem.source(elemDisc, elemVars, qpData.ipData());
268
269 source *= elemVars[scv].extrusionFactor();
270
271 // add contribution from possible point sources
272 const auto& pointSources = problem.pointSources();
273 if (!pointSources.empty())
274 for (const auto& context : pointSources.contexts(elemDisc, scv))
275 {
276 auto psValues = pointSources.eval(elemDisc, elemVars, context);
277 source += psValues;
278 }
279
280 return source;
281 }
282
293 template<class SubControlVolumeFace>
294 NumEqVector fluxIntegral(const ElementDiscretization& elemDisc,
295 const ElementVariables& elemVars,
296 const SubControlVolumeFace& scvf) const
297 {
298 DUNE_THROW(Dune::NotImplemented, "This model does not implement a fluxIntegral method!");
299 }
300
301 // \}
302
307 // \{
308
322 template<class SubControlVolume>
324 const Problem& problem,
325 const Element& element,
326 const ElementDiscretization& elemDisc,
327 const ElementVariables& prevElemVars,
328 const ElementVariables& curElemVars,
329 const SubControlVolume& scv) const
330 {
331 // mass balance within the element. this is the
332 // \f$\frac{\partial S}{\partial t}\f$ term if using implicit or explicit
333 // euler as time discretization.
334 //
335 // TODO: We might need a more explicit way for
336 // doing the time discretization...
337
339 NumEqVector prevStorage = this->asImp().storageIntegral(elemDisc, prevElemVars, scv, /*previous time level?*/true);
340 NumEqVector storage = this->asImp().storageIntegral(elemDisc, curElemVars, scv, /*previous time level?*/false);
341
342 storage -= prevStorage;
343 storage /= timeLoop_->timeStepSize();
344
345 residual[scv.localDofIndex()] += storage;
346 }
347
360 template<class SubControlVolume>
362 const Problem& problem,
363 const Element& element,
364 const ElementDiscretization& elemDisc,
365 const ElementVariables& curElemVars,
366 const SubControlVolume& scv) const
367 {
369 NumEqVector source = this->asImp().sourceIntegral(elemDisc, curElemVars, scv);
371 residual[scv.localDofIndex()] -= source;
372 }
373
384 template<class SubControlVolumeFace>
386 const Problem& problem,
387 const Element& element,
388 const ElementDiscretization& elemDisc,
389 const ElementVariables& elemVars,
390 const SubControlVolumeFace& scvf) const {}
391
402 template<class SubControlVolumeFace>
403 NumEqVector evalFlux(const Problem& problem,
404 const Element& element,
405 const ElementDiscretization& elemDisc,
406 const ElementVariables& elemVars,
407 const SubControlVolumeFace& scvf) const
408 {
409 return asImp().evalFlux(problem, element, elemDisc, elemVars, scvf);
410 }
411
412 //\}
413
417 // \{
418
420 const Problem& problem() const
421 { return *problem_; }
422
425 const TimeLoop& timeLoop() const
426 { return *timeLoop_; }
427
429 bool isStationary() const
430 { return !timeLoop_; }
431
432 // \}
433
434protected:
435 Implementation& asImp()
436 { return *static_cast<Implementation*>(this); }
437
438 const Implementation& asImp() const
439 { return *static_cast<const Implementation*>(this); }
440
441private:
442 static constexpr void checkStorageHook_()
443 {
444 static_assert(!requires { &Implementation::addToElementStorageResidual; },
445 "addToElementStorageResidual(prevElemVars, curElemVars) is not called anymore. "
446 "Implement addToElementStorage(..., elemVars, isPreviousTimeLevel) returning the storage at one time level.");
447 }
448
449 const Problem* problem_;
450 const TimeLoop* timeLoop_;
451};
452
453} // end namespace Dumux::Experimental
454
455#endif
GVC GridVariablesCache
export type of the grid variables cache
Definition discretization/gridvariables.hh:33
ElementResidualVector evalStorage(const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &prevElemVars, const ElementVariables &curElemVars) const
Definition assembly/localresidual.hh:98
LocalResidual(const Problem *problem, const TimeLoop *timeLoop=nullptr)
the constructor
Definition assembly/localresidual.hh:59
void evalSource(ElementResidualVector &residual, const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &curElemVars, const SubControlVolume &scv) const
Compute the source local residual, i.e. the deviation of the source term from zero.
Definition assembly/localresidual.hh:361
NumEqVector sourceIntegral(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const SubControlVolume &scv) const
Calculate the source term integral of the equation.
Definition assembly/localresidual.hh:259
NumEqVector evalFlux(const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const SubControlVolumeFace &scvf) const
Compute the fluxes of the local residual.
Definition assembly/localresidual.hh:403
ElementResidualVector evalFluxAndSource(const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars) const
Compute the flux and source.
Definition assembly/localresidual.hh:138
void addToElementStorage(ElementResidualVector &storage, const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars, bool isPreviousTimeLevel) const
Add additional storage contributions at one time level (e.g. hybrid CVFE or FE schemes).
Definition assembly/localresidual.hh:180
const Problem & problem() const
the problem
Definition assembly/localresidual.hh:420
const TimeLoop & timeLoop() const
Definition assembly/localresidual.hh:425
bool isStationary() const
returns true if the residual is stationary
Definition assembly/localresidual.hh:429
const Implementation & asImp() const
Definition assembly/localresidual.hh:438
void evalFlux(ElementResidualVector &residual, const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const SubControlVolumeFace &scvf) const
Compute the fluxes of the local residual.
Definition assembly/localresidual.hh:385
NumEqVector storageIntegral(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const SubControlVolume &scv, bool isPreviousTimeLevel) const
Calculate the source term integral of the equation.
Definition assembly/localresidual.hh:240
void addBoundaryFluxIntegral(ElementResidualVector &residual, const Problem &problem, const ElementDiscretization &elemDisc, const ElementVariables &elemVars) const
add boundary flux contributions
Definition assembly/localresidual.hh:197
void addToElementFluxAndSourceResidual(ElementResidualVector &residual, const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &curElemVars) const
add additional flux and source contributions (e.g. hybrid CVFE or FE schemes)
Definition assembly/localresidual.hh:189
ElementResidualVector evalStorageCurrentLevel(const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &elemVars) const
Evaluate the raw (undivided) storage at the current time level.
Definition assembly/localresidual.hh:79
Implementation & asImp()
Definition assembly/localresidual.hh:435
void evalStorage(ElementResidualVector &residual, const Problem &problem, const Element &element, const ElementDiscretization &elemDisc, const ElementVariables &prevElemVars, const ElementVariables &curElemVars, const SubControlVolume &scv) const
Compute the storage local residual, i.e. the deviation of the storage term from zero for instationary...
Definition assembly/localresidual.hh:323
NumEqVector fluxIntegral(const ElementDiscretization &elemDisc, const ElementVariables &elemVars, const SubControlVolumeFace &scvf) const
Calculate the flux integral of the equation.
Definition assembly/localresidual.hh:294
ReservedBlockVector< NumEqVector, Dumux::Detail::LocalDofs::maxNumLocalDofs< ElementDiscretization >()> ElementResidualVector
the container storing all element residuals
Definition assembly/localresidual.hh:56
A arithmetic block vector type based on DUNE's reserved vector.
Definition reservedblockvector.hh:26
Manages the handling of time dependent problems.
Definition common/timeloop.hh:84
Defines all properties used in Dumux.
Manages the handling of time dependent problems.
Concept for pure finite-element discretizations (no FV structure).
Definition concepts.hh:50
Concept for finite-volume discretizations.
Definition concepts.hh:26
Concept for hybrid finite-element/finite-volume discretizations.
Definition concepts.hh:39
Concepts for discretization types.
Helper classes to compute the integration elements.
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
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:296
auto quadratureRule(const FVElementGeometry &fvGeometry, const typename FVElementGeometry::SubControlVolume &scv, QuadratureRules::MidpointQuadrature)
Midpoint quadrature for scv.
Definition quadraturerules.hh:159
Definition assembly/assembler.hh:44
std::ranges::range auto scvs(const FVElementGeometry &fvGeometry, const LocalDof &localDof)
Definition localdof.hh:82
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition extrusion.hh:257
A helper to deduce a vector with the same size as numbers of equations.
Point source types and helpers for handling point sources.
Quadrature rules over sub-control volumes and sub-control volume faces.
A arithmetic block vector type based on DUNE's reserved vector.