KASKADE 7 development version
lossy_helper.hh
Go to the documentation of this file.
1#ifndef LOSSY_HELPER
2#define LOSSY_HELPER
3
4#include <map>
5
6#include "dune/grid/common/grid.hh"
7#include "dune/grid/common/entity.hh"
8#include "dune/grid/io/file/dgfparser/dgfparser.hh"
9#include "dune/istl/matrix.hh"
10#include "dune/istl/bcrsmatrix.hh"
11#include "dune/common/fmatrix.hh"
12#include "dune/common/iteratorfacades.hh"
13#include "dune/istl/matrixindexset.hh"
14
15#include "linalg/conjugation.hh"
16
17
18namespace Lossy_Detail {
19
20 void bcrsPrint( const Dune::BCRSMatrix<Dune::FieldMatrix<double,1,1> >& bcrsMatrix )
21 {
22 std::cout << std::endl;
23 for(int i=0;i<bcrsMatrix.N();i++)
24 {
25 for(int k =0;k<bcrsMatrix.M();k++)
26 {
27 if(bcrsMatrix.exists(i,k))
28 /*if( bcrsMatrix[i][k] > 0 )*/ std::cout << "(" << i << "," << k << ") : " << bcrsMatrix[i][k] << "\n";
29 }
30 std::cout << std::endl;
31 }
32 std::cout << std::endl;
33 }
34
35
36 template < class Grid >
38 {
39 static const int dim = Grid::dimension;
40 typedef typename Grid::LevelGridView::IndexSet::IndexType IndexType;
41 typedef typename std::pair<IndexType,double> FatherIndexValue;
42 typedef typename std::vector<FatherIndexValue> FatherSimplexPairs;
43
44 private:
45 void findParents( const Grid& grid, int level );
46 int maxLevel;
47
48 public:
49 std::vector< std::vector<FatherSimplexPairs> > levelParentsVector;
50 // levelParentsVector[level][vertexIdx at level][fatherVertexNo] = pair(fatherVertexIdx, barycentricCoor)
51 // level > 0 (level 0 vertices have no father), fatherVertexNo < dim+1 (in 2D for splitting edges at midpoint/red
52 // refinement there should be only 2 father nodes?!)
53
54 ParentalNodes( Grid const& grid ) : maxLevel(grid.maxLevel()), levelParentsVector(maxLevel)
55 {
56 for(int level=1; level<=maxLevel; level++) findParents( grid, level );
57 }
58
59 };
60
61 template < class Grid >
62 void ParentalNodes<Grid>::findParents( const Grid& grid, int level )
63 {
64 typedef typename Grid::template Codim<0>::LevelIterator ElementLevelIterator;
65 typedef typename Grid::template Codim<dim>::Entity VertexPointer;
66 typedef typename Grid::template Codim<0>::Entity ElementPointer;
67 typedef typename Grid::LevelGridView::IndexSet::IndexType IndexType;
68
69 std::vector<FatherSimplexPairs> levelParents( grid.size(level,dim), FatherSimplexPairs(dim+1) );
70
71
72 // helpvector to avoid multiple calls of identical vertices
73 std::vector<bool> toProcess(grid.size(dim), true);
74
75 typename Grid::LevelGridView::IndexSet const& indexSet = grid.levelIndexSet(level) ;
76 typename Grid::LevelGridView::IndexSet const& fatherIndexSet = grid.levelIndexSet(level-1);
77// typename Grid::LevelGridView::IndexSet const& indexSet = grid.levelView(level).indexSet() ;
78// typename Grid::LevelGridView::IndexSet const& fatherIndexSet = grid.levelView(level-1).indexSet();
79
80 Dune::FieldVector<double, dim> geomInFatherCorner ;
81
82
83 // iterate through all cells on current level
84 ElementLevelIterator itEnd = grid.levelGridView(level).template end<0>() ;
85 for(ElementLevelIterator it = grid.levelGridView(level).template begin<0>() ; it != itEnd; ++it)
86 {
87 std::vector<IndexType> fatherIndices(dim+1);
88 ElementPointer itFather = it->father();
89 for(int i=0 ; i<=dim ; i++)
90 {
91 fatherIndices[i] = fatherIndexSet/*grid.levelView(level-1).indexSet()*/.subIndex(itFather, i, dim);
92 }
93
94 // now regard corners of subentity
95 for( int i=0 ; i<=dim ; i++ )
96 {
97 IndexType idx_child = indexSet/*grid.levelView(level).indexSet()*/.subIndex(*it, i, dim);
98
99 if(toProcess[idx_child])
100 {
101 toProcess[idx_child]=false;
102
103 double relativeCoor = 1 ;
104 geomInFatherCorner = it->geometryInFather().corner(i);
105
106 for( int component = dim/*-1*/ ; component >/*=*/ 0; component-- )
107// for( int component = 1 ; component <= dim; component++ )
108 {
109 double val = geomInFatherCorner[component-1];
110 relativeCoor -= val;
111 levelParents[idx_child][component/*+1*/] = std::make_pair(fatherIndices[component/*+1*/],val);
112 }
113 levelParents[idx_child][0] = std::make_pair(fatherIndices[0],relativeCoor);
114 }
115 }
116 }
117
118// std::cout << "Element loop: " << time << "s\n";
119// levelParentsVector.push_back( levelParents );
120 levelParentsVector[level-1] = levelParents;
121 }
122
123
124 template<class Grid>
126 {
127 typedef typename Grid::template Codim<Grid::dimension>::LevelIterator VertexLevelIterator;
128 typedef typename Grid::LevelGridView::IndexSet::IndexType IndexType;
129 typedef typename std::pair<IndexType,double> FatherIndexValue;
131
132 public:
133 Prolongation(Grid const& grid_) : parentalNodes(grid_)
134 {
135 // test: compute prolongation matrix, dropping entries < 1
136 auto maxLevel = grid_.maxLevel();
137 for(int level = 1 ; level <= maxLevel ; level++)
138 {
139 int prolCols = grid_.size( level-1, Grid::dimension ) ;
140 int prolRows = grid_.size( level, Grid::dimension ) ;
141
142 // we now create a BCRS Prolongation matrix
143 // we need three (triangle) or four (tetraeder) nnz's per row, because barycentric coordinates
144 // therefore: prolRows*((Grid::dimension)+1)
145 Dune::BCRSMatrix<M> prolMatrix(prolRows,prolCols, prolRows*((Grid::dimension)+1),Dune::BCRSMatrix<M>::row_wise);
146 typedef Dune::BCRSMatrix<M>::CreateIterator Iter;
147 // now set sparsity pattern
148 for(Iter row=prolMatrix.createbegin(); row!=prolMatrix.createend(); ++row)
149 {
150 for( int k = 0 ; k <= Grid::dimension ; k++ )
151 {
152 row.insert( parentalNodes.levelParentsVector[level-1][row.index()][k].first );
153 }
154 }
155 // now set values
156 for(int row = 0 ; row < prolRows ; row++)
157 {
158 for( int k = 0 ; k <= Grid::dimension ; k++ )
159 {
160 if( parentalNodes.levelParentsVector[level-1][row][k].second > 0.9 ) // consider only 1s
161 prolMatrix[row][ parentalNodes.levelParentsVector[level-1][row][k].first ]
162 = parentalNodes.levelParentsVector[level-1][row][k].second;
163 }
164 }
165 prolStack.push_back( prolMatrix );
166// std::cout << "modified prolongation matrix to level " << level << "\n";
167// bcrsPrint(prolMatrix);
168 }
169// std::cerr << "prolStack computed\n";
170
171 // build level index mapper: levelIndexMapper[level l][idx on l][i] = idx on level l+i+1, i =0,..,maxLevel-l
172 // not only on maxLevel, but for all levels from l+1 up to maxLevel, e.g. for use with solutions defined on coarser levels
173 // as im MLSDC/PFASST
174 indexOnNextLevel.resize(maxLevel, std::vector<size_t>());
175 for( int l = 0; l < maxLevel; l++ )
176 {
177 auto bcrsMatrix = prolStack[l]; // prolongation to level l+1
178 indexOnNextLevel[l].resize(bcrsMatrix.M());
179 for(size_t k =0; k < bcrsMatrix.M(); k++) // iterate through columns
180 {
181 for( size_t i = 0; i < bcrsMatrix.N(); i++ ) // find existing row entry
182 {
183 if(bcrsMatrix.exists(i,k) && bcrsMatrix[i][k] > 0.9 ) // there are zeros and ones only in the matrix
184 {
185 indexOnNextLevel[l][k] = i;
186 break; // leave for i loop
187 }
188 }
189 }
190 }
191// std::cerr << "indexOnNextLevel computed\n";
192
193 levelIndexMapper.resize(maxLevel);
194 for( int l = 0 ; l < maxLevel; l++ )
195 {
196// std::cout << "\nLEVEL " << l << "\n";
197 for( size_t k = 0; k < indexOnNextLevel[l].size(); k++ )
198 {
199// std::cout << "idx " << k << " -> ";
200 levelIndexMapper[l].resize(indexOnNextLevel[l].size());
201 size_t tmpIdx = k ;
202 for( int j = 0; j < maxLevel-l; j++ )
203 {
204 // determine index on level l+j+1
205 tmpIdx = indexOnNextLevel[l+j][tmpIdx];
206 levelIndexMapper[l][k].push_back(tmpIdx);
207// std::cout << tmpIdx << ", " ;
208 }
209// std::cout << "\n";
210 }
211// std::cout << "\n";
212 }
213// std::cerr << "levelIndexMapper computed\n";
214 }
215
217
218
219 // transfer source from level-1 to level
220 // target is resized to have the correct size
221 template<class CoeffVector>
222 void mv( unsigned level, CoeffVector const& source, CoeffVector& target)
223 {
224 unsigned int maxIndex = parentalNodes.levelParentsVector[level].size();
225 target.resize(maxIndex);
226 for( unsigned int i = 0 ; i <maxIndex ; i++ )
227 {
228 target[i] = 0 ;
229 unsigned int maxIndexOld = parentalNodes.levelParentsVector[level][i].size();
230 for( unsigned int j = 0 ; j < maxIndexOld; j++ )
231 {
232 FatherIndexValue tmp = parentalNodes.levelParentsVector[level][i][j];
233 target[i] += source[ tmp.first ] * tmp.second ;
234 }
235 }
236 }
237
238 // leaf has to be handeled separately!
239 size_t getIndexOnLevel(int currentLevel, size_t currentIndex, int targetLevel)
240 {
241 if( targetLevel <= currentLevel ) return currentIndex;
242 return levelIndexMapper[currentLevel][currentIndex][(targetLevel-currentLevel-1)];
243 }
244
245 private:
246 Prolongation( Prolongation const & ) {}
247
248 ParentalNodes<Grid> parentalNodes;
249
250 std::vector<Dune::BCRSMatrix<M>> prolStack;
251 std::vector<std::vector<size_t>> indexOnNextLevel;
252 std::vector<std::vector<std::vector<size_t>>> levelIndexMapper;
253 };
254
255 //------------------------------------------------------------------------------------------------------------------------
256
282 // example usage: ProlongationStack<Grid> prolstack( gridManager.grid() );
283
284 // creates Vector prolStack of prolongationmatrices
285 template < class Grid >
287 {
289
290 public:
291 std::vector<Dune::BCRSMatrix<M> > prolStack;
292 ProlongationStack( const Grid& grid );
293 };
294
295
296 template < class Grid >
298 {
299 using namespace Dune;
300
301 int maxLevel = grid.maxLevel();
302
303 ParentalNodes<Grid> parentalNodes( grid );
304
305 for(int level = 1 ; level <= maxLevel ; level++)
306 {
307 int prolCols = grid.size( level-1, Grid::dimension ) ;
308 int prolRows = grid.size( level, Grid::dimension ) ;
309
310 // we now create a BCRS Prolongation matrix
311 // we need three (triangle) or four (tetraeder) nnz's per row, because barycentric coordinates
312 // therefore: prolRows*((Grid::dimension)+1)
313 BCRSMatrix<M> prolMatrix(prolRows,prolCols, prolRows*((Grid::dimension)+1),BCRSMatrix<M>::row_wise);
314 typedef BCRSMatrix<M>::CreateIterator Iter;
315 // now set sparsity pattern
316 for(Iter row=prolMatrix.createbegin(); row!=prolMatrix.createend(); ++row)
317 {
318 for( int k = 0 ; k <= Grid::dimension ; k++ )
319 {
320 row.insert( parentalNodes.levelParentsVector[level-1][row.index()][k].first );
321 }
322 }
323 // now set values
324 for(int row = 0 ; row < prolRows ; row++)
325 {
326 for( int k = 0 ; k <= Grid::dimension ; k++ )
327 {
328 prolMatrix[row][ parentalNodes.levelParentsVector[level-1][row][k].first ]
329 = parentalNodes.levelParentsVector[level-1][row][k].second;
330 }
331 }
332 prolStack.push_back( prolMatrix );
333 }
334 }
335
336
349 // example usage: ProlongationStack<Grid> prolStack( gridManager.grid() ); MlStack<Grid> myStack( prolStack , bcrsMatrix );
350
351 // creates vector levelMatrixStack of level stiffness matrices
352 template < class Grd >
354 {
356 public:
357 // sets the member levelMatrixStack, a vector of level stiffness matrices
358 MlStack( ProlongationStack<Grd> const& ps , Dune::BCRSMatrix<M> const& bcrsA , bool onlyLowerTriangle = false);
359 std::vector<Dune::BCRSMatrix<M> > levelMatrixStack;
360 };
361
362
363 template < class Grd >
364 MlStack<Grd>::MlStack(ProlongationStack<Grd> const& ps , Dune::BCRSMatrix<M> const& bcrsA , bool onlyLowerTriangle)
365 {
366 using namespace Kaskade;
367 // number of prolongations ( = # gridlevels - 1 )
368 int prols = ps.prolStack.size();
369 // sets the first entry of levelMatrixStack to A (stiffness matrix on leaflevel)
370 levelMatrixStack.push_back(bcrsA);
371
372 for(int i = 0 ; i < prols ; i++)
373 {
374 // format needed for toolbox conjugation.hh --> C=C+P^T*A*P
375 std::unique_ptr<Dune::MatrixIndexSet> C = conjugationPattern<double,M>( ps.prolStack[prols-1-i] , levelMatrixStack[ i ] , onlyLowerTriangle);
376 Dune::BCRSMatrix<M> Cnew;
377 // exportIdx from Dune::MatrixIndexSet
378 C->exportIdx(Cnew);
379 // initialize Cnew
380 Cnew *= 0.0;
381 // now Cnew = Cnew + P^T * A * P , where P and A are level corresponding
382 // prolongation- and stiffness matrices
383 conjugation( Cnew , ps.prolStack[prols-1-i] , levelMatrixStack[ i ] , onlyLowerTriangle );
384 // append new stiffness matrix
385 levelMatrixStack.push_back( Cnew );
386 }
387}
388
389 bool abscompare( double a, double b ) { return fabs( a ) < fabs( b ) ; }
390 template <class T> bool greaterZero(T v) {return v > 0 ;}
391 double ld( double val ) { return log(val)/log(2.0) ; }
392
393} //namespace Lossy_Detail
394
395#endif
std::vector< Dune::BCRSMatrix< M > > levelMatrixStack
MlStack(ProlongationStack< Grd > const &ps, Dune::BCRSMatrix< M > const &bcrsA, bool onlyLowerTriangle=false)
ParentalNodes(Grid const &grid)
Definition: lossy_helper.hh:54
std::vector< std::vector< FatherSimplexPairs > > levelParentsVector
Definition: lossy_helper.hh:49
Prolongation(Grid const &grid_)
void mv(unsigned level, CoeffVector const &source, CoeffVector &target)
size_t getIndexOnLevel(int currentLevel, size_t currentIndex, int targetLevel)
ProlongationStack(const Grid &grid)
std::vector< Dune::BCRSMatrix< M > > prolStack
Finds the parent nodes and their interpolation weight for each node in the grid. usage eg....
void conjugation(Dune::BCRSMatrix< Entry > &C, Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, 1, 1 > > const &P, Dune::BCRSMatrix< Entry > const &A, bool onlyLowerTriangle=false)
Computes the triple sparse matrix product .
Definition: conjugation.hh:286
auto & component(LinearProductSpace< Scalar, Sequence > &x)
Definition: linearspace.hh:463
bool abscompare(double a, double b)
double ld(double val)
bool greaterZero(T v)
void bcrsPrint(const Dune::BCRSMatrix< Dune::FieldMatrix< double, 1, 1 > > &bcrsMatrix)
Definition: lossy_helper.hh:20