GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/assembly/staggeredlocalresidual.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 77 79 97.5%
Functions: 323 380 85.0%
Branches: 20 24 83.3%

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-FileCopyrightInfo: 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 Assembly
10 * \ingroup StaggeredDiscretization
11 * \brief Calculates the element-wise residual for the staggered FV scheme
12 */
13 #ifndef DUMUX_STAGGERED_LOCAL_RESIDUAL_HH
14 #define DUMUX_STAGGERED_LOCAL_RESIDUAL_HH
15
16 #include <dumux/common/timeloop.hh>
17 #include <dumux/common/properties.hh>
18 #include <dumux/discretization/extrusion.hh>
19
20 namespace Dumux {
21
22 /*!
23 * \ingroup Assembly
24 * \ingroup StaggeredDiscretization
25 * \brief Calculates the element-wise residual for the staggered FV scheme
26 */
27 template<class TypeTag>
28 class StaggeredLocalResidual
29 {
30 using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView;
31
32 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
33 using Implementation = GetPropType<TypeTag, Properties::LocalResidual>;
34 using Problem = GetPropType<TypeTag, Properties::Problem>;
35 using Element = typename GridView::template Codim<0>::Entity;
36 using ElementBoundaryTypes = GetPropType<TypeTag, Properties::ElementBoundaryTypes>;
37 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
38 using ElementFluxVariablesCache = typename GetPropType<TypeTag, Properties::GridFluxVariablesCache>::LocalView;
39 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
40 using FVElementGeometry = typename GridGeometry::LocalView;
41 using SubControlVolume = typename GridGeometry::SubControlVolume;
42 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
43 using FaceSubControlVolume = typename GridGeometry::Traits::FaceSubControlVolume;
44 using Extrusion = Extrusion_t<GridGeometry>;
45 using CellCenterPrimaryVariables = GetPropType<TypeTag, Properties::CellCenterPrimaryVariables>;
46
47 using CellCenterResidual = GetPropType<TypeTag, Properties::CellCenterPrimaryVariables>;
48 using FaceResidual = GetPropType<TypeTag, Properties::FacePrimaryVariables>;
49 using ElementFaceVariables = typename GetPropType<TypeTag, Properties::GridFaceVariables>::LocalView;
50
51 using TimeLoop = TimeLoopBase<Scalar>;
52
53 public:
54 using CellCenterResidualValue = GetPropType<TypeTag, Properties::CellCenterPrimaryVariables>;
55 using FaceResidualValue = GetPropType<TypeTag, Properties::FacePrimaryVariables>;
56 using ElementResidualVector = CellCenterResidualValue;
57
58 //! the constructor
59 2628 StaggeredLocalResidual(const Problem* problem,
60 const TimeLoop* timeLoop = nullptr)
61 : problem_(problem)
62
2/2
✓ Branch 0 taken 2578 times.
✓ Branch 1 taken 50 times.
2628 , timeLoop_(timeLoop)
63 {}
64
65 //! Convenience function to evaluate the flux and source terms for the cell center residual
66 41373356 CellCenterResidualValue evalFluxAndSourceForCellCenter(const Element& element,
67 const FVElementGeometry& fvGeometry,
68 const ElementVolumeVariables& elemVolVars,
69 const ElementFaceVariables& elemFaceVars,
70 const ElementBoundaryTypes& bcTypes,
71 const ElementFluxVariablesCache& elemFluxVarsCache) const
72 {
73 41373356 CellCenterResidualValue residual(0.0);
74
75 // evaluate the source term
76
4/4
✓ Branch 0 taken 41373356 times.
✓ Branch 1 taken 41373356 times.
✓ Branch 2 taken 41373356 times.
✓ Branch 3 taken 41373356 times.
124120068 for (auto&& scv : scvs(fvGeometry))
77 41373356 asImp().evalSourceForCellCenter(residual, this->problem(), element, fvGeometry, elemVolVars, elemFaceVars, scv);
78
79 // evaluate the flux term
80
4/4
✓ Branch 0 taken 165493424 times.
✓ Branch 1 taken 41373356 times.
✓ Branch 2 taken 165493424 times.
✓ Branch 3 taken 41373356 times.
248240136 for (auto&& scvf : scvfs(fvGeometry))
81 165493424 asImp().evalFluxForCellCenter(residual, this->problem(), element, fvGeometry, elemVolVars, elemFaceVars, bcTypes, elemFluxVarsCache, scvf);
82
83 41373356 return residual;
84 }
85
86 //! Evaluate the flux terms for a cell center residual
87 165493424 void evalFluxForCellCenter(CellCenterResidualValue& residual,
88 const Problem& problem,
89 const Element& element,
90 const FVElementGeometry& fvGeometry,
91 const ElementVolumeVariables& elemVolVars,
92 const ElementFaceVariables& elemFaceVars,
93 const ElementBoundaryTypes& elemBcTypes,
94 const ElementFluxVariablesCache& elemFluxVarsCache,
95 const SubControlVolumeFace& scvf) const
96 {
97
2/2
✓ Branch 0 taken 156137274 times.
✓ Branch 1 taken 9356150 times.
165493424 if (!scvf.boundary())
98 297551780 residual += asImp_().computeFluxForCellCenter(problem, element, fvGeometry, elemVolVars, elemFaceVars, scvf, elemFluxVarsCache);
99 else
100 18424796 residual += asImp_().computeBoundaryFluxForCellCenter(problem, element, fvGeometry, scvf, elemVolVars, elemFaceVars, elemBcTypes, elemFluxVarsCache);
101 165493424 }
102
103 //! Evaluate the source terms for a cell center residual
104 37620788 void evalSourceForCellCenter(CellCenterResidualValue& residual,
105 const Problem& problem,
106 const Element& element,
107 const FVElementGeometry& fvGeometry,
108 const ElementVolumeVariables& curElemVolVars,
109 const ElementFaceVariables& curElemFaceVars,
110 const SubControlVolume& scv) const
111 {
112 37620788 const auto curExtrusionFactor = curElemVolVars[scv].extrusionFactor();
113
114 // subtract the source term from the local rate
115
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
37620788 auto source = asImp_().computeSourceForCellCenter(problem, element, fvGeometry, curElemVolVars, curElemFaceVars, scv);
116 75241576 source *= Extrusion::volume(fvGeometry, scv)*curExtrusionFactor;
117 37620788 residual -= source;
118 37620788 }
119
120 //! Evaluate the storage terms for a cell center residual
121 38399336 CellCenterResidualValue evalStorageForCellCenter(const Element &element,
122 const FVElementGeometry& fvGeometry,
123 const ElementVolumeVariables& prevElemVolVars,
124 const ElementVolumeVariables& curElemVolVars) const
125 {
126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38399336 times.
38399336 assert(timeLoop_ && "no time loop set for storage term evaluation");
127 38399336 CellCenterResidualValue storage(0.0);
128
129
4/4
✓ Branch 0 taken 38399336 times.
✓ Branch 1 taken 38399336 times.
✓ Branch 2 taken 38399336 times.
✓ Branch 3 taken 38399336 times.
115198008 for (auto&& scv : scvs(fvGeometry))
130 38399336 asImp().evalStorageForCellCenter(storage, problem(), element, fvGeometry, prevElemVolVars, curElemVolVars, scv);
131
132 38399336 return storage;
133 }
134
135 //! Evaluate the storage terms for a cell center residual
136 38399336 void evalStorageForCellCenter(CellCenterResidualValue& residual,
137 const Problem& problem,
138 const Element &element,
139 const FVElementGeometry& fvGeometry,
140 const ElementVolumeVariables& prevElemVolVars,
141 const ElementVolumeVariables& curElemVolVars,
142 const SubControlVolume& scv) const
143 {
144 38399336 CellCenterResidualValue storage(0.0);
145 38399336 const auto& curVolVars = curElemVolVars[scv];
146 38399336 const auto& prevVolVars = prevElemVolVars[scv];
147
148 // mass balance within the element. this is the
149 // \f$\frac{m}{\partial t}\f$ term if using implicit
150 // euler as time discretization.
151
152 // We might need a more explicit way for
153 // doing the time discretization...
154 38399336 auto prevCCStorage = asImp_().computeStorageForCellCenter(problem, scv, prevVolVars);
155 38399336 auto curCCStorage = asImp_().computeStorageForCellCenter(problem, scv, curVolVars);
156
157 38399336 prevCCStorage *= prevVolVars.extrusionFactor();
158 38399336 curCCStorage *= curVolVars.extrusionFactor();
159
160 38399336 storage = std::move(curCCStorage);
161 38399336 storage -= std::move(prevCCStorage);
162 76798672 storage *= Extrusion::volume(fvGeometry, scv);
163 38399336 storage /= timeLoop_->timeStepSize();
164
165 38399336 residual += storage;
166 38399336 }
167
168 //! for compatibility with FVLocalAssemblerBase
169 template<class... Args>
170 CellCenterResidualValue evalFluxAndSource(Args&&... args) const
171 {
172 return CellCenterResidualValue(0.0);
173 }
174
175 //! for compatibility with FVLocalAssemblerBase
176 template<class... Args>
177 CellCenterResidualValue evalStorage(Args&&... args) const
178 {
179 return CellCenterResidualValue(0.0);
180 }
181
182 /*!
183 * \name User interface
184 * \note The following methods are usually expensive to evaluate
185 * They are useful for outputting residual information.
186 */
187 // \{
188
189 //! Convenience function to evaluate the flux and source terms for the face residual
190 150537748 FaceResidualValue evalFluxAndSourceForFace(const Element& element,
191 const FVElementGeometry& fvGeometry,
192 const ElementVolumeVariables& elemVolVars,
193 const ElementFaceVariables& elemFaceVars,
194 const ElementBoundaryTypes& bcTypes,
195 const ElementFluxVariablesCache& elemFluxVarsCache,
196 const SubControlVolumeFace& scvf) const
197 {
198 150537748 FaceResidualValue residual(0.0);
199 150537748 asImp().evalSourceForFace(residual, this->problem(), element, fvGeometry, elemVolVars, elemFaceVars, scvf);
200 150537748 asImp().evalFluxForFace(residual, this->problem(), element, fvGeometry, elemVolVars, elemFaceVars, bcTypes, elemFluxVarsCache, scvf);
201
202 150537748 return residual;
203 }
204
205 //! Evaluate the flux terms for a face residual
206 150537748 void evalFluxForFace(FaceResidualValue& residual,
207 const Problem& problem,
208 const Element& element,
209 const FVElementGeometry& fvGeometry,
210 const ElementVolumeVariables& elemVolVars,
211 const ElementFaceVariables& elemFaceVars,
212 const ElementBoundaryTypes& elemBcTypes,
213 const ElementFluxVariablesCache& elemFluxVarsCache,
214 const SubControlVolumeFace& scvf) const
215 {
216
2/2
✓ Branch 0 taken 141926782 times.
✓ Branch 1 taken 8610966 times.
150537748 if (!scvf.boundary())
217 141926782 residual += asImp_().computeFluxForFace(problem, element, scvf, fvGeometry, elemVolVars, elemFaceVars, elemFluxVarsCache);
218 else
219 8610966 residual += asImp_().computeBoundaryFluxForFace(problem, element, fvGeometry, scvf, elemVolVars, elemFaceVars, elemBcTypes, elemFluxVarsCache);
220 150537748 }
221
222 //! Evaluate the source terms for a face residual
223 150537748 void evalSourceForFace(FaceResidualValue& residual,
224 const Problem& problem,
225 const Element& element,
226 const FVElementGeometry& fvGeometry,
227 const ElementVolumeVariables& elemVolVars,
228 const ElementFaceVariables& elemFaceVars,
229 const SubControlVolumeFace& scvf) const
230 {
231 // the source term:
232 150537748 auto source = asImp_().computeSourceForFace(problem, element, fvGeometry, scvf, elemVolVars, elemFaceVars);
233 301075496 const auto& scv = fvGeometry.scv(scvf.insideScvIdx());
234 150537748 const auto extrusionFactor = elemVolVars[scv].extrusionFactor();
235
236 // construct staggered scv (half of the element)
237 602150992 auto faceScvCenter = scvf.center() + scv.center();
238 301075496 faceScvCenter *= 0.5;
239 301075496 FaceSubControlVolume faceScv(faceScvCenter, 0.5*scv.volume());
240
241 301075496 source *= Extrusion::volume(fvGeometry, faceScv)*extrusionFactor;
242 150537748 residual -= source;
243 150537748 }
244
245 //! Evaluate the storage terms for a face residual
246 135806428 FaceResidualValue evalStorageForFace(const Element& element,
247 const FVElementGeometry& fvGeometry,
248 const ElementVolumeVariables& prevElemVolVars,
249 const ElementVolumeVariables& curElemVolVars,
250 const ElementFaceVariables& prevElemFaceVars,
251 const ElementFaceVariables& curElemFaceVars,
252 const SubControlVolumeFace& scvf) const
253 {
254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 135806428 times.
135806428 assert(timeLoop_ && "no time loop set for storage term evaluation");
255 135806428 FaceResidualValue storage(0.0);
256 135806428 asImp().evalStorageForFace(storage, problem(), element, fvGeometry, prevElemVolVars, curElemVolVars, prevElemFaceVars, curElemFaceVars, scvf);
257 135806428 return storage;
258 }
259
260 //! Evaluate the storage terms for a face residual
261 135806428 void evalStorageForFace(FaceResidualValue& residual,
262 const Problem& problem,
263 const Element& element,
264 const FVElementGeometry& fvGeometry,
265 const ElementVolumeVariables& prevElemVolVars,
266 const ElementVolumeVariables& curElemVolVars,
267 const ElementFaceVariables& prevElemFaceVars,
268 const ElementFaceVariables& curElemFaceVars,
269 const SubControlVolumeFace& scvf) const
270 {
271 271612856 const auto& scv = fvGeometry.scv(scvf.insideScvIdx());
272
273 135806428 auto storage = asImp_().computeStorageForFace(problem, scvf, curElemVolVars[scv], curElemFaceVars);
274 135806428 storage -= asImp_().computeStorageForFace(problem, scvf, prevElemVolVars[scv], prevElemFaceVars);
275
276 135806428 const auto extrusionFactor = curElemVolVars[scv].extrusionFactor();
277
278 // construct staggered scv (half of the element)
279 407419284 auto faceScvCenter = scvf.center() + scv.center();
280 135806428 faceScvCenter *= 0.5;
281 135806428 FaceSubControlVolume faceScv(faceScvCenter, 0.5*scv.volume());
282
283 271612856 storage *= Extrusion::volume(fvGeometry, faceScv)*extrusionFactor;
284 135806428 storage /= timeLoop_->timeStepSize();
285
286 135806428 residual += storage;
287 135806428 }
288
289 //! If no solution has been set, we treat the problem as stationary.
290 bool isStationary() const
291 { return !timeLoop_; }
292
293 //! the problem
294 const Problem& problem() const
295 { return *problem_; }
296
297 protected:
298
299 Implementation &asImp_()
300 { return *static_cast<Implementation*>(this); }
301
302 const Implementation &asImp_() const
303 { return *static_cast<const Implementation*>(this); }
304
305
306 TimeLoop& timeLoop()
307 { return *timeLoop_; }
308
309 const TimeLoop& timeLoop() const
310 { return *timeLoop_; }
311
312 Implementation &asImp()
313 { return *static_cast<Implementation*>(this); }
314
315 const Implementation &asImp() const
316 { return *static_cast<const Implementation*>(this); }
317
318 private:
319 const Problem* problem_; //!< the problem we are assembling this residual for
320 const TimeLoop* timeLoop_;
321
322 };
323
324 } // end namespace Dumux
325
326 #endif
327