3.1-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
l2error.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_TEST_L2_ERROR_HH
25#define DUMUX_TEST_L2_ERROR_HH
26
27#include <vector>
28#include <cmath>
29
30namespace Dumux {
31
36template<class Scalar, class ModelTraits, class PrimaryVariables>
38{
39 using Indices = typename ModelTraits::Indices;
40
41public:
42
49 template<class Problem, class SolutionVector>
50 static auto calculateL2Error(const Problem& problem, const SolutionVector& curSol)
51 {
52 using GridGeometry = std::decay_t<decltype(problem.gridGeometry())>;
53 PrimaryVariables sumError(0.0), sumReference(0.0), l2NormAbs(0.0), l2NormRel(0.0);
54
55 const int numFaceDofs = problem.gridGeometry().numFaceDofs();
56
57 std::vector<Scalar> staggeredVolume(numFaceDofs);
58 std::vector<Scalar> errorVelocity(numFaceDofs);
59 std::vector<Scalar> velocityReference(numFaceDofs);
60 std::vector<int> directionIndex(numFaceDofs);
61
62 Scalar totalVolume = 0.0;
63
64 for (const auto& element : elements(problem.gridGeometry().gridView()))
65 {
66 auto fvGeometry = localView(problem.gridGeometry());
67 fvGeometry.bindElement(element);
68
69 for (auto&& scv : scvs(fvGeometry))
70 {
71 // treat cell-center dofs
72 const auto dofIdxCellCenter = scv.dofIndex();
73 const auto& posCellCenter = scv.dofPosition();
74 const auto analyticalSolutionCellCenter = problem.dirichletAtPos(posCellCenter)[Indices::pressureIdx];
75 const auto numericalSolutionCellCenter = curSol[GridGeometry::cellCenterIdx()][dofIdxCellCenter][Indices::pressureIdx - ModelTraits::dim()];
76 sumError[Indices::pressureIdx] += squaredDiff_(analyticalSolutionCellCenter, numericalSolutionCellCenter) * scv.volume();
77 sumReference[Indices::pressureIdx] += analyticalSolutionCellCenter * analyticalSolutionCellCenter * scv.volume();
78 totalVolume += scv.volume();
79
80 // treat face dofs
81 for (auto&& scvf : scvfs(fvGeometry))
82 {
83 const int dofIdxFace = scvf.dofIndex();
84 const int dirIdx = scvf.directionIndex();
85 const auto analyticalSolutionFace = problem.dirichletAtPos(scvf.center())[Indices::velocity(dirIdx)];
86 const auto numericalSolutionFace = curSol[GridGeometry::faceIdx()][dofIdxFace][0];
87 directionIndex[dofIdxFace] = dirIdx;
88 errorVelocity[dofIdxFace] = squaredDiff_(analyticalSolutionFace, numericalSolutionFace);
89 velocityReference[dofIdxFace] = squaredDiff_(analyticalSolutionFace, 0.0);
90 const Scalar staggeredHalfVolume = 0.5 * scv.volume();
91 staggeredVolume[dofIdxFace] = staggeredVolume[dofIdxFace] + staggeredHalfVolume;
92 }
93 }
94 }
95
96 // get the absolute and relative discrete L2-error for cell-center dofs
97 l2NormAbs[Indices::pressureIdx] = std::sqrt(sumError[Indices::pressureIdx] / totalVolume);
98 l2NormRel[Indices::pressureIdx] = std::sqrt(sumError[Indices::pressureIdx] / sumReference[Indices::pressureIdx]);
99
100 // get the absolute and relative discrete L2-error for face dofs
101 for(int i = 0; i < numFaceDofs; ++i)
102 {
103 const int dirIdx = directionIndex[i];
104 const auto error = errorVelocity[i];
105 const auto ref = velocityReference[i];
106 const auto volume = staggeredVolume[i];
107 sumError[Indices::velocity(dirIdx)] += error * volume;
108 sumReference[Indices::velocity(dirIdx)] += ref * volume;
109 }
110
111 for(int dirIdx = 0; dirIdx < ModelTraits::dim(); ++dirIdx)
112 {
113 l2NormAbs[Indices::velocity(dirIdx)] = std::sqrt(sumError[Indices::velocity(dirIdx)] / totalVolume);
114 l2NormRel[Indices::velocity(dirIdx)] = std::sqrt(sumError[Indices::velocity(dirIdx)] / sumReference[Indices::velocity(dirIdx)]);
115 }
116 return std::make_pair(l2NormAbs, l2NormRel);
117 }
118
119private:
120
121 template<class T>
122 static T squaredDiff_(const T& a, const T& b)
123 {
124 return (a-b)*(a-b);
125 }
126
127};
128} // end namespace Dumux
129
130#endif
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
static unsigned int directionIndex(Vector &&vector)
Returns the dirction index of the facet (0 = x, 1 = y, 2 = z)
Definition: staggeredgeometryhelper.hh:114
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
Property tag Indices
Definition: porousmediumflow/sequential/properties.hh:59
Routines to calculate the discrete L2 error.
Definition: l2error.hh:38
static auto calculateL2Error(const Problem &problem, const SolutionVector &curSol)
Calculates the L2 error between the analytical solution and the numerical approximation.
Definition: l2error.hh:50