50 template <
class FromSpace,
class ToSpace>
61 auto eval = from.evaluator(&sfCache,0);
62 std::vector<std::tuple<size_t,size_t,Real>> entries;
64 for (
auto const& tv: Dune::vertices(to.gridView()))
66 auto x = tv.geometry().center();
67 auto const& sc =
findCell(from.gridView(),x);
69 eval.evaluateAt(sc.geometry().local(x));
70 auto sfCoeff = from.linearCombination(eval);
72 auto row = to.indexSet().index(tv);
73 for (
auto const& pair: sfCoeff)
75 auto col = pair.first;
77 entries.push_back(std::make_tuple(row,col,pair.second[0]));
83 for (
auto const& entry: entries)
84 P[std::get<0>(entry)][std::get<1>(entry)] = std::get<2>(entry);
124 template <
class FromSpace,
class ToSpace>
127 using LeafView =
typename FromSpace::Grid::LeafGridView;
129 assert((
"Coarse space should have less DOFs than fine space.", from.degreesOfFreedom()<to.degreesOfFreedom()));
136 auto eval = from.evaluator(&sfCache,0);
137 std::vector<std::tuple<size_t,size_t,Real>> entries;
140 const auto& idxCoarse = from.gridView().indexSet();
147 std::vector<double> rowscale(to.degreesOfFreedom(),1.0);
150 for(
const auto& fVert : Dune::vertices(to.gridView()) )
153 auto xglob = fVert.geometry().center();
161 eval.evaluateAt(cell.geometry().local(xglob));
162 auto coeff = from.linearCombination(eval);
165 auto row = to.indexSet().index(fVert);
169 double rowtotal(0.), rowMax(0.), rowdiff(0.);
170 for(
const auto& p : coeff)
172 double val = p.second[0];
173 rowtotal += fabs(val);
174 if(fabs(val) > rowMax)
181 for(
const auto& p:coeff)
184 double val = p.second[0];
186 if(fabs(val) >= 1e-10 && fabs(val) >= tolTrunc*rowtotal)
189 entries.push_back(std::make_tuple(row,col,val));
191 rowdiff += fabs(val);
197 assert((
"Truncation deletes all row entries! Use smaller tolerance or other criterion for truncation.", rowdiff < rowtotal ));
198 if(tolTrunc>0 && rowdiff != 0)
199 rowscale.at(row) = rowtotal/(rowtotal-rowdiff);
204 for (
auto const& entry: entries)
205 P[std::get<0>(entry)][std::get<1>(entry)] = rowscale.at(std::get<0>(entry))*std::get<2>(entry);
224 std::vector<Prolongation>
229 std::vector<Prolongation> retPs;
233 int levels = ps.size();
237 std::vector<size_t> nzCols(ps.at(levels-1).N());
240 for(
int l=levels-1; l>=0; --l)
245 std::vector<size_t> allCols(Pl.
M());
246 std::iota(allCols.begin(),allCols.end(),0);
250 if(nzCols.size() < Pl.
N() && l!=levels-1)
251 Pl = submatrix<Prolongation>(Pl,nzCols,allCols);
255 timer.start(
"seeking nonzero columns");
256 nzCols = nonZeroColumns(Pl);
257 timer.stop(
"seeking nonzero columns");
258 std::cout <<
"Found " << Pl.
M() - nzCols.size() <<
" zero columns in P-matrix on level " << l <<
". Removing... ";
261 if(nzCols.size() < Pl.
M())
263 std::vector<size_t> allRows(Pl.
N());
264 std::iota(allRows.begin(),allRows.end(),0);
265 Pl = submatrix<Prolongation>(Pl,allRows,nzCols);
267 std::cout <<
"done! \n";
270 retPs.insert(retPs.begin(), Pl);
299 template <
class Space>
300 std::vector<Prolongation>
makeNonNestedPstack(std::initializer_list<Space> spacelist,
double tolTrunc=0.1)
302 std::cout <<
"Build prolongation stack based on " << spacelist.size() <<
" spaces (levels).\n";
303 std::vector<Prolongation> ps;
304 for(
auto space = spacelist.begin(); space!= spacelist.end()-1; ++space)
333 template <
class Space1,
class Space2>
334 std::vector<Prolongation>
makeJointPstack(Space1 space1, Space2 space2,
int coarseLevel=0)
336 std::vector<Prolongation> Pstack;
338 std::cout <<
"grid1:\n";
340 std::cout <<
"grid2:\n";
342 assert((
"At least one grid should be hierarchical.", Pstack1.size()+Pstack2.size()>0));
345 size_t n1 = space1.grid().leafGridView().size(space1.dim), n2 = space2.grid().size(space2.dim);
346 if(Pstack1.size()<Pstack2.size())
348 while(Pstack1.size()<Pstack2.size())
349 Pstack1.push_back(sparseUnitMatrix<double,1>(n1));
350 }
else if (Pstack1.size() > Pstack2.size())
352 while(Pstack1.size()>Pstack2.size())
353 Pstack2.push_back(sparseUnitMatrix<double,1>(n2));
355 assert((
"Number of levels differ on the grids.",Pstack1.size() == Pstack2.size()));
356 for(
int i=0; i<Pstack1.size(); ++i)
357 Pstack.push_back(diagcat(Pstack1[i],Pstack2[i]));
358 for(
int i=0; i<Pstack.size(); ++i)
359 std::cout <<
"prolongation matrix P(" << i <<
"," << i+1 <<
") has dimensions " << Pstack[i].N() <<
"x" << Pstack[i].M() <<
".\n";
376 template <
class Space,
class Entry,
class Index>
377 MultiGridStack<Prolongation,Entry,Index>
379 double volumeRatio=100)
381 assert(A.
N() == space.degreesOfFreedom());
382 using Grid =
typename Space::Grid;
383 std::cout <<
"creating cover grid..."; std::cout.flush();
385 std::cout <<
" done\n"; std::cout.flush();
389 std::cout <<
"cover grid vertices: " << coverSpace.
degreesOfFreedom() <<
"\n"; std::cout.flush();
393 std::cout <<
"creating prolongation..."; std::cout.flush();
395 std::cout <<
"done\n"; std::cout.flush();
396 std::cout <<
"creating conjugation..."; std::cout.flush();
397 std::vector<Matrix> as{
conjugation(P,A,
false,
true),A};
398 std::cout <<
"done\n"; std::cout.flush();
399 std::vector<Prolongation> ps{std::move(P)};
404 std::cout <<
"making spd..."; std::cout.flush();
405 double maxDiagonal = 0;
406 for (Index i=0; i<as[0].N(); ++i)
407 maxDiagonal =
std::max(maxDiagonal,as[0][i][i].frobenius_norm());
408 for (Index i=0; i<as[0].N(); ++i)
409 if (as[0][i][i].frobenius_norm() < 1e-8*maxDiagonal)
410 as[0][i][i] = 1e-8*maxDiagonal*unitMatrix<typename Entry::field_type,Entry::rows>();
411 std::cout <<
"done\n"; std::cout.flush();
413 std::cout <<
"creating multigridstack..."; std::cout.flush();
std::pair< Cell, double > closestCell(Position const &pos) const
Returns a pair consisting of the closest cell to pos and the distance to this cell.
A representation of a finite element function space defined over a domain covered by a grid.
size_t degreesOfFreedom() const
Returns the dimension of the function space, i.e. the number of degrees of freedom of a one-component...
Grid const & grid() const
Returns a const reference on the owned grid.
Class for multigrid stacks.
A NUMA-aware compressed row storage matrix adhering mostly to the Dune ISTL interface (to complete....
Index M() const
The number of columns.
Index N() const
The number of rows.
A NUMA-aware creator for matrix sparsity patterns.
void addElement(Index row, Index col)
Enters a single entry into the sparsity pattern.
Scalar Real
The real type on which the scalar field is based.
This class caches values and derivatives of shape functions at quadrature points.
static Timings & instance()
Returns a reference to a single default instance.
std::vector< Prolongation > makeNonNestedPstack(std::initializer_list< Space > spacelist, double tolTrunc=0.1)
Computes an interpolation matrix for transfer between P1 finite element spaces on two different (poss...
Prolongation twoGridProlongation(FromSpace const &from, ToSpace const &to)
Computes an interpolation matrix for transfer between P1 finite element spaces on two different grids...
std::vector< Prolongation > makeJointPstack(Space1 space1, Space2 space2, int coarseLevel=0)
Computes a (joint) prolongation stack for a geometry defined by two grids.
Prolongation nonNestedProlongation(FromSpace const &from, ToSpace const &to, double tolTrunc=0.1)
Computes an interpolation matrix for transfer between P1 finite element spaces on two different (poss...
std::vector< Prolongation > nonNestedProlognationStack(std::vector< Prolongation > ps)
Computes a full column rank prolongation stack from a colum rank deficient prolongation stack.
std::unique_ptr< typename GridView::Grid > createCoverGrid(GridView const &gv, double volumeRatio=10)
Creates a cartesian structured grid occupying the bounding box of the given grid view.
Cell< GridView > findCell(GridView const &gv, GlobalPosition< GridView > global)
Returns a cell of the given grid containing the specified global coordinate.
Dune::FieldVector< T, n > max(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise maximum.
auto makeDeepProlongationStack(FineSpace const &space, int coarseLevel=0, int minNodes=0)
Convenience routine for creating a deep prolongation stack from coarse to fine grid and on from P1 to...
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 .
MultiGridStack< Prolongation, Entry, Index > makeAuxiliarySpaceMultigridStack(Space const &space, NumaBCRSMatrix< Entry, Index > const &A, double volumeRatio=100)
creates a semi-geometric multigrid preconditioner based on an auxiliary space