3.1-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
resultevaluation.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*****************************************************************************/
19
20#ifndef DUMUX_BENCHMARKRESULT_HH
21#define DUMUX_BENCHMARKRESULT_HH
22
31
32namespace Dumux
33{
38{
39public:
41 double ergrad;
42 double ervell2;
43 double uMin;
44 double uMax;
45 double flux0;
46 double flux1;
47 double fluy0;
48 double fluy1;
49 double sumf;
50 double sumflux;
51 double exactflux0;
52 double exactflux1;
53 double exactfluy0;
54 double exactfluy1;
55 double errflx0;
56 double errflx1;
57 double errfly0;
58 double errfly1;
59 double erflm;
60 double ener1;
61
70 template<class GridView, class Problem>
71 void evaluate(const GridView& gridView,
72 Problem& problem, bool consecutiveNumbering = false)
73 {
74 using Grid = typename GridView::Grid;
75 using Scalar = typename Grid::ctype;
76 enum {dim=Grid::dimension};
77 using Element = typename Grid::template Codim<0>::Entity;
78 using Geometry = typename Element::Geometry;
79 using JacobianInverseTransposed = typename Geometry::JacobianInverseTransposed;
80
81 uMin = 1e100;
82 uMax = -1e100;
83 flux0 = 0;
84 flux1 = 0;
85 fluy0 = 0;
86 fluy1 = 0;
87 sumf = 0;
88 sumflux = 0;
89 exactflux0 = 0;
90 exactflux1 = 0;
91 exactfluy0 = 0;
92 exactfluy1 = 0;
93 erflm = 0;
94 ener1 = 0;
95 Scalar numerator = 0;
96 Scalar denominator = 0;
97 double numeratorGrad = 0;
98 double denominatorGrad = 0;
99 double numeratorFlux = 0;
100 double denominatorFlux = 0;
101 for (const auto& element : elements(gridView))
102 {
103 // element geometry
104 const Geometry& geometry = element.geometry();
105 Dune::GeometryType geomType = geometry.type();
106 using ReferenceElements = Dune::ReferenceElements<Scalar, dim>;
107 const Dune::FieldVector<Scalar,dim>& local = ReferenceElements::general(geomType).position(0, 0);
108 Dune::FieldVector<Scalar,dim> globalPos = geometry.global(local);
109
110 Scalar volume = geometry.volume();
111
112 int elemIdx = problem.variables().index(element);
113
114 Scalar approxPressure = problem.variables().cellData(elemIdx).globalPressure();
115 Scalar exactPressure = problem.exact(globalPos);
116
117 numerator += volume*(approxPressure - exactPressure)*(approxPressure - exactPressure);
118 denominator += volume*exactPressure*exactPressure;
119
120 // update uMin and uMax
121 using std::min;
122 using std::max;
123 uMin = min(uMin, approxPressure);
124 uMax = max(uMax, approxPressure);
125
126 typename Problem::PrimaryVariables sourceVec;
127 problem.source(sourceVec, element);
128 sumf += volume*sourceVec[0];
129
130 // get the absolute permeability
131 Dune::FieldMatrix<double,dim,dim> K = problem.spatialParams().intrinsicPermeability(element);
132
133 int isIdx = -1;
134 Dune::FieldVector<Scalar,2*dim> fluxVector;
135 Dune::FieldVector<Scalar,dim> exactGradient;
136 for (const auto& intersection : intersections(gridView, element))
137 {
138 // local number of facet
139 int fIdx = intersection.indexInInside();
140
141 if (consecutiveNumbering)
142 isIdx++;
143 else
144 isIdx = fIdx;
145
146 Dune::FieldVector<double,dim> faceGlobal = intersection.geometry().center();
147 double faceVol = intersection.geometry().volume();
148
149 // get normal vector
150 Dune::FieldVector<double,dim> unitOuterNormal = intersection.centerUnitOuterNormal();
151
152 // get the exact gradient
153 exactGradient = problem.exactGrad(faceGlobal);
154
155 // get the negative exact velocity
156 Dune::FieldVector<double,dim> KGrad(0);
157 K.umv(exactGradient, KGrad);
158
159 // calculate the exact normal velocity
160 double exactFlux = KGrad*unitOuterNormal;
161
162 // get the approximate normalvelocity
163 double approximateFlux = problem.variables().cellData(elemIdx).fluxData().velocityTotal(isIdx)*unitOuterNormal;
164
165 // calculate the difference in the normal velocity
166 double fluxDiff = exactFlux + approximateFlux;
167
168 // update mean value error
169 using std::abs;
170 erflm = max(erflm, abs(fluxDiff));
171
172 numeratorFlux += volume*fluxDiff*fluxDiff;
173 denominatorFlux += volume*exactFlux*exactFlux;
174
175 // calculate the fluxes through the element faces
176 exactFlux *= faceVol;
177 approximateFlux *= faceVol;
178 fluxVector[fIdx] = approximateFlux;
179
180 if (!intersection.neighbor()) {
181 if (abs(faceGlobal[1]) < 1e-6) {
182 fluy0 += approximateFlux;
183 exactfluy0 += exactFlux;
184 }
185 else if (abs(faceGlobal[1] - 1.0) < 1e-6) {
186 fluy1 += approximateFlux;
187 exactfluy1 += exactFlux;
188 }
189 else if (faceGlobal[0] < 1e-6) {
190 flux0 += approximateFlux;
191 exactflux0 += exactFlux;
192 }
193 else if (abs(faceGlobal[0] - 1.0) < 1e-6) {
194 flux1 += approximateFlux;
195 exactflux1 += exactFlux;
196 }
197 }
198 }
199
200 // calculate velocity on reference element as the Raviart-Thomas-0
201 // interpolant of the fluxes
202 Dune::FieldVector<Scalar, dim> refVelocity;
203 // simplices
204 if (geometry.type().isSimplex()) {
205 for (int dimIdx = 0; dimIdx < dim; dimIdx++)
206 {
207 refVelocity[dimIdx] = -fluxVector[dim - 1 - dimIdx];
208 for (int fIdx = 0; fIdx < dim + 1; fIdx++)
209 {
210 refVelocity[dimIdx] += fluxVector[fIdx]/(dim + 1);
211 }
212 }
213 }
214 // cubes
215 else if (geometry.type().isCube()){
216 for (int i = 0; i < dim; i++)
217 refVelocity[i] = 0.5 * (fluxVector[2*i + 1] - fluxVector[2*i]);
218 }
219 // 3D prism and pyramids
220 else {
221 DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
222 }
223
224 // get the transposed Jacobian of the element mapping
225 const JacobianInverseTransposed& jacobianInv = geometry.jacobianInverseTransposed(local);
226 JacobianInverseTransposed jacobianT(jacobianInv);
227 jacobianT.invert();
228
229 // calculate the element velocity by the Piola transformation
230 Dune::FieldVector<Scalar,dim> elementVelocity(0);
231 jacobianT.umtv(refVelocity, elementVelocity);
232 elementVelocity /= geometry.integrationElement(local);
233
234 // get the approximate gradient
235 Dune::FieldVector<Scalar,dim> approximateGradient;
236 K.solve(approximateGradient, elementVelocity);
237
238 // get the exact gradient
239 exactGradient = problem.exactGrad(globalPos);
240
241 // the difference between exact and approximate gradient
242 Dune::FieldVector<Scalar,dim> gradDiff(exactGradient);
243 gradDiff += approximateGradient;
244
245 // add to energy
246 ener1 += volume*(approximateGradient*elementVelocity);
247
248 numeratorGrad += volume*(gradDiff*gradDiff);
249 denominatorGrad += volume*(exactGradient*exactGradient);
250 }
251
252 using std::sqrt;
253 using std::abs;
254 relativeL2Error = sqrt(numerator/denominator);
255 ergrad = sqrt(numeratorGrad/denominatorGrad);
256 ervell2 = sqrt(numeratorFlux/denominatorFlux);
257 sumflux = flux0 + flux1 + fluy0 + fluy1 - sumf;
262 }
263};
264
265
266
267}
268
269#endif
Base class for definition of an sequential diffusion (pressure) or transport problem.
Dune::IteratorRange< typename MultiDomainGlue< DomainGridView, TargetGridView, DomainMapper, TargetMapper >::Intersections::const_iterator > intersections(const MultiDomainGlue< DomainGridView, TargetGridView, DomainMapper, TargetMapper > &glue)
Range generator to iterate with range-based for loops over all intersections as follows: for (const a...
Definition: glue.hh:62
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
Calculate errors for the diffusion test problem.
Definition: resultevaluation.hh:38
double ener1
Definition: resultevaluation.hh:60
double relativeL2Error
Definition: resultevaluation.hh:40
double fluy0
Definition: resultevaluation.hh:47
double uMin
Definition: resultevaluation.hh:43
double exactflux1
Definition: resultevaluation.hh:52
double errfly0
Definition: resultevaluation.hh:57
double ervell2
Definition: resultevaluation.hh:42
double sumf
Definition: resultevaluation.hh:49
void evaluate(const GridView &gridView, Problem &problem, bool consecutiveNumbering=false)
Calculate errors for the diffusion test problem.
Definition: resultevaluation.hh:71
double flux0
Definition: resultevaluation.hh:45
double erflm
Definition: resultevaluation.hh:59
double fluy1
Definition: resultevaluation.hh:48
double ergrad
Definition: resultevaluation.hh:41
double errfly1
Definition: resultevaluation.hh:58
double errflx0
Definition: resultevaluation.hh:55
double exactflux0
Definition: resultevaluation.hh:51
double sumflux
Definition: resultevaluation.hh:50
double errflx1
Definition: resultevaluation.hh:56
double exactfluy1
Definition: resultevaluation.hh:54
double uMax
Definition: resultevaluation.hh:44
double flux1
Definition: resultevaluation.hh:46
double exactfluy0
Definition: resultevaluation.hh:53