KASKADE 7 development version
algorithm/hierarchicErrorEstimator.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2012 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef ALGORITHM_HIERARCHIC_ERROR_ESTIMATOR_HH
14#define ALGORITHM_HIERARCHIC_ERROR_ESTIMATOR_HH
15
16#include <algorithm>
17#include <iostream>
18#include <utility>
19#include <vector>
20
21#include <boost/timer/timer.hpp>
22#include <boost/fusion/include/at_c.hpp>
23
27#include "fem/variables.hh"
28#include "linalg/direct.hh"
29#include "linalg/tcg.hh"
30#include "utilities/enums.hh"
31
32// forward declarations
33namespace Dune
34{
35 struct InverseOperatorResult;
36 template <class,int> class FieldVector;
37}
38
39namespace Kaskade
40{
41 namespace HierarchicErrorEstimator_Detail{
42 bool biggerThanAbs(const std::pair<double,int>& x1, const std::pair<double,int>& x2)
43 {
44 return fabs(x1.first)>fabs(x2.first);
45 }
46
47 double add(const double& x1, const std::pair<double,int>& x2)
48 {
49 return x1+x2.first;
50 }
51 }
52
53 template <class CorrectionVector>
54 struct LeaveRHS
55 {
56 explicit LeaveRHS(CorrectionVector const&) {}
57
58 template <class RhsVector>
59 void operator()(RhsVector& rhs)
60 {}
61 };
62
63 template <class CorrectionVector>
65 {
66 explicit SubstractCorrection(CorrectionVector const& cor_)
67 : cor(cor_)
68 {}
69
70 template <class RhsVector>
71 void operator()(RhsVector& rhs)
72 {
73 rhs -= cor;
74 }
75
76 private:
77 CorrectionVector const& cor;
78 };
79
80
81 template <class Functional, /*class LF,*/ class ExtensionVariableSetDescription, class ExtensionSpace, class NormFunctional=Functional, template <class> class AdjustRHS=LeaveRHS>
83 {
84 static constexpr int yId = 1, uId = 0, pId = 2;
85 static constexpr int noOfVariables = ExtensionVariableSetDescription::noOfVariables;
86 // typedef typename LF::AnsatzVars LVars;
87 public:
88 typedef typename Functional::Scalar Scalar;
89 typedef typename Functional::AnsatzVars::VariableSet VariableSet;
90 static constexpr int dim = VariableSet::Descriptions::Grid::dimension;
91 typedef HierarchicErrorEstimator<LinearizationAt<Functional>,ExtensionVariableSetDescription,ExtensionVariableSetDescription,HierarchicErrorEstimatorDetail::TakeAllD2<LinearizationAt<Functional> > > ErrorEstimator;
93 typedef typename ExtensionVariableSetDescription::template CoefficientVectorRepresentation<0,2>::type CoefficientVector02;
94 typedef typename ExtensionVariableSetDescription::template CoefficientVectorRepresentation<0,noOfVariables>::type CoefficientVector;
95 typedef typename ExtensionVariableSetDescription::GridView::template Codim<0>::Iterator CellIterator;
96
97 // HierarchicalBasisErrorEstimator(Functional& f_, LF& lf_, LVars& lvars, ExtensionVariableSetDescription& extensionVariableSetDescription_, ExtensionSpace& extensionSpace_, Scalar fraction=0.7, bool verbose_=false)
98 // : f(f_), lf(lf_), normFunctional(f_), extensionVariableSetDescription(extensionVariableSetDescription_), extensionSpace(extensionSpace_), assembler(extensionVariableSetDescription.spaces),
99 // squaredFraction(fraction*fraction), verbose(verbose_)
100 // {}
101
102 HierarchicalBasisErrorEstimator(Functional& f_, /*LF& lf_,*/ /*LVars& lvars_,*/ NormFunctional& normFunctional_, ExtensionVariableSetDescription& extensionVariableSetDescription_,
103 ExtensionSpace& extensionSpace_, Scalar fraction=0.7, bool verbose_=false)
104 : f(f_), /*lf(lf_), lvars(lvars_),*/ normFunctional(normFunctional_), extensionVariableSetDescription(extensionVariableSetDescription_), extensionSpace(extensionSpace_), assembler(extensionVariableSetDescription.spaces),
105 squaredFraction(fraction*fraction), verbose(verbose_)
106 {}
107
109
110 void operator()(AbstractVector const& x_, AbstractVector const& dx_, int step, AbstractVector const& lowerOrderRhs)
111 {
112 if(verbose) std::cout << "ERROR ESTIMATOR: Start." << std::endl;
113 Bridge::Vector<VariableSet> const& x = dynamic_cast<const Bridge::Vector<VariableSet>&>(x_);
114 Bridge::Vector<VariableSet> const& dx = dynamic_cast<const Bridge::Vector<VariableSet>&>(dx_);
115 // Bridge::Vector<VariableSet> const& loRhs = dynamic_cast<const Bridge::Vector<VariableSet>&>(lowerOrderRhs);
116
117
118 boost::timer::cpu_timer atimer;
120 if(verbose) std::cout << "ERROR ESTIMATOR: assembly time: " << boost::timer::format(atimer.elapsed(), 2, "%t") << "s" << std::endl;
121
123 typedef AssembledGalerkinOperator<Assembler,0,2,0,2> CorrectionOperator;
124 typedef typename Functional::AnsatzVars::template CoefficientVectorRepresentation<0,2>::type CorrectionVector;
125
126 Operator op(assembler);
127 // CorrectionOperator(assembler);
128
129 CoefficientVector estRhs(assembler.rhs());
130 std::vector<Scalar> tmpRepVec;
131 IstlInterfaceDetail::toVector(estRhs,tmpRepVec);
132 //estRhs = Bridge::getImpl<VariableSet>(lowerOrderRhs);
133 std::cout << "rhs entries:" << std::endl;
135 for(size_t i=0; i<tmpRepVec.size(); ++i){
136 if(std::isnan(tmpRepVec[i])) std::cout << "nan at " << i << std::endl;
137
138 Scalar val = tmpRepVec[i];
139 if(val < minRhs) minRhs = val;
140 if(val > maxRhs) maxRhs = val;
141 rhsSum += val*val;
142 }
143 std::cout << "max rhs: " << maxRhs << std::endl;
144 std::cout << "min rhs: " << minRhs << std::endl;
145 std::cout << "sum: " << rhsSum << std::endl;
146 // possible adjustment of rhs
147 //adjustRHS(estRhs);
148
149 boost::timer::cpu_timer timer;
150 CoefficientVector estSol(ExtensionVariableSetDescription::template CoefficientVectorRepresentation<0,noOfVariables>::init(extensionVariableSetDescription));
151
153
154
155 if(verbose) std::cout << "ERROR ESTIMATOR: computation time: " << boost::timer::format(timer.elapsed(), 2, "%t") << "s" << std::endl;
156 typename ExtensionVariableSetDescription::VariableSet mySol(extensionVariableSetDescription);
157 mySol = estSol;
158 using namespace boost::fusion;
159
162 sum = 0;
163
164 if(verbose)
165 {
166 for(int i=0; i<at_c<yId>(mySol.data).size(); ++i)
167 {
168 for(int j=0; j<at_c<yId>(mySol.data).coefficients()[i].size; ++j)
169 {
170 Scalar val = at_c<yId>(mySol.data).coefficients()[i][j];
171 sum += val*val;
172 if(val > maxVal) maxVal = val;
173 if(val < minVal) minVal = val;
174 }
175 }
176 std::cout << "y: minimal value: " << minVal << std::endl;
177 std::cout << "y: maximal value: " << maxVal << std::endl;
178 std::cout << "y: l2-sum: " << sum << std::endl;
179 Scalar tmpMax = maxVal, tmpMin = minVal, tmpSum = sum;
182 sum = 0;
183
184 for(int i=0; i<at_c<uId>(mySol.data).size(); ++i)
185 {
186 for(int j=0; j<at_c<uId>(mySol.data).coefficients()[i].size; ++j)
187 {
188 Scalar val = at_c<uId>(mySol.data).coefficients()[i][0];
189 sum += val*val;
190 if(val > maxVal) maxVal = val;
191 if(val < minVal) minVal = val;
192 }
193 }
194 std::cout << "u: minimal value: " << minVal << std::endl;
195 std::cout << "u: maximal value: " << maxVal << std::endl;
196 std::cout << "u: l2-sum: " << sum << std::endl;
197 tmpMax = std::max(tmpMax,maxVal), tmpMin = std::min(tmpMin,minVal), tmpSum += sum;
200 sum = 0;
201
202 for(int i=0; i<at_c<pId>(mySol.data).size(); ++i)
203 {
204 for(int j=0; j<at_c<pId>(mySol.data).coefficients()[i].size; ++j)
205 {
206 Scalar val = at_c<pId>(mySol.data).coefficients()[i][j];
207 sum += val*val;
208 if(val > maxVal) maxVal = val;
209 if(val < minVal) minVal = val;
210 }
211 }
212 std::cout << "p: minimal value: " << minVal << std::endl;
213 std::cout << "p: maximal value: " << maxVal << std::endl;
214 std::cout << "p: l2-sum: " << sum << std::endl;
215
216 tmpSum += sum;
217 std::cout << "minimal value: " << std::min(tmpMin,minVal) << std::endl;
218 std::cout << "maximal value: " << std::max(tmpMax,maxVal) << std::endl;
219 std::cout << "l2-sum: " << tmpSum << std::endl;
220 }
221 // Transfer error indicators to cells.
222 auto const& is = extensionSpace.gridManager().grid().leafIndexSet();
223 errorDistribution.clear();
224 errorDistribution.resize(is.size(0),std::make_pair(0.0,0));
225 Scalar errLevel(0.0), minRefine(0.2);
226
228 EnergyError energyError(normFunctional,x.get(),mySol);
230 EnergyErrorAssembler eeAssembler(extensionSpace.gridManager(), energyError.getSpaces());
231
232 eeAssembler.assemble(linearization(energyError,x.get()), EnergyErrorAssembler::RHS);
233 typename EnergyError::ErrorVector distError( eeAssembler.rhs() );
234 typename EnergyError::AnsatzVars::VariableSet mde( energyError.getVariableSetDescription() );
235 mde = distError;
236
237 if(verbose)
238 {
239 std::string name = "errorDistribution_";
240 name += boost::lexical_cast<std::string>(step);
241 writeVTKFile(mde.descriptions.gridView,mde.descriptions,mde,name);
242 }
243 // Fehler bzgl L_xx : ( sum_i estSol_i * (L_xx * estSol)_i )^{1/2} (nur die x - Komponente, nicht p)
244 // Lokalisierung: einfachste Idee: v_i = estSol_i * (L_xx * estSol)_i
245 // Aufteilen von v_i auf die einzelnen Zellen
246 CellIterator cend = extensionVariableSetDescription.gridView.template end<0>();
247 for (CellIterator ci=extensionVariableSetDescription.gridView.template begin<0>(); ci!=cend; ++ci)
248 errorDistribution[is.index(*ci)] = std::make_pair( fabs(boost::fusion::at_c<0>(mde.data).value(*ci,Dune::FieldVector<Scalar,dim>(0.3))) , is.index(*ci));
249
250 totalErrorSquared = std::accumulate(errorDistribution.begin(), errorDistribution.end(), 0.0, HierarchicErrorEstimator_Detail::add);
251 }
252
254 {
255 // int lastIndexForDoubleRefinement = -1;
256 std::sort(errorDistribution.begin(), errorDistribution.end(), HierarchicErrorEstimator_Detail::biggerThanAbs);
257
258 Scalar bulkCriterionTolerance = squaredFraction*totalErrorSquared;
259 if(verbose)
260 {
261 std::cout << "ERROR ESTIMATOR: totalErrorSquared: " << totalErrorSquared << std::endl;
262 std::cout << "ERROR ESTIMATOR: bulkCriterionTolerance: " << bulkCriterionTolerance << std::endl;
263 }
264 Scalar bulkErrorSquared = 0;
265
266 std::vector<std::pair<Scalar,size_t> > bulkErrorDistribution;
267 auto const& is = extensionSpace.gridManager().grid().leafIndexSet();
268 CellIterator cend = extensionVariableSetDescription.gridView.template end<0>();
269
270 while(bulkErrorSquared < bulkCriterionTolerance)
271 {
272 bulkErrorDistribution.push_back(errorDistribution[bulkErrorDistribution.size()]);
273 bulkErrorSquared += bulkErrorDistribution.back().first;
274 }
275
276 if(verbose) std::cout << "ERROR ESTIMATOR: number of candidates for refinement: " << bulkErrorDistribution.size() << std::endl;
277
278 // size_t lastIndex = bulkErrorDistribution.size()-1;
279 // size_t firstIndex = 0;
280
281 /*while(firstIndex+3 < lastIndex)
282 {
283 if(bulkErrorDistribution.size() > 4)
284 {
285 Scalar firstContribution = bulkErrorDistribution[firstIndex].first;
286 firstContribution *= 15.0/256.0;
287
288 Scalar lastContributions = bulkErrorDistribution[lastIndex--].first;
289 lastContributions += bulkErrorDistribution[lastIndex--].first;
290 lastContributions += bulkErrorDistribution[lastIndex].first;
291 lastContributions *= 15.0/16.0;
292
293 if(lastContributions < firstContribution)
294 {
295 ++lastIndexForDoubleRefinement;
296 ++firstIndex;
297 --lastIndex;
298 bulkErrorDistribution.erase(bulkErrorDistribution.end()-3, bulkErrorDistribution.end());
299 }
300 else break;
301 }
302 }*/
303
304
305 // Refine mesh.
306 for (CellIterator ci=extensionVariableSetDescription.gridView.template begin<0>(); ci!=cend; ++ci) // iterate over cells
307 {
308 for(int i=0; i<bulkErrorDistribution.size(); ++i) // iterate over chosen part of the error distribution
309 if(is.index(*ci) == bulkErrorDistribution[i].second)
310 {
311 // if(i <= lastIndexForDoubleRefinement) {
312 // extensionSpace.gridManager().mark(2,*ci);
313 // }
314 // else{
315 extensionSpace.gridManager().mark(1,*ci);
316 // }
317 }
318 }
319
320 extensionSpace.gridManager().adaptAtOnce();
321 }
322
323 double estimatedAbsoluteError() const final
324 {
325 return sqrt(fabs(totalErrorSquared));
326 }
327
328 size_t gridSize() const final
329 {
330 return extensionSpace.gridManager().grid().size(0);
331 }
332
333 private:
334 Functional& f;
335 // LF& lf;
336 // LVars& lvars;
337 NormFunctional& normFunctional;
338 ExtensionVariableSetDescription& extensionVariableSetDescription;
339 ExtensionSpace& extensionSpace;
340 Assembler assembler;
341 Scalar squaredFraction;
342 Scalar totalErrorSquared;
343 std::vector<std::pair<double,int> > errorDistribution;
344 bool verbose;
345 // AdjustRHS<CoefficientVector> adjustRHS;
346 };
347}
348
349#endif
An adaptor presenting a Dune::LinearOperator <domain_type,range_type> interface to a contiguous sub-b...
Mathematical Vector that supports copy-on-write, implements AbstractFunctionSpaceElement.
Implementation const & get() const
Access to the data.
Defines assembly of hierarchically extended problems for defining DLY style error estimators.
HierarchicErrorEstimator< LinearizationAt< Functional >, ExtensionVariableSetDescription, ExtensionVariableSetDescription, HierarchicErrorEstimatorDetail::TakeAllD2< LinearizationAt< Functional > > > ErrorEstimator
ExtensionVariableSetDescription::template CoefficientVectorRepresentation< 0, 2 >::type CoefficientVector02
VariationalFunctionalAssembler< ErrorEstimator > Assembler
ExtensionVariableSetDescription::template CoefficientVectorRepresentation< 0, noOfVariables >::type CoefficientVector
HierarchicalBasisErrorEstimator(Functional &f_, NormFunctional &normFunctional_, ExtensionVariableSetDescription &extensionVariableSetDescription_, ExtensionSpace &extensionSpace_, Scalar fraction=0.7, bool verbose_=false)
ExtensionVariableSetDescription::GridView::template Codim< 0 >::Iterator CellIterator
void operator()(AbstractVector const &x_, AbstractVector const &dx_, int step, AbstractVector const &lowerOrderRhs)
TestVariableSetDescription::template CoefficientVectorRepresentation< first, last >::type rhs() const
Returns a contiguous subrange of the rhs coefficient vectors.
void assemble(F const &f, unsigned int flags=Assembler::EVERYTHING, int nThreads=0, bool verbose=false)
Assembly without block filter or cell filter.
Error estimation via hierachic FEM.
@ UMFPACK
UMFPack from SuiteSparse, using 32 bit integer indices.
Dune::FieldVector< T, n > max(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise maximum.
Definition: fixdune.hh:110
Dune::FieldVector< T, n > min(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise minimum.
Definition: fixdune.hh:122
bool biggerThanAbs(const std::pair< double, int > &x1, const std::pair< double, int > &x2)
double add(const double &x1, const std::pair< double, int > &x2)
InverseLinearOperator< DirectSolver< typename AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol >::Domain, typename AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol >::Range > > directInverseOperator(AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol > const &A, DirectType directType, MatrixProperties properties)
Definition: direct.hh:618
Bridge classes that connect low level FE algorithms to higher level algorithms.
LeaveRHS(CorrectionVector const &)
SubstractCorrection(CorrectionVector const &cor_)
Variables and their descriptions.