82 void evaluate(
const Grid& grid, ProblemType& problem,
83 SolutionType& solution,
bool pureNeumann =
false)
85 using Entity =
typename Grid::Traits::template Codim<0>::Entity;
86 using Geometry =
typename Entity::Geometry;
87 using GV =
typename Grid::LevelGridView;
88 using IS =
typename GV::IndexSet;
89 using Mapper = Dune::MultipleCodimMultipleGeomTypeMapper<GV>;
90 using ct =
typename Grid::ctype;
92 enum{dim = Grid::dimension};
94 using JacobianInverseTransposed =
typename Geometry::JacobianInverseTransposed;
95 using ReferenceElements = Dune::ReferenceElements<ct, dim>;
96 const GV& gridview(grid.levelGridView(grid.maxLevel()));
97 const IS& indexset(gridview.indexSet());
98 Mapper elementMapper(gridview, Dune::mcmgElementLayout());
99 Mapper faceMapper(gridview, Dune::mcmgLayout(Dune::Codim<1>()));
100 SolutionType& exactSol(grid.levelGridView(grid.maxLevel()));
103 double domainVolume = 0;
104 for (
const auto& element : elements(gridview))
107 double volume = element.geometry().volume();
110 int indexi = elementMapper.index(element);
113 uMean += volume*(problem.variables().cellData(indexi).globalPressure());
116 domainVolume += volume;
118 uMean /= domainVolume;
121 for (
int i = 0; i < (int) problem.variables().pressure().size(); i++)
123 double press = problem.variables().cellData(i).globalPressure() -
uMean;
124 problem.variables().cellData(i).setGlobalPressure(press);
150 double numerator = 0;
151 double denominator = 0;
152 double numeratorGrad = 0;
153 double denominatorGrad = 0;
154 double numeratorFlux = 0;
155 double denominatorFlux = 0;
156 bool exactOutput =
true;
157 for (
const auto& element : elements(gridview))
160 const Geometry& geometry = element.geometry();
163 Dune::GeometryType gt = geometry.type();
166 const Dune::FieldVector<ct,dim>&
167 local = ReferenceElements::general(gt).position(0,0);
170 Dune::FieldVector<ct,dim> globalPos = geometry.global(local);
173 double exactValue = problem.exact(globalPos);
176 int indexi = elementMapper.index(element);
179 exactSol[indexi] = exactValue;
182 double approximateValue = problem.variables().cellData(indexi).globalPressure();
195 double volume = geometry.volume();
198 sumf += volume*(problem.source(globalPos, element, local)[0]);
201 Dune::FieldMatrix<double,dim,dim> K = problem.spatialParams().K(globalPos, element, local);
203 numerator += volume*(exactValue - approximateValue)*(exactValue - approximateValue);
204 denominator += volume*exactValue*exactValue;
207 Dune::FieldVector<ct,2*dim> fluxVector;
208 Dune::FieldVector<ct,dim> exactGradient;
209 for (
const auto& intersection :
intersections(gridview, element))
212 i = intersection.indexInInside();
215 int faceIndex = faceMapper.template map<1>(element, i);
217 Dune::FieldVector<double,dim> faceGlobal = intersection.geometry().center();
218 double faceVol = intersection.geometry().volume();
221 Dune::FieldVector<double,dim> unitOuterNormal = intersection.centerUnitOuterNormal();
224 double approximateFace = (*solution.pressTrace)[faceIndex];
227 exactGradient = problem.exactGrad(faceGlobal);
230 Dune::FieldVector<double,dim> KGrad(0);
231 K.umv(exactGradient, KGrad);
234 double exactFlux = KGrad*unitOuterNormal;
237 double approximateFlux = solution.normalVelocity[indexi][i];
240 double fluxDiff = exactFlux + approximateFlux;
246 numeratorFlux += volume*fluxDiff*fluxDiff;
247 denominatorFlux += volume*exactFlux*exactFlux;
250 exactFlux *= faceVol;
251 approximateFlux *= faceVol;
252 fluxVector[i] = approximateFlux;
255 if (!intersection.neighbor()) {
256 if (abs(faceGlobal[2]) < 1e-6) {
257 fluz0 += approximateFlux;
259 ener2 += -approximateFlux*approximateFace;
261 else if (abs(faceGlobal[2] - 1.0) < 1e-6) {
262 fluz1 += approximateFlux;
264 ener2 += -approximateFlux*approximateFace;
266 if (abs(faceGlobal[1]) < 1e-6) {
267 fluy0 += approximateFlux;
269 ener2 += -approximateFlux*approximateFace;
271 else if (abs(faceGlobal[1] - 1.0) < 1e-6) {
272 fluy1 += approximateFlux;
274 ener2 += -approximateFlux*approximateFace;
276 else if (faceGlobal[0] < 1e-6) {
277 flux0 += approximateFlux;
279 ener2 += -approximateFlux*approximateFace;
281 else if (abs(faceGlobal[0] - 1.0) < 1e-6) {
282 flux1 += approximateFlux;
284 ener2 += -approximateFlux*approximateFace;
291 Dune::FieldVector<double, dim> refVelocity;
293 if (geometry.type().isSimplex()) {
294 for (
int dimIdx = 0; dimIdx < dim; dimIdx++)
296 refVelocity[dimIdx] = -fluxVector[dim - 1 - dimIdx];
297 for (
int fIdx = 0; fIdx < dim + 1; fIdx++)
299 refVelocity[dimIdx] += fluxVector[fIdx]/(dim + 1);
304 else if (geometry.type().isCube()){
305 for (
int j = 0; j < dim; j++)
306 refVelocity[j] = 0.5 * (fluxVector[2*j + 1] - fluxVector[2*j]);
310 DUNE_THROW(Dune::NotImplemented,
"velocity output for prism/pyramid not implemented");
314 const JacobianInverseTransposed& jacobianInv = geometry.jacobianInverseTransposed(local);
315 JacobianInverseTransposed jacobianT(jacobianInv);
319 Dune::FieldVector<ct,dim> elementVelocity(0);
320 jacobianT.umtv(refVelocity, elementVelocity);
321 elementVelocity /= geometry.integrationElement(local);
324 Dune::FieldVector<ct,dim> approximateGradient;
325 K.solve(approximateGradient, elementVelocity);
328 exactGradient = problem.exactGrad(globalPos);
331 Dune::FieldVector<ct,dim> gradDiff(exactGradient);
332 gradDiff += approximateGradient;
335 ener1 += volume*(approximateGradient*elementVelocity);
337 numeratorGrad += volume*(gradDiff*gradDiff);
338 denominatorGrad += volume*(exactGradient*exactGradient);
345 ergrad = sqrt(numeratorGrad/denominatorGrad);
346 ervell2 = sqrt(numeratorFlux/denominatorFlux);
357 Dune::VTKWriter<GV> vtkwriter(gridview);
359 sprintf(fname,
"%d",
"exactSol-numRefine", grid.maxLevel());
360 vtkwriter.addCellData(exactSol,
"exact pressure solution~");
361 vtkwriter.write(fname,Dune::VTK::ascii);