GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/test/freeflow/navierstokes/errors.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 221 279 79.2%
Functions: 86 209 41.1%
Branches: 360 896 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-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 NavierStokesTests
10 * \copydoc Dumux::NavierStokesTestError
11 */
12 #ifndef DUMUX_TEST_FREEFLOW_NAVIERSTOKES_ERRORS_HH
13 #define DUMUX_TEST_FREEFLOW_NAVIERSTOKES_ERRORS_HH
14
15 #include <vector>
16 #include <cmath>
17 #include <fstream>
18
19 #include <dune/common/fvector.hh>
20 #include <dune/common/indices.hh>
21
22 #include <dumux/discretization/method.hh>
23 #include <dumux/discretization/extrusion.hh>
24 #include <dumux/io/format.hh>
25 #include <dumux/geometry/diameter.hh>
26
27 namespace Dumux {
28
29 /*!
30 * \brief Compute errors between an analytical solution and the numerical approximation
31 */
32 template<class Problem, class Scalar = double>
33
1/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 class NavierStokesErrors
34 {
35 using GridGeometry = std::decay_t<decltype(std::declval<Problem>().gridGeometry())>;
36 using SubControlVolume = typename GridGeometry::SubControlVolume;
37 using Extrusion = Extrusion_t<GridGeometry>;
38 using Indices = typename Problem::Indices;
39 using Element = typename GridGeometry::LocalView::Element;
40 using PrimaryVariables = std::decay_t<decltype(
41 std::declval<Problem>().dirichlet(std::declval<Element>(), std::declval<SubControlVolume>())
42 )>;
43
44 static constexpr int dim = GridGeometry::GridView::dimension;
45
46 public:
47 template<class SolutionVector>
48 6 NavierStokesErrors(std::shared_ptr<const Problem> problem,
49 const SolutionVector& curSol,
50 Scalar time = 0.0)
51
4/10
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 6 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
6 : problem_(problem)
52
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 { calculateErrors_(curSol, time); }
53
54 /*!
55 * \brief Computes errors between an analytical solution and the numerical approximation
56 *
57 * \param curSol The current solution vector
58 * \param time The current time
59 */
60 template<class SolutionVector>
61 void update(const SolutionVector& curSol, Scalar time = 0.0)
62 { calculateErrors_(curSol, time); }
63
64 //! The (absolute) discrete l2 error
65 const PrimaryVariables& l2Absolute() const { return l2Absolute_; }
66 //! The relative discrete l2 error (relative to the discrete l2 norm of the reference solution)
67 const PrimaryVariables& l2Relative() const { return l2Relative_; }
68 //! The (absolute) discrete l-infinity error
69 const PrimaryVariables& lInfAbsolute() const { return lInfAbsolute_; }
70 //! The relative discrete l-infinity error (relative to the discrete loo norm of the reference solution)
71 const PrimaryVariables& lInfRelative() const { return lInfRelative_; }
72
73 //! Time corresponding to the error (returns 0 per default)
74 Scalar time() const { return time_; }
75
76 private:
77 template<class SolutionVector>
78 6 void calculateErrors_(const SolutionVector& curSol, Scalar time)
79 {
80 // store time information
81 6 time_ = time;
82
83 // calculate helping variables
84 6 Scalar totalVolume = 0.0;
85
86 6 PrimaryVariables sumReference(0.0);
87 6 PrimaryVariables sumError(0.0);
88 6 PrimaryVariables maxReference(0.0);
89 6 PrimaryVariables maxError(0.0);
90
91 18 auto fvGeometry = localView(problem_->gridGeometry());
92
1/2
✓ Branch 4 taken 67206 times.
✗ Branch 5 not taken.
134424 for (const auto& element : elements(problem_->gridGeometry().gridView()))
93 {
94 67200 fvGeometry.bindElement(element);
95
96
4/4
✓ Branch 2 taken 67200 times.
✓ Branch 3 taken 67200 times.
✓ Branch 4 taken 67200 times.
✓ Branch 5 taken 67200 times.
201600 for (const auto& scv : scvs(fvGeometry))
97 {
98 67200 totalVolume += Extrusion::volume(fvGeometry, scv);
99
100 // compute the pressure errors
101 67200 const auto analyticalSolutionCellCenter
102
2/2
✓ Branch 3 taken 1826 times.
✓ Branch 4 taken 65374 times.
201600 = problem_->analyticalSolution(scv.dofPosition(), time)[Indices::pressureIdx];
103 67200 const auto numericalSolutionCellCenter
104
6/6
✓ Branch 0 taken 1826 times.
✓ Branch 1 taken 65374 times.
✓ Branch 2 taken 1826 times.
✓ Branch 3 taken 65374 times.
✓ Branch 4 taken 1826 times.
✓ Branch 5 taken 65374 times.
201600 = curSol[GridGeometry::cellCenterIdx()][scv.dofIndex()][Indices::pressureIdx - dim];
105
106 134400 const Scalar pError = absDiff_(analyticalSolutionCellCenter, numericalSolutionCellCenter);
107 134400 const Scalar pReference = absDiff_(analyticalSolutionCellCenter, 0.0);
108
109
4/4
✓ Branch 0 taken 1826 times.
✓ Branch 1 taken 65374 times.
✓ Branch 2 taken 1799 times.
✓ Branch 3 taken 65401 times.
69026 maxError[Indices::pressureIdx] = std::max(maxError[Indices::pressureIdx], pError);
110
4/4
✓ Branch 0 taken 1799 times.
✓ Branch 1 taken 65401 times.
✓ Branch 2 taken 1799 times.
✓ Branch 3 taken 65401 times.
136199 maxReference[Indices::pressureIdx] = std::max(maxReference[Indices::pressureIdx], pReference);
111 134400 sumError[Indices::pressureIdx] += pError * pError * Extrusion::volume(fvGeometry, scv);
112 134400 sumReference[Indices::pressureIdx] += pReference * pReference * Extrusion::volume(fvGeometry, scv);
113
114
4/4
✓ Branch 0 taken 268800 times.
✓ Branch 1 taken 67200 times.
✓ Branch 2 taken 268800 times.
✓ Branch 3 taken 67200 times.
672000 for (const auto& scvf : scvfs(fvGeometry))
115 {
116 // compute the velocity errors
117 268800 const auto velocityIndex = Indices::velocity(scvf.directionIndex());
118
119 268800 const Scalar staggeredHalfVolume = Extrusion::volume(fvGeometry,
120 typename GridGeometry::Traits::FaceSubControlVolume(
121 1612800 0.5*(scv.center() + scvf.center()), 0.5*Extrusion::volume(fvGeometry, scv)
122 )
123 );
124
125
2/2
✓ Branch 3 taken 1512 times.
✓ Branch 4 taken 267288 times.
806400 const auto analyticalSolutionFace = problem_->analyticalSolution(scvf.center(), time)[velocityIndex];
126
6/6
✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 267288 times.
✓ Branch 2 taken 1512 times.
✓ Branch 3 taken 267288 times.
✓ Branch 4 taken 1512 times.
✓ Branch 5 taken 267288 times.
806400 const auto numericalSolutionFace = curSol[GridGeometry::faceIdx()][scvf.dofIndex()][0];
127
128 537600 const Scalar velError = absDiff_(analyticalSolutionFace, numericalSolutionFace);
129 537600 const Scalar velReference = absDiff_(analyticalSolutionFace, 0.0);
130
131
4/4
✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 267288 times.
✓ Branch 2 taken 7701 times.
✓ Branch 3 taken 261099 times.
270312 maxError[velocityIndex] = std::max(maxError[velocityIndex], velError);
132
4/4
✓ Branch 0 taken 7701 times.
✓ Branch 1 taken 261099 times.
✓ Branch 2 taken 7701 times.
✓ Branch 3 taken 261099 times.
545301 maxReference[velocityIndex] = std::max(maxReference[velocityIndex], velReference);
133 268800 sumError[velocityIndex] += velError * velError * staggeredHalfVolume;
134 537600 sumReference[velocityIndex] += velReference * velReference * staggeredHalfVolume;
135 }
136 }
137 }
138
139 // calculate errors
140
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 for (int i = 0; i < PrimaryVariables::size(); ++i)
141 {
142 36 l2Absolute_[i] = std::sqrt(sumError[i] / totalVolume);
143 54 l2Relative_[i] = std::sqrt(sumError[i] / sumReference[i]);
144 36 lInfAbsolute_[i] = maxError[i];
145 72 lInfRelative_[i] = maxError[i] / maxReference[i];
146 }
147 6 }
148
149 template<class T>
150 T absDiff_(const T& a, const T& b) const
151
12/12
✓ Branch 0 taken 1826 times.
✓ Branch 1 taken 65374 times.
✓ Branch 2 taken 1826 times.
✓ Branch 3 taken 65374 times.
✓ Branch 4 taken 1826 times.
✓ Branch 5 taken 65374 times.
✓ Branch 6 taken 1512 times.
✓ Branch 7 taken 267288 times.
✓ Branch 8 taken 1512 times.
✓ Branch 9 taken 267288 times.
✓ Branch 10 taken 1512 times.
✓ Branch 11 taken 267288 times.
1008000 { using std::abs; return abs(a-b); }
152
153 std::shared_ptr<const Problem> problem_;
154
155 PrimaryVariables l2Absolute_;
156 PrimaryVariables l2Relative_;
157 PrimaryVariables lInfAbsolute_;
158 PrimaryVariables lInfRelative_;
159 Scalar time_;
160 };
161
162 template<class Problem, class SolutionVector>
163 NavierStokesErrors(std::shared_ptr<Problem>, SolutionVector&&)
164 -> NavierStokesErrors<Problem>;
165
166 template<class Problem, class SolutionVector, class Scalar>
167 NavierStokesErrors(std::shared_ptr<Problem>, SolutionVector&&, Scalar)
168 -> NavierStokesErrors<Problem, Scalar>;
169
170
171 /*!
172 * \brief An error CSV file writer
173 */
174 template<class Problem, class Scalar = double>
175 class NavierStokesErrorCSVWriter
176 {
177 using GridGeometry = std::decay_t<decltype(std::declval<Problem>().gridGeometry())>;
178 using Indices = typename Problem::Indices;
179
180 static constexpr int dim = GridGeometry::GridView::dimension;
181
182 public:
183 NavierStokesErrorCSVWriter(std::shared_ptr<const Problem> problem, const std::string& suffix = "")
184 : name_(problem->name() + (suffix.empty() ? "_error" : "_error_" + suffix))
185 {
186 const int numCCDofs = problem->gridGeometry().numCellCenterDofs();
187 const int numFaceDofs = problem->gridGeometry().numFaceDofs();
188
189 // print auxiliary file with the number of dofs
190 std::ofstream logFileDofs(name_ + "_dofs.csv", std::ios::trunc);
191 logFileDofs << "cc dofs, face dofs, all dofs\n"
192 << numCCDofs << ", " << numFaceDofs << ", " << numCCDofs + numFaceDofs << "\n";
193
194 // clear error file
195 std::ofstream logFile(name_ + ".csv", std::ios::trunc);
196
197 // write header
198 logFile << "time";
199 for (const std::string e : { "L2Abs", "L2Rel", "LinfAbs", "LinfRel" })
200 printError_(logFile, errorNames_(e), "{:s}");
201 logFile << "\n";
202 }
203
204 void printErrors(const NavierStokesErrors<Problem>& errors) const
205 {
206 // append to error file
207 std::ofstream logFile(name_ + ".csv", std::ios::app);
208
209 logFile << Fmt::format("{:.5e}", errors.time());
210 printError_(logFile, errors.l2Absolute());
211 printError_(logFile, errors.l2Relative());
212 printError_(logFile, errors.lInfAbsolute());
213 printError_(logFile, errors.lInfRelative());
214
215 logFile << "\n";
216 }
217
218 private:
219 template<class Error>
220 void printError_(std::ofstream& logFile, const Error& error, const std::string& format = "{:.5e}") const
221 {
222 logFile << Fmt::vformat(", " + format, Fmt::make_format_args(error[Indices::pressureIdx]));
223 for (int dirIdx = 0; dirIdx < dim; ++dirIdx)
224 logFile << Fmt::vformat(", " + format, Fmt::make_format_args(error[Indices::velocity(dirIdx)]));
225 }
226
227 std::vector<std::string> errorNames_(const std::string& e) const
228 {
229 if constexpr (dim == 1)
230 return { e + "(u)", e + "(p)" };
231 else if constexpr (dim == 2)
232 return { e + "(u)", e + "(v)", e + "(p)" };
233 else
234 return { e + "(u)", e + "(v)", e + "(w)", e + "(p)" };
235 }
236
237 std::string name_;
238 };
239
240 template<class Problem>
241 NavierStokesErrorCSVWriter(std::shared_ptr<Problem>)
242 -> NavierStokesErrorCSVWriter<Problem>;
243
244 template<class Problem>
245 NavierStokesErrorCSVWriter(std::shared_ptr<Problem>, const std::string&)
246 -> NavierStokesErrorCSVWriter<Problem>;
247
248
249 /*!
250 * \brief Append errors to the log file during a convergence test
251 */
252 template<class Problem>
253 void convergenceTestAppendErrors(std::ofstream& logFile,
254 std::shared_ptr<Problem> problem,
255 const NavierStokesErrors<Problem>& errors)
256 {
257 const auto numCCDofs = problem->gridGeometry().numCellCenterDofs();
258 const auto numFaceDofs = problem->gridGeometry().numFaceDofs();
259
260 logFile << Fmt::format(
261 "[ConvergenceTest] numCCDofs = {} numFaceDofs = {}",
262 numCCDofs, numFaceDofs
263 );
264
265 const auto print = [&](const auto& e, const std::string& name){
266 using Indices = typename Problem::Indices;
267 logFile << Fmt::format(
268 " {0}(p) = {1} {0}(vx) = {2} {0}(vy) = {3}",
269 name, e[Indices::pressureIdx], e[Indices::velocityXIdx], e[Indices::velocityYIdx]
270 );
271 };
272
273 print(errors.l2Absolute(), "L2Abs");
274 print(errors.l2Relative(), "L2Rel");
275 print(errors.lInfAbsolute(), "LinfAbs");
276 print(errors.lInfRelative(), "LinfRel");
277
278 logFile << "\n";
279 }
280
281 /*!
282 * \brief Append errors to the log file during a convergence test
283 */
284 template<class Problem>
285 void convergenceTestAppendErrors(std::shared_ptr<Problem> problem,
286 const NavierStokesErrors<Problem>& errors)
287 {
288 const auto logFileName = problem->name() + ".log";
289 std::ofstream logFile(logFileName, std::ios::app);
290 convergenceTestAppendErrors(logFile, problem, errors);
291 }
292
293 namespace NavierStokesTest {
294
295 /*!
296 * \brief Compute errors between an analytical solution and the numerical approximation for momentum eq.
297 */
298 template<class Problem, class Scalar = double>
299
1/5
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
46 class ErrorsSubProblem
300 {
301 static constexpr bool isMomentumProblem = Problem::isMomentumProblem();
302 static constexpr int dim
303 = std::decay_t<decltype(std::declval<Problem>().gridGeometry())>::GridView::dimension;
304
305 using ErrorVector = typename std::conditional_t< isMomentumProblem,
306 Dune::FieldVector<Scalar, dim>,
307 Dune::FieldVector<Scalar, 1> >;
308
309 public:
310 template<class SolutionVector>
311 151 ErrorsSubProblem(std::shared_ptr<const Problem> problem,
312 const SolutionVector& curSol,
313 Scalar time = 0.0)
314
4/10
✓ Branch 2 taken 87 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 87 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 87 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 87 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
151 : problem_(problem)
315
1/2
✓ Branch 1 taken 87 times.
✗ Branch 2 not taken.
151 { calculateErrors_(curSol, time); }
316
317 /*!
318 * \brief Computes errors between an analytical solution and the numerical approximation
319 *
320 * \param curSol The current solution vector
321 * \param time The current time
322 */
323 template<class SolutionVector>
324 void update(const SolutionVector& curSol, Scalar time = 0.0)
325 138 { calculateErrors_(curSol, time); }
326
327 //! The (absolute) discrete l2 error
328 144 const ErrorVector& l2Absolute() const { return l2Absolute_; }
329 //! The relative discrete l2 error (relative to the discrete l2 norm of the reference solution)
330 144 const ErrorVector& l2Relative() const { return l2Relative_; }
331 //! The (absolute) discrete l-infinity error
332 144 const ErrorVector& lInfAbsolute() const { return lInfAbsolute_; }
333 //! The relative discrete l-infinity error (relative to the discrete loo norm of the reference solution)
334 144 const ErrorVector& lInfRelative() const { return lInfRelative_; }
335
336 //! Time corresponding to the error (returns 0 per default)
337 Scalar time() const { return time_; }
338
339 //! Maximum diameter of primal grid elements
340 Scalar hMax() const { return hMax_; }
341
342 //! Volume of domain
343 Scalar totalVolume() const { return totalVolume_; }
344
345 //! Number of scvs that have been considered in error calculation
346 155 Scalar numDofs() const { return numDofs_; }
347
348 private:
349 template<class SolutionVector>
350 427 void calculateErrors_(const SolutionVector& curSol, Scalar time)
351 {
352 // store time information
353 427 time_ = time;
354
355 // calculate helping variables
356 427 totalVolume_ = 0.0;
357 427 hMax_ = 0.0;
358
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
1281 numDofs_ = problem_->gridGeometry().numDofs();
359
360 using GridGeometry = std::decay_t<decltype(std::declval<Problem>().gridGeometry())>;
361 // We do not consider the overlapping Dofs, i.e. elements, in the errors
362 if constexpr (GridGeometry::discMethod == DiscretizationMethods::pq1bubble)
363 20 numDofs_ -= problem_->gridGeometry().gridView().size(0);
364
365
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
427 ErrorVector sumReference(0.0);
366
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
427 ErrorVector sumError(0.0);
367
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
427 ErrorVector maxReference(0.0);
368
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
427 ErrorVector maxError(0.0);
369
370 using namespace Dune::Indices;
371
372
4/10
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 28 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 22 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
1325 auto fvGeometry = localView(problem_->gridGeometry());
373
17/24
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1636369 times.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 28 times.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7100 times.
✓ Branch 11 taken 12 times.
✓ Branch 12 taken 7072 times.
✓ Branch 13 taken 40 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 7072 times.
✓ Branch 16 taken 28 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 42022 times.
✓ Branch 19 taken 28 times.
✓ Branch 20 taken 34950 times.
✓ Branch 21 taken 28 times.
✓ Branch 23 taken 34950 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 34950 times.
✗ Branch 27 not taken.
6662638 for (const auto& element : elements(problem_->gridGeometry().gridView()))
374 {
375
5/5
✓ Branch 1 taken 42022 times.
✓ Branch 2 taken 1045 times.
✓ Branch 3 taken 1635111 times.
✓ Branch 4 taken 135 times.
✓ Branch 5 taken 41887 times.
3296145 hMax_ = std::max(hMax_, diameter(element.geometry()));
376
1/2
✓ Branch 1 taken 42022 times.
✗ Branch 2 not taken.
3295914 fvGeometry.bindElement(element);
377
8/8
✓ Branch 0 taken 303690 times.
✓ Branch 1 taken 3289478 times.
✓ Branch 2 taken 1883702 times.
✓ Branch 3 taken 4077802 times.
✓ Branch 4 taken 1597730 times.
✓ Branch 5 taken 798894 times.
✓ Branch 6 taken 2177 times.
✓ Branch 7 taken 514419 times.
21375874 for (const auto& scv : scvs(fvGeometry))
378 {
379 using Extrusion = Extrusion_t<GridGeometry>;
380
381 // velocity errors
382 if constexpr (isMomentumProblem)
383 {
384 if constexpr (GridGeometry::discMethod == DiscretizationMethods::fcstaggered)
385 {
386
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 189 times.
6432816 totalVolume_ += Extrusion::volume(fvGeometry, scv);
387 // compute the velocity errors
388 using Indices = typename Problem::Indices;
389 6432816 const auto velIdx = Indices::velocity(scv.dofAxis());
390 6432816 const auto analyticalSolution
391
6/8
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 189 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 19323 times.
✓ Branch 4 taken 3203813 times.
✓ Branch 5 taken 189 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
19298448 = problem_->analyticalSolution(scv.dofPosition(), time)[velIdx];
392 6432816 const auto numericalSolution
393
2/2
✓ Branch 0 taken 19137 times.
✓ Branch 1 taken 3203999 times.
6432816 = curSol[scv.dofIndex()][0];
394
395 12865632 const Scalar vError = absDiff_(analyticalSolution, numericalSolution);
396 12865632 const Scalar vReference = absDiff_(analyticalSolution, 0.0);
397
398
4/4
✓ Branch 0 taken 19134 times.
✓ Branch 1 taken 3203810 times.
✓ Branch 2 taken 25080 times.
✓ Branch 3 taken 3197864 times.
6471176 maxError[velIdx] = std::max(maxError[velIdx], vError);
399
4/4
✓ Branch 0 taken 25176 times.
✓ Branch 1 taken 3197960 times.
✓ Branch 2 taken 25080 times.
✓ Branch 3 taken 3197864 times.
12914836 maxReference[velIdx] = std::max(maxReference[velIdx], vReference);
400 12865248 sumError[velIdx] += vError * vError * Extrusion::volume(fvGeometry, scv);
401 19298064 sumReference[velIdx] += vReference * vReference * Extrusion::volume(fvGeometry, scv);
402 }
403 else if constexpr (GridGeometry::discMethod == DiscretizationMethods::fcdiamond
404 || GridGeometry::discMethod == DiscretizationMethods::box)
405 {
406 156674 totalVolume_ += Extrusion::volume(fvGeometry, scv);
407
2/2
✓ Branch 0 taken 274948 times.
✓ Branch 1 taken 137474 times.
470022 for (int dirIdx = 0; dirIdx < dim; ++dirIdx)
408 {
409 313348 const auto analyticalSolution
410
2/2
✓ Branch 3 taken 4438 times.
✓ Branch 4 taken 270510 times.
940044 = problem_->analyticalSolution(scv.dofPosition(), time)[dirIdx];
411 313348 const auto numericalSolution
412
4/4
✓ Branch 0 taken 4438 times.
✓ Branch 1 taken 270510 times.
✓ Branch 2 taken 4438 times.
✓ Branch 3 taken 270510 times.
626696 = curSol[scv.dofIndex()][dirIdx];
413
414 626696 const Scalar vError = absDiff_(analyticalSolution, numericalSolution);
415 626696 const Scalar vReference = absDiff_(analyticalSolution, 0.0);
416
417
4/4
✓ Branch 0 taken 4438 times.
✓ Branch 1 taken 270510 times.
✓ Branch 2 taken 1092 times.
✓ Branch 3 taken 273856 times.
318230 maxError[dirIdx] = std::max(maxError[dirIdx], vError);
418
4/4
✓ Branch 0 taken 1092 times.
✓ Branch 1 taken 273856 times.
✓ Branch 2 taken 1092 times.
✓ Branch 3 taken 273856 times.
627970 maxReference[dirIdx] = std::max(maxReference[dirIdx], vReference);
419 626696 sumError[dirIdx] += vError * vError * Extrusion::volume(fvGeometry, scv);
420 940044 sumReference[dirIdx] += vReference * vReference * Extrusion::volume(fvGeometry, scv);
421 }
422 }
423 else if constexpr (GridGeometry::discMethod == DiscretizationMethods::pq1bubble)
424 {
425
2/2
✓ Branch 0 taken 100000 times.
✓ Branch 1 taken 25800 times.
125800 if(!scv.isOverlapping())
426 {
427 100000 totalVolume_ += Extrusion::volume(fvGeometry, scv);
428
2/2
✓ Branch 0 taken 200000 times.
✓ Branch 1 taken 100000 times.
300000 for (int dirIdx = 0; dirIdx < dim; ++dirIdx)
429 {
430 200000 const auto analyticalSolution
431
2/2
✓ Branch 3 taken 2371 times.
✓ Branch 4 taken 197629 times.
600000 = problem_->analyticalSolution(scv.dofPosition(), time)[dirIdx];
432 200000 const auto numericalSolution
433
4/4
✓ Branch 0 taken 2371 times.
✓ Branch 1 taken 197629 times.
✓ Branch 2 taken 2371 times.
✓ Branch 3 taken 197629 times.
400000 = curSol[scv.dofIndex()][dirIdx];
434
435 400000 const Scalar vError = absDiff_(analyticalSolution, numericalSolution);
436 400000 const Scalar vReference = absDiff_(analyticalSolution, 0.0);
437
438
4/4
✓ Branch 0 taken 2371 times.
✓ Branch 1 taken 197629 times.
✓ Branch 2 taken 191 times.
✓ Branch 3 taken 199809 times.
202371 maxError[dirIdx] = std::max(maxError[dirIdx], vError);
439
4/4
✓ Branch 0 taken 191 times.
✓ Branch 1 taken 199809 times.
✓ Branch 2 taken 191 times.
✓ Branch 3 taken 199809 times.
400191 maxReference[dirIdx] = std::max(maxReference[dirIdx], vReference);
440 400000 sumError[dirIdx] += vError * vError * Extrusion::volume(fvGeometry, scv);
441 600000 sumReference[dirIdx] += vReference * vReference * Extrusion::volume(fvGeometry, scv);
442 }
443 }
444 }
445 else
446 DUNE_THROW(Dune::InvalidStateException,
447 "Unknown momentum discretization scheme in Navier-Stokes error calculation");
448 }
449 // pressure errors
450 else
451 {
452
2/2
✓ Branch 0 taken 2271 times.
✓ Branch 1 taken 540597 times.
1643336 totalVolume_ += Extrusion::volume(fvGeometry, scv);
453 // compute the pressure errors
454 using Indices = typename Problem::Indices;
455 1643336 const auto analyticalSolution
456
6/6
✓ Branch 0 taken 2271 times.
✓ Branch 1 taken 540597 times.
✓ Branch 2 taken 2271 times.
✓ Branch 3 taken 540597 times.
✓ Branch 4 taken 2271 times.
✓ Branch 5 taken 540597 times.
4930008 = problem_->analyticalSolution(scv.dofPosition(), time)[Indices::pressureIdx];
457 1643336 const auto numericalSolution
458
4/6
✓ Branch 0 taken 5625 times.
✓ Branch 1 taken 816043 times.
✓ Branch 2 taken 5607 times.
✓ Branch 3 taken 796861 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3248272 = curSol[scv.dofIndex()][Indices::pressureIdx];
459
460 3286672 const Scalar pError = absDiff_(analyticalSolution, numericalSolution);
461 3286672 const Scalar pReference = absDiff_(analyticalSolution, 0.0);
462
463 3286672 maxError[0] = std::max(maxError[0], pError);
464
2/2
✓ Branch 0 taken 6878 times.
✓ Branch 1 taken 814790 times.
1643336 maxReference[0] = std::max(maxReference[0], pReference);
465 1643336 sumError[0] += pError * pError * Extrusion::volume(fvGeometry, scv);
466 3286672 sumReference[0] += pReference * pReference * Extrusion::volume(fvGeometry, scv);
467 }
468 }
469 }
470
471 // calculate errors
472
2/2
✓ Branch 0 taken 346 times.
✓ Branch 1 taken 225 times.
1073 for (int i = 0; i < ErrorVector::size(); ++i)
473 {
474 1084 l2Absolute_[i] = std::sqrt(sumError[i] / totalVolume_);
475 1522 l2Relative_[i] = std::sqrt(sumError[i] / sumReference[i]);
476 1084 lInfAbsolute_[i] = maxError[i];
477 1960 lInfRelative_[i] = maxError[i] / maxReference[i];
478 }
479 427 }
480
481 template<class T>
482 T absDiff_(const T& a, const T& b) const
483
12/12
✓ Branch 0 taken 12282 times.
✓ Branch 1 taken 1259390 times.
✓ Branch 2 taken 12282 times.
✓ Branch 3 taken 1259390 times.
✓ Branch 4 taken 12282 times.
✓ Branch 5 taken 1259390 times.
✓ Branch 6 taken 19289 times.
✓ Branch 7 taken 3228791 times.
✓ Branch 8 taken 19289 times.
✓ Branch 9 taken 3228791 times.
✓ Branch 10 taken 19289 times.
✓ Branch 11 taken 3228791 times.
13559256 { using std::abs; return abs(a-b); }
484
485 std::shared_ptr<const Problem> problem_;
486
487 ErrorVector l2Absolute_;
488 ErrorVector l2Relative_;
489 ErrorVector lInfAbsolute_;
490 ErrorVector lInfRelative_;
491 Scalar time_;
492 Scalar hMax_;
493 Scalar totalVolume_;
494 std::size_t numDofs_;
495 };
496
497 /*!
498 * \brief Compute errors between an analytical solution and the numerical approximation
499 */
500 template<class MomentumProblem, class MassProblem, class Scalar = double>
501 class Errors
502 {
503 static constexpr int dim
504 = std::decay_t<decltype(std::declval<MomentumProblem>().gridGeometry())>::GridView::dimension;
505
506 using ErrorVector = Dune::FieldVector<Scalar, dim+1>;
507 using NumSubProblemVector = Dune::FieldVector<Scalar, 2>;
508
509 public:
510 template<class SolutionVector>
511 32 Errors(std::shared_ptr<const MomentumProblem> momentumProblem,
512 std::shared_ptr<const MassProblem> massProblem,
513 const SolutionVector& curSol,
514 Scalar time = 0.0)
515 64 : momentumErrors_(momentumProblem, curSol[Dune::Indices::_0], time)
516
11/30
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 32 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 32 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 32 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 32 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 32 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 32 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 32 times.
✗ Branch 28 not taken.
✓ Branch 30 taken 32 times.
✗ Branch 31 not taken.
✓ Branch 33 taken 32 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
352 , massErrors_(massProblem, curSol[Dune::Indices::_1], time)
517
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 { update(curSol, time); }
518
519 /*!
520 * \brief Computes errors between an analytical solution and the numerical approximation
521 *
522 * \param curSol The current solution vector
523 * \param time The current time
524 */
525 template<class SolutionVector>
526 69 void update(const SolutionVector& curSol, Scalar time = 0.0)
527 {
528 138 momentumErrors_.update(curSol[Dune::Indices::_0], time);
529 138 massErrors_.update(curSol[Dune::Indices::_1], time);
530
531 69 time_ = time;
532
533 138 const auto& l2AbsoluteMomentum = momentumErrors_.l2Absolute();
534 138 const auto& l2RelativeMomentum = momentumErrors_.l2Relative();
535 138 const auto& lInfAbsoluteMomentum = momentumErrors_.lInfAbsolute();
536 138 const auto& lInfRelativeMomentum = momentumErrors_.lInfRelative();
537
538 138 const auto& l2AbsoluteMass = massErrors_.l2Absolute();
539 138 const auto& l2RelativeMass = massErrors_.l2Relative();
540 138 const auto& lInfAbsoluteMass = massErrors_.lInfAbsolute();
541 138 const auto& lInfRelativeMass = massErrors_.lInfRelative();
542
543 69 l2Absolute_[0] = l2AbsoluteMass[0];
544 69 l2Relative_[0] = l2RelativeMass[0];
545 69 lInfAbsolute_[0] = lInfAbsoluteMass[0];
546 69 lInfRelative_[0] = lInfRelativeMass[0];
547
548 345 std::copy( l2AbsoluteMomentum.begin(), l2AbsoluteMomentum.end(), l2Absolute_.begin() + 1 );
549 345 std::copy( l2RelativeMomentum.begin(), l2RelativeMomentum.end(), l2Relative_.begin() + 1 );
550 345 std::copy( lInfAbsoluteMomentum.begin(), lInfAbsoluteMomentum.end(), lInfAbsolute_.begin() + 1 );
551 345 std::copy( lInfRelativeMomentum.begin(), lInfRelativeMomentum.end(), lInfRelative_.begin() + 1 );
552
553 138 hMax_[0] = massErrors_.hMax();
554 138 totalVolume_[0] = massErrors_.totalVolume();
555 207 numDofs_[0] = massErrors_.numDofs();
556 138 hMax_[1] = momentumErrors_.hMax();
557 138 totalVolume_[1] = momentumErrors_.totalVolume();
558 207 numDofs_[1] = momentumErrors_.numDofs();
559 69 }
560
561 //! The (absolute) discrete l2 error
562 52 const ErrorVector& l2Absolute() const { return l2Absolute_; }
563 //! The relative discrete l2 error (relative to the discrete l2 norm of the reference solution)
564 52 const ErrorVector& l2Relative() const { return l2Relative_; }
565 //! The (absolute) discrete l-infinity error
566 52 const ErrorVector& lInfAbsolute() const { return lInfAbsolute_; }
567 //! The relative discrete l-infinity error (relative to the discrete loo norm of the reference solution)
568 52 const ErrorVector& lInfRelative() const { return lInfRelative_; }
569
570 //! Volume of scvs considered in error calculation
571 const NumSubProblemVector& totalVolume() const { return totalVolume_; }
572 //! Number of scvs considered in error calculation
573 const NumSubProblemVector& numDofs() const { return numDofs_; }
574 //! Maximum diameter of primal grid elements
575 const NumSubProblemVector& hMax() const { return hMax_; }
576
577 //! Time corresponding to the error (returns 0 per default)
578 Scalar time() const { return time_; }
579
580 private:
581 ErrorsSubProblem<MomentumProblem, Scalar> momentumErrors_;
582 ErrorsSubProblem<MassProblem, Scalar> massErrors_;
583
584 ErrorVector l2Absolute_;
585 ErrorVector l2Relative_;
586 ErrorVector lInfAbsolute_;
587 ErrorVector lInfRelative_;
588
589 NumSubProblemVector hMax_;
590 NumSubProblemVector totalVolume_;
591 NumSubProblemVector numDofs_;
592
593 Scalar time_;
594 };
595
596 template<class Problem, class SolutionVector>
597 ErrorsSubProblem(std::shared_ptr<Problem>, SolutionVector&&)
598 -> ErrorsSubProblem<Problem>;
599
600 template<class Problem, class SolutionVector, class Scalar>
601 ErrorsSubProblem(std::shared_ptr<Problem>, SolutionVector&&, Scalar)
602 -> ErrorsSubProblem<Problem, Scalar>;
603
604 template<class MomentumProblem, class MassProblem, class SolutionVector>
605 Errors(std::shared_ptr<MomentumProblem>, std::shared_ptr<MassProblem>, SolutionVector&&)
606 -> Errors<MomentumProblem, MassProblem>;
607
608 template<class MomentumProblem, class MassProblem, class SolutionVector, class Scalar>
609 Errors(std::shared_ptr<MomentumProblem>, std::shared_ptr<MassProblem>, SolutionVector&&, Scalar)
610 -> Errors<MomentumProblem, MassProblem, Scalar>;
611
612
613 /*!
614 * \brief An error CSV file writer
615 */
616 template<class MomentumProblem, class MassProblem, class Scalar = double>
617
3/10
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
40 class ErrorCSVWriter
618 {
619 static constexpr int dim
620 = std::decay_t<decltype(std::declval<MomentumProblem>().gridGeometry())>::GridView::dimension;
621
622 public:
623 20 ErrorCSVWriter(std::shared_ptr<const MomentumProblem> momentumProblem,
624 std::shared_ptr<const MassProblem> massProblem,
625 const std::string& suffix = "")
626
11/20
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 7 times.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 13 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 7 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 20 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 20 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 20 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 20 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
40 : name_(massProblem->name() + (suffix.empty() ? "_error" : "_error_" + suffix))
627 {
628
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
60 const int numCCDofs = massProblem->gridGeometry().numDofs();
629
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
60 const int numFaceDofs = momentumProblem->gridGeometry().numDofs();
630
631 // print auxiliary file with the number of dofs
632
2/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
40 std::ofstream logFileDofs(name_ + "_dofs.csv", std::ios::trunc);
633 20 logFileDofs << "cc dofs, face dofs, all dofs\n"
634
4/8
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 20 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 20 times.
✗ Branch 13 not taken.
60 << numCCDofs << ", " << numFaceDofs << ", " << numCCDofs + numFaceDofs << "\n";
635
636 // clear error file
637
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
40 std::ofstream logFile(name_ + ".csv", std::ios::trunc);
638
639 // write header
640
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 logFile << "time";
641 using ErrorNames = std::vector<std::string>;
642
4/8
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 20 times.
✓ Branch 3 taken 80 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 80 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
100 for (const std::string e : { "L2Abs", "L2Rel", "LinfAbs", "LinfRel" })
643
16/36
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 80 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 80 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 80 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 80 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 80 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 80 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 80 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 80 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 320 times.
✓ Branch 29 taken 80 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 320 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 80 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 80 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 80 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 80 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
480 printError_(logFile, ErrorNames({ e + "(p)", e + "(u)", e + "(v)", e + "(w)" }), "{:s}");
644
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 logFile << "\n";
645 20 }
646
647 47 void printErrors(const Errors<MomentumProblem, MassProblem>& errors) const
648 {
649 // append to error file
650
1/2
✓ Branch 2 taken 47 times.
✗ Branch 3 not taken.
94 std::ofstream logFile(name_ + ".csv", std::ios::app);
651
652
3/8
✓ Branch 2 taken 47 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 47 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 47 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
47 logFile << Fmt::format("{:.5e}", errors.time());
653
5/12
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 47 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 47 times.
✓ Branch 12 taken 47 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
94 printError_(logFile, errors.l2Absolute());
654
5/12
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 47 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 47 times.
✓ Branch 12 taken 47 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
94 printError_(logFile, errors.l2Relative());
655
5/12
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 47 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 47 times.
✓ Branch 12 taken 47 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
94 printError_(logFile, errors.lInfAbsolute());
656
5/12
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 47 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 47 times.
✓ Branch 12 taken 47 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
94 printError_(logFile, errors.lInfRelative());
657
658
1/2
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
47 logFile << "\n";
659 47 }
660
661 private:
662 template<class Error>
663 536 void printError_(std::ofstream& logFile, const Error& error, const std::string& format = "{:.5e}") const
664 {
665 using MassIndices = typename MassProblem::Indices;
666 using MomIndices = typename MomentumProblem::Indices;
667
14/27
✓ Branch 1 taken 256 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 256 times.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 256 times.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 256 times.
✓ Branch 11 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 256 times.
✓ Branch 14 taken 12 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 268 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 256 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 80 times.
✓ Branch 22 taken 176 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 176 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
1984 logFile << Fmt::vformat(", " + format, Fmt::make_format_args(error[MassIndices::pressureIdx]));
668
2/2
✓ Branch 0 taken 528 times.
✓ Branch 1 taken 268 times.
1592 for (int dirIdx = 0; dirIdx < dim; ++dirIdx)
669
13/27
✓ Branch 1 taken 504 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 504 times.
✓ Branch 5 taken 24 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 504 times.
✓ Branch 8 taken 24 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 504 times.
✓ Branch 11 taken 24 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 504 times.
✓ Branch 14 taken 24 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 528 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 504 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 504 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 504 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
4224 logFile << Fmt::vformat(", " + format, Fmt::make_format_args(error[MomIndices::velocity(dirIdx)+1]));
670 536 }
671
672 std::string name_;
673 };
674
675 template<class MomentumProblem, class MassProblem>
676 ErrorCSVWriter(std::shared_ptr<MomentumProblem>, std::shared_ptr<MassProblem>)
677 -> ErrorCSVWriter<MomentumProblem, MassProblem>;
678
679 template<class MomentumProblem, class MassProblem>
680 ErrorCSVWriter(std::shared_ptr<MomentumProblem>, std::shared_ptr<MassProblem>, const std::string&)
681 -> ErrorCSVWriter<MomentumProblem, MassProblem>;
682
683
684 /*!
685 * \brief Append errors to the log file during a convergence test
686 */
687 template<class MomentumProblem, class MassProblem>
688 5 void convergenceTestAppendErrors(std::ofstream& logFile,
689 std::shared_ptr<MomentumProblem> momentumProblem,
690 std::shared_ptr<MassProblem> massProblem,
691 const Errors<MomentumProblem, MassProblem>& errors)
692 {
693 15 const auto numCCDofs = massProblem->gridGeometry().numDofs();
694 15 const auto numFaceDofs = momentumProblem->gridGeometry().numDofs();
695
696
2/6
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
5 logFile << Fmt::format(
697 "[ConvergenceTest] numCCDofs = {} numFaceDofs = {}",
698 numCCDofs, numFaceDofs
699 );
700
701 45 const auto print = [&](const auto& e, const std::string& name){
702 using MassIndices = typename MassProblem::Indices;
703 using MomIndices = typename MomentumProblem::Indices;
704
2/6
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
100 logFile << Fmt::format(
705 " {0}(p) = {1} {0}(vx) = {2} {0}(vy) = {3}",
706 name, e[MassIndices::pressureIdx], e[MomIndices::velocityXIdx], e[MomIndices::velocityYIdx]
707 );
708 };
709
710
5/12
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
10 print(errors.l2Absolute(), "L2Abs");
711
5/12
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
10 print(errors.l2Relative(), "L2Rel");
712
5/12
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
10 print(errors.lInfAbsolute(), "LinfAbs");
713
4/10
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
10 print(errors.lInfRelative(), "LinfRel");
714
715 5 logFile << "\n";
716 5 }
717
718
719 /*!
720 * \brief Append errors to the log file during a convergence test
721 */
722 template<class MomentumProblem, class MassProblem>
723 5 void convergenceTestAppendErrors(std::shared_ptr<MomentumProblem> momentumProblem,
724 std::shared_ptr<MassProblem> massProblem,
725 const Errors<MomentumProblem, MassProblem>& errors)
726 {
727
0/2
✗ Branch 3 not taken.
✗ Branch 4 not taken.
15 const auto logFileName = massProblem->name() + ".log";
728
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
10 std::ofstream logFile(logFileName, std::ios::app);
729
3/10
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
15 convergenceTestAppendErrors(logFile, momentumProblem, massProblem, errors);
730 5 }
731
732 /*!
733 * \brief Append errors to the log file during a convergence test
734 */
735 template<class MomentumProblem>
736 6 void convergenceTestAppendErrorsMomentum(std::ofstream& logFile,
737 std::shared_ptr<MomentumProblem> problem,
738 const ErrorsSubProblem<MomentumProblem>& errors)
739 {
740 18 const auto numFaceDofs = problem->gridGeometry().numDofs();
741
742
2/6
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
6 logFile << Fmt::format(
743 "[ConvergenceTest] numFaceDofs = {}",
744 numFaceDofs
745 );
746
747 54 const auto print = [&](const auto& e, const std::string& name){
748 using MomIndices = typename MomentumProblem::Indices;
749
2/6
✓ Branch 5 taken 24 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 24 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
96 logFile << Fmt::format(
750 " {0}(vx) = {1} {0}(vy) = {2}",
751 name, e[MomIndices::velocityXIdx], e[MomIndices::velocityYIdx]
752 );
753 };
754
755
5/12
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
12 print(errors.l2Absolute(), "L2Abs");
756
5/12
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
12 print(errors.l2Relative(), "L2Rel");
757
5/12
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
12 print(errors.lInfAbsolute(), "LinfAbs");
758
4/10
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
12 print(errors.lInfRelative(), "LinfRel");
759
760 6 logFile << "\n";
761 6 }
762
763
764 /*!
765 * \brief Append errors to the log file during a convergence test
766 */
767 template<class MomentumProblem>
768 6 void convergenceTestAppendErrorsMomentum(std::shared_ptr<MomentumProblem> problem,
769 const ErrorsSubProblem<MomentumProblem>& errors)
770 {
771
0/2
✗ Branch 3 not taken.
✗ Branch 4 not taken.
18 const auto logFileName = problem->name() + ".log";
772
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
12 std::ofstream logFile(logFileName, std::ios::app);
773
2/6
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
12 convergenceTestAppendErrorsMomentum(logFile, problem, errors);
774 6 }
775
776 } // end namespace NavierStokesTest
777
778 } // end namespace Dumux
779
780 #endif
781