ug4
std_transfer_impl.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2015: G-CSC, Goethe University Frankfurt
3  * Author: Andreas Vogel
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__STD_TRANSFER_IMPL__
34 #define __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__STD_TRANSFER_IMPL__
35 
36 #include "std_transfer.h"
40 #include "lib_grid/algorithms/debug_util.h" // ElementDebugInfo
41 
42 namespace ug{
43 
44 
45 template <typename TDomain, typename TAlgebra>
48  const DoFDistribution& fineDD,
49  const DoFDistribution& coarseDD)
50 {
51  PROFILE_FUNC_GROUP("gmg");
52 // allow only lagrange P1 functions
53  for(size_t fct = 0; fct < fineDD.num_fct(); ++fct)
54  if(fineDD.lfeid(fct).type() != LFEID::LAGRANGE ||
55  fineDD.lfeid(fct).order() != 1)
56  UG_THROW("AssembleStdProlongationForP1Lagrange:"
57  "Interpolation only implemented for Lagrange P1 functions.");
58 
59 // resize matrix
60  P.resize_and_clear(fineDD.num_indices(), coarseDD.num_indices());
61 
62 // iterators
63  const MultiGrid& mg = *coarseDD.multi_grid();
65  const_iterator iter, iterBegin, iterEnd;
66 
67 // loop subsets on fine level
68  std::vector<size_t> vParentIndex, vChildIndex;
69  std::vector<DoFIndex> vParentDoF, vChildDoF;
70  for(int si = 0; si < fineDD.num_subsets(); ++si)
71  {
72  iterBegin = fineDD.template begin<Vertex>(si);
73  iterEnd = fineDD.template end<Vertex>(si);
74 
75  // loop vertices for fine level subset
76  for(iter = iterBegin; iter != iterEnd; ++iter)
77  {
78  // get element
79  Vertex* child = *iter;
80 
81  // get father
82  GridObject* parent = mg.get_parent(child);
83 
84  // check if child contained in coarseDD. This should always be false
85  // for a GridLevel::LEVEL, but might be the case for GridLevel::SURFACE
86  // and an adaptive grid-part used by both dds. In such a case we can
87  // simply set identity.
88  if(coarseDD.is_contained(child)){
89  // get indices
90  coarseDD.inner_algebra_indices(child, vParentIndex);
91  fineDD.inner_algebra_indices(child, vChildIndex);
92  UG_ASSERT(vParentIndex.size() == vChildIndex.size(), "Size mismatch");
93 
94  // set identity
95  for(size_t i = 0; i < vParentIndex.size(); ++i)
96  P(vChildIndex[i], vParentIndex[i]) = 1.0;
97 
98  // this child is perfectly handled
99  continue;
100  }
101  else{
102  // check if parent exists (this should always be the case, except in
103  // the case that 'child' is a v-slave)
104  if(!parent) continue;
105 
106  if(!coarseDD.is_contained(parent)){
107  UG_THROW("StdTransfer: Parent element \n"
108  << ElementDebugInfo(mg, parent) <<
109  "is not contained in coarse-dd nor the child element\n"
110  << ElementDebugInfo(mg, child) <<
111  " in the coarse-dd. This should not happen.")
112  }
113  }
114 
115  // type of father
116  const ReferenceObjectID roid = parent->reference_object_id();
117 
118  // loop all components
119  for(size_t fct = 0; fct < fineDD.num_fct(); fct++)
120  {
121  // check that fct defined on subset
122  if(!fineDD.is_def_in_subset(fct, si)) continue;
123 
124  // get global indices
125  fineDD.inner_dof_indices(child, fct, vChildDoF);
126 
127  // detect type of father
128  switch(roid)
129  {
130  case ROID_VERTEX:
131  {
132  Vertex* vrt = dynamic_cast<Vertex*>(parent);
133  coarseDD.inner_dof_indices(vrt, fct, vParentDoF);
134  DoFRef(P, vChildDoF[0], vParentDoF[0]) = 1.0;
135  }
136  break;
137  case ROID_EDGE:
138  for(int i = 0; i < 2; ++i)
139  {
140  Edge* edge = dynamic_cast<Edge*>(parent);
141  coarseDD.inner_dof_indices(edge->vertex(i), fct, vParentDoF);
142  DoFRef(P, vChildDoF[0], vParentDoF[0]) = 0.5;
143  }
144  break;
145  case ROID_QUADRILATERAL:
146  for(int i = 0; i < 4; ++i)
147  {
148  Face* face = dynamic_cast<Face*>(parent);
149  coarseDD.inner_dof_indices(face->vertex(i), fct, vParentDoF);
150  DoFRef(P, vChildDoF[0], vParentDoF[0]) = 0.25;
151  }
152  break;
153  case ROID_HEXAHEDRON:
154  for(int i = 0; i < 8; ++i)
155  {
156  Volume* hexaeder = dynamic_cast<Volume*>(parent);
157  coarseDD.inner_dof_indices(hexaeder->vertex(i), fct, vParentDoF);
158  DoFRef(P, vChildDoF[0], vParentDoF[0]) = 0.125;
159  }
160  break;
161  default: UG_THROW("AssembleStdProlongationForP1Lagrange: Element father"
162  " is of unsupported type "<< roid << " for "
163  << ElementDebugInfo(mg, child) << ".");
164  }
165  }
166  }
167  }
168 }
169 /*
170 template <typename TDomain>
171 void ProjectGlobalPositionToElem(std::vector<MathVector<TDomain::dim> >& vGlobPos,
172  GridObject* parent, const TDomain& domain)
173 {
174  const int parentDim = parent->base_object_id();
175 
176  // vertex and full dim parent must match
177  if(parentDim == 0 || parentDim == TDomain::dim)
178  return;
179 
180 // get the vertices
181  std::vector<MathVector<TDomain::dim> > vCornerCoord;
182  switch(parentDim)
183  {
184  case EDGE:
185  {
186  CollectCornerCoordinates(vCornerCoord, *static_cast<Edge*>(parent), domain, true);
187  MathVector<TDomain::dim> dir;
188  VecSubtract(dir, vCornerCoord[1], vCornerCoord[0]);
189  for(size_t p = 0; p < vGlobPos.size(); ++p){
190  ProjectPointToRay(vGlobPos[p], vGlobPos[p], vCornerCoord[0], dir);
191  }
192  }
193  break;
194  case FACE:
195  {
196  CollectCornerCoordinates(vCornerCoord, *static_cast<Face*>(parent), domain, true);
197  MathVector<TDomain::dim> normal;
198  MathVector<TDomain::dim> a, b;
199  VecSubtract(a, vCornerCoord[1], vCornerCoord[0]);
200  VecSubtract(b, vCornerCoord[2], vCornerCoord[0]);
201  VecCross(normal, a,b);
202 
203  for(size_t p = 0; p < vGlobPos.size(); ++p){
204  ProjectPointToPlane(vGlobPos[p], vGlobPos[p], vCornerCoord[0], normal);
205  }
206  }
207  break;
208  default: UG_THROW( "Base Object type not found.");
209  }
210 }
211 */
212 
213 
214 template <typename TDomain, typename TAlgebra>
215 template <typename TChild>
218  const DoFDistribution& fineDD,
219  const DoFDistribution& coarseDD,
220  ConstSmartPtr<TDomain> spDomain)
221 {
222  PROFILE_FUNC_GROUP("gmg");
223 
224 // iterators
225  MultiGrid& mg = *const_cast<MultiGrid*>(coarseDD.multi_grid().get());
226  typedef typename DoFDistribution::traits<TChild>::const_iterator const_iterator;
227  const_iterator iter, iterBegin, iterEnd;
228 
229 // loop subsets on coarse level
230  std::vector<DoFIndex> vParentDoF, vChildDoF;
231  std::vector<size_t> vParentIndex, vChildIndex;
232  for(int si = 0; si < fineDD.num_subsets(); ++si)
233  {
234  iterBegin = fineDD.template begin<TChild>(si);
235  iterEnd = fineDD.template end<TChild>(si);
236 
237  // check, which cmps to consider on this subset
238  std::vector<LFEID> vLFEID;
239  std::vector<size_t> vFct;
240  for(size_t fct = 0; fct < fineDD.num_fct(); ++fct){
241  if(fineDD.max_fct_dofs(fct, TChild::dim, si) == 0) continue;
242  vFct.push_back(fct);
243  vLFEID.push_back(fineDD.lfeid(fct));
244  }
245  if(vFct.empty()) continue;
246 
247  // loop elems on coarse level for subset
248  for(iter = iterBegin; iter != iterEnd; ++iter)
249  {
250  // get child
251  TChild* child = *iter;
252 
253  // get parent
254  GridObject* parent = mg.get_parent(child);
255 
256  // check if child contained in coarseDD. This should always be false
257  // for a GridLevel::LEVEL, but might be the case for GridLevel::SURFACE
258  // and an adaptive grid-part used by both dds. In such a case we can
259  // simply set identity.
260  if(coarseDD.is_contained(child)){
261  // get indices
262  coarseDD.inner_algebra_indices(child, vParentIndex);
263  fineDD.inner_algebra_indices(child, vChildIndex);
264  UG_ASSERT(vParentIndex.size() == vChildIndex.size(), "Size mismatch");
265 
266  // set identity
267  for(size_t i = 0; i < vParentIndex.size(); ++i)
268  P(vChildIndex[i], vParentIndex[i]) = 1.0;
269 
270  // this child is perfectly handled
271  continue;
272  }
273  else{
274 
275  // check if parent exists (this should always be the case, except in
276  // the case that 'child' is a v-slave)
277  if(!parent) continue;
278 
279  if(!coarseDD.is_contained(parent)){
280  UG_THROW("StdTransfer: A parent element is not contained in "
281  " coarse-dd nor the child element in the coarse-dd. "
282  "This should not happen.")
283  }
284  }
285 
286  // loop all components
287  for(size_t f = 0; f < vFct.size(); f++)
288  {
289  // get comp and lfeid
290  const size_t fct = vFct[f];
291  const LFEID& lfeID = vLFEID[f];
292 
293  // get global indices
294  fineDD.inner_dof_indices(child, fct, vChildDoF);
295 
296  // switch space type
297  switch(lfeID.type())
298  {
300  {
301  coarseDD.dof_indices(parent, fct, vParentDoF);
302  UG_ASSERT(vChildDoF.size() == 1, "Must be one.");
303  UG_ASSERT(vParentDoF.size() == 1, "Must be one.");
304 
305  DoFRef(P, vChildDoF[0], vParentDoF[0]) = 1.0;
306  }
307  break;
308 
310  {
311  // get dimension of parent
312  const int parentDim = parent->base_object_id();
313  std::vector<GridObject*> vParent;
314 
315  // check if to interpolate from neighbor elems
316  if(parentDim == lfeID.dim()){
317  // case: Side inner to parent. --> Parent fine.
318  vParent.push_back(parent);
319  } else if(parentDim == lfeID.dim() - 1){
320  // case: parent is Side. --> Get neighbor elems
321  typedef typename TChild::sideof TElem;
322  std::vector<TElem*> vElem;
323  coarseDD.collect_associated(vElem, parent);
324  for(size_t p = 0; p < vElem.size(); ++p)
325  vParent.push_back(vElem[p]);
326 
327  } else {
328  UG_THROW("StdTransfer: For CR parent must be full-dim "
329  "elem or a side (dim-1). But has dim: "<<parentDim);
330  }
331 
332 
333  // global positions of fine dofs
334  std::vector<MathVector<TDomain::dim> > vDoFPos;
335  InnerDoFPosition(vDoFPos, child, *spDomain, lfeID);
336 
337  // loop contributions from parents
338  for(size_t i = 0; i < vParent.size(); ++i)
339  {
340  // get coarse indices
341  coarseDD.dof_indices(vParent[i], fct, vParentDoF);
342 
343  // get shapes at global positions
344  std::vector<std::vector<number> > vvShape;
345  ShapesAtGlobalPosition(vvShape, vDoFPos, vParent[i], *spDomain, lfeID);
346 
347  // add restriction
348  for(size_t ip = 0; ip < vvShape.size(); ++ip)
349  for(size_t sh = 0; sh < vvShape[ip].size(); ++sh)
350  DoFRef(P, vChildDoF[ip], vParentDoF[sh]) +=
351  (1./vParent.size()) * vvShape[ip][sh];
352  }
353  }
354  break;
355 
356  case LFEID::LAGRANGE:
357  {
358  // get coarse indices
359  coarseDD.dof_indices(parent, fct, vParentDoF);
360 
361  // global positions of child dofs
362  std::vector<MathVector<TDomain::dim> > vDoFPos;
363  InnerDoFPosition(vDoFPos, child, *spDomain, lfeID);
364 
365  // project
366  // ProjectGlobalPositionToElem(vDoFPos, parent, *spDomain);
367 
368  // get shapes at global positions
369  std::vector<std::vector<number> > vvShape;
370  ShapesAtGlobalPosition(vvShape, vDoFPos, parent, *spDomain, lfeID);
371 
372  // set restriction
373  for(size_t ip = 0; ip < vvShape.size(); ++ip)
374  for(size_t sh = 0; sh < vvShape[ip].size(); ++sh)
375  DoFRef(P, vChildDoF[ip], vParentDoF[sh]) = vvShape[ip][sh];
376  }
377  break;
378 
379  default:
380  UG_THROW("StdTransfer: Local-Finite-Element: "<<lfeID<<
381  " is not supported by this Transfer.")
382 
383  } // end LFEID-switch
384  } // end fct - cmps
385  } // end fine - elements
386  } // end subset
387 }
388 
389 template <typename TDomain, typename TAlgebra>
392  const DoFDistribution& fineDD,
393  const DoFDistribution& coarseDD,
394  ConstSmartPtr<TDomain> spDomain)
395 {
396  // resize matrix
397  P.resize_and_clear(fineDD.num_indices(), coarseDD.num_indices());
398 
399  // loop all base types carrying indices on fine elems
400  if(fineDD.max_dofs(VERTEX)) assemble_prolongation<Vertex>(P, fineDD, coarseDD, spDomain);
401  if(fineDD.max_dofs(EDGE)) assemble_prolongation<Edge>(P, fineDD, coarseDD, spDomain);
402  if(fineDD.max_dofs(FACE)) assemble_prolongation<Face>(P, fineDD, coarseDD, spDomain);
403  if(fineDD.max_dofs(VOLUME)) assemble_prolongation<Volume>(P, fineDD, coarseDD, spDomain);
404 }
405 
406 
407 template <typename TDomain, typename TAlgebra>
408 template <typename TChild>
411  const DoFDistribution& coarseDD,
412  const DoFDistribution& fineDD,
413  ConstSmartPtr<TDomain> spDomain)
414 {
415  PROFILE_FUNC_GROUP("gmg");
416 
417 // iterators
418  MultiGrid& mg = *const_cast<MultiGrid*>(coarseDD.multi_grid().get());
419  typedef typename DoFDistribution::traits<TChild>::const_iterator const_iterator;
420  const_iterator iter, iterBegin, iterEnd;
421 
422 // loop subsets on coarse level
423  std::vector<DoFIndex> vParentDoF, vChildDoF;
424  std::vector<size_t> vParentIndex, vChildIndex;
425  for(int si = 0; si < fineDD.num_subsets(); ++si)
426  {
427  iterBegin = fineDD.template begin<TChild>(si);
428  iterEnd = fineDD.template end<TChild>(si);
429 
430  // check, which cmps to consider on this subset
431  std::vector<LFEID> vLFEID;
432  std::vector<size_t> vFct;
433  for(size_t fct = 0; fct < fineDD.num_fct(); ++fct){
434  if(fineDD.max_fct_dofs(fct, TChild::dim, si) == 0) continue;
435  vFct.push_back(fct);
436  vLFEID.push_back(fineDD.lfeid(fct));
437  }
438  if(vFct.empty()) continue;
439 
440  // loop elems on coarse level for subset
441  for(iter = iterBegin; iter != iterEnd; ++iter)
442  {
443  // get child
444  TChild* child = *iter;
445 
446  // get parent
447  GridObject* parent = mg.get_parent(child);
448 
449  // check if child contained in coarseDD. This should always be false
450  // for a GridLevel::LEVEL, but might be the case for GridLevel::SURFACE
451  // and an adaptive grid-part used by both dds. In such a case we can
452  // simply set identity.
453  if(coarseDD.is_contained(child)){
454  // get indices
455  coarseDD.inner_algebra_indices(child, vParentIndex);
456  fineDD.inner_algebra_indices(child, vChildIndex);
457  UG_ASSERT(vParentIndex.size() == vChildIndex.size(), "Size mismatch");
458 
459  // set identity
460  for(size_t i = 0; i < vParentIndex.size(); ++i)
461  R(vParentIndex[i], vChildIndex[i]) = 1.0;
462 
463  // this child is perfectly handled
464  continue;
465  }
466  else{
467 
468  // check if parent exists (this should always be the case, except in
469  // the case that 'child' is a v-slave)
470  if(!parent) continue;
471 
472  if(!coarseDD.is_contained(parent)){
473  UG_THROW("StdTransfer: A parent element is not contained in "
474  " coarse-dd nor the child element in the coarse-dd. "
475  "This should not happen.")
476  }
477  }
478 
479  // loop all components
480  for(size_t f = 0; f < vFct.size(); f++)
481  {
482  // get comp and lfeid
483  const size_t fct = vFct[f];
484  const LFEID& lfeID = vLFEID[f];
485 
486  // get global indices
487  fineDD.inner_dof_indices(child, fct, vChildDoF);
488 
489  // switch space type
490  switch(lfeID.type())
491  {
493  {
494  coarseDD.dof_indices(parent, fct, vParentDoF);
495  UG_ASSERT(vChildDoF.size() == 1, "Must be one.");
496  UG_ASSERT(vParentDoF.size() == 1, "Must be one.");
497 
498  DoFRef(R, vParentDoF[0], vChildDoF[0]) = 1.0;
499  }
500  break;
501 
503  {
504  // get dimension of parent
505  const int parentDim = parent->base_object_id();
506  std::vector<GridObject*> vParent;
507 
508  // check if to interpolate from neighbor elems
509  if(parentDim == lfeID.dim()){
510  // case: Side inner to parent. --> Parent fine.
511  vParent.push_back(parent);
512  } else if(parentDim == lfeID.dim() - 1){
513  // case: parent is Side. --> Get neighbor elems
514  typedef typename TChild::sideof TElem;
515  std::vector<TElem*> vElem;
516  coarseDD.collect_associated(vElem, parent);
517  for(size_t p = 0; p < vElem.size(); ++p){
518  // NOTE: This is not the transposed of the prolongation
519  // in adaptive case, since we only restrict to
520  // covered parts.
521  if(mg.num_children<TElem>(vElem[p]) > 0)
522  vParent.push_back(vElem[p]);
523  }
524 
525  } else {
526  UG_THROW("StdTransfer: For CR parent must be full-dim "
527  "elem or a side (dim-1). But has dim: "<<parentDim);
528  }
529 
530 
531  // global positions of fine dofs
532  std::vector<MathVector<TDomain::dim> > vDoFPos;
533  InnerDoFPosition(vDoFPos, child, *spDomain, lfeID);
534 
535  // loop contributions from parents
536  for(size_t i = 0; i < vParent.size(); ++i)
537  {
538  // get coarse indices
539  coarseDD.dof_indices(vParent[i], fct, vParentDoF);
540 
541  // get shapes at global positions
542  std::vector<std::vector<number> > vvShape;
543  ShapesAtGlobalPosition(vvShape, vDoFPos, vParent[i], *spDomain, lfeID);
544 
545  // add restriction
546  for(size_t ip = 0; ip < vvShape.size(); ++ip)
547  for(size_t sh = 0; sh < vvShape[ip].size(); ++sh)
548  DoFRef(R, vParentDoF[sh], vChildDoF[ip]) +=
549  (1./vParent.size()) * vvShape[ip][sh];
550  }
551  }
552  break;
553 
554  case LFEID::LAGRANGE:
555  {
556  // get coarse indices
557  coarseDD.dof_indices(parent, fct, vParentDoF);
558 
559  // global positions of child dofs
560  std::vector<MathVector<TDomain::dim> > vDoFPos;
561  InnerDoFPosition(vDoFPos, child, *spDomain, lfeID);
562 
563  // get shapes at global positions
564  std::vector<std::vector<number> > vvShape;
565  ShapesAtGlobalPosition(vvShape, vDoFPos, parent, *spDomain, lfeID);
566 
567  // set restriction
568  for(size_t ip = 0; ip < vvShape.size(); ++ip)
569  for(size_t sh = 0; sh < vvShape[ip].size(); ++sh)
570  DoFRef(R, vParentDoF[sh], vChildDoF[ip]) = vvShape[ip][sh];
571  }
572  break;
573 
574  default:
575  UG_THROW("StdTransfer: Local-Finite-Element: "<<lfeID<<
576  " is not supported by this Transfer.")
577 
578  } // end LFEID-switch
579  } // end fct - cmps
580  } // end fine - elements
581  } // end subset
582 }
583 
584 template <typename TDomain, typename TAlgebra>
587  const DoFDistribution& coarseDD,
588  const DoFDistribution& fineDD,
589  ConstSmartPtr<TDomain> spDomain)
590 {
591  // resize matrix
592  R.resize_and_clear(coarseDD.num_indices(), fineDD.num_indices());
593 
594  // loop all base types carrying indices on fine elems
595  if(fineDD.max_dofs(VERTEX)) assemble_restriction<Vertex>(R, coarseDD, fineDD, spDomain);
596  if(fineDD.max_dofs(EDGE)) assemble_restriction<Edge>(R, coarseDD, fineDD, spDomain);
597  if(fineDD.max_dofs(FACE)) assemble_restriction<Face>(R, coarseDD, fineDD, spDomain);
598  if(fineDD.max_dofs(VOLUME)) assemble_restriction<Volume>(R, coarseDD, fineDD, spDomain);
599 }
600 
601 
602 template <typename TDomain, typename TAlgebra>
605 prolongation(const GridLevel& fineGL, const GridLevel& coarseGL,
607 {
608  if(fineGL.level() - coarseGL.level() != 1)
609  UG_THROW("StdTransfer: Can only project between successive level, "
610  "but fine = "<<fineGL<<", coarse = "<<coarseGL);
611 
612  if(fineGL.type() != coarseGL.type())
613  UG_THROW("StdTransfer: Can only project between dof distributions of "
614  "same type, but fine = "<<fineGL<<", coarse = "<<coarseGL);
615 
616  // remove old revisions
617  remove_outdated(m_mProlongation, spApproxSpace->revision());
618 
619  // key of this restriction
620  TransferKey key(coarseGL, fineGL, spApproxSpace->revision());
621 
622  // check if must be created
623  if(m_mProlongation.find(key) == m_mProlongation.end())
624  {
626  m_mProlongation[key] = SmartPtr<matrix_type>(new matrix_type);
627 
628  ConstSmartPtr<DoFDistribution> spCoarseDD = spApproxSpace->dof_distribution(coarseGL);
629  ConstSmartPtr<DoFDistribution> spFineDD = spApproxSpace->dof_distribution(fineGL);
630 
631  bool P1LagrangeOnly = false;
632  if(m_p1LagrangeOptimizationEnabled){
633  P1LagrangeOnly = true;
634  for(size_t fct = 0; fct < spApproxSpace->num_fct(); ++fct)
635  if(spApproxSpace->lfeid(fct).type() != LFEID::LAGRANGE ||
636  spApproxSpace->lfeid(fct).order() != 1)
637  P1LagrangeOnly = false;
638  }
639 
640  if(P1LagrangeOnly){
641  assemble_prolongation_p1(*P, *spFineDD, *spCoarseDD);
642  } else{
643  assemble_prolongation(*P, *spFineDD, *spCoarseDD, spApproxSpace->domain());
644  }
645 
646  for (int type = 1; type < CT_ALL; type = type << 1)
647  {
648  for (size_t i = 0; i < m_vConstraint.size(); ++i)
649  {
650  if (m_vConstraint[i]->type() & type)
651  m_vConstraint[i]->adjust_prolongation(*P, spFineDD, spCoarseDD, type);
652  }
653  }
654 
655  #ifdef UG_PARALLEL
657  #endif
658 
659  write_debug(*P, "P", fineGL, coarseGL);
660  }
661 
662  return m_mProlongation[key];
663 }
664 
665 template <typename TDomain, typename TAlgebra>
668 restriction(const GridLevel& coarseGL, const GridLevel& fineGL,
670 {
671  if(fineGL.level() - coarseGL.level() != 1)
672  UG_THROW("StdTransfer: Can only project between successive level, "
673  "but fine = "<<fineGL<<", coarse = "<<coarseGL);
674 
675  if(fineGL.type() != coarseGL.type())
676  UG_THROW("StdTransfer: Can only project between dof distributions of "
677  "same type, but fine = "<<fineGL<<", coarse = "<<coarseGL);
678 
679  // remove old revisions
680  remove_outdated(m_mRestriction, spApproxSpace->revision());
681 
682  // key of this restriction
683  TransferKey key(coarseGL, fineGL, spApproxSpace->revision());
684 
685  // check if must be created
686  if(m_mRestriction.find(key) == m_mRestriction.end())
687  {
689  m_mRestriction[key] = SmartPtr<matrix_type>(new matrix_type);
690 
691  ConstSmartPtr<DoFDistribution> spCoarseDD = spApproxSpace->dof_distribution(coarseGL);
692  ConstSmartPtr<DoFDistribution> spFineDD = spApproxSpace->dof_distribution(fineGL);
693 
694  if(m_bUseTransposed)
695  R->set_as_transpose_of(*prolongation(fineGL, coarseGL, spApproxSpace));
696  else
697  assemble_restriction(*R, *spCoarseDD, *spFineDD, spApproxSpace->domain());
698 
699 
700  #ifdef UG_PARALLEL
702  #endif
703 
704  for (int type = 1; type < CT_ALL; type = type << 1)
705  {
706  for (size_t i = 0; i < m_vConstraint.size(); ++i)
707  {
708  if (m_vConstraint[i]->type() & type)
709  m_vConstraint[i]->adjust_restriction(*R, spCoarseDD, spFineDD, type);
710  }
711  }
712 
713  write_debug(*R, "R", coarseGL, fineGL);
714  }
715 
716  return m_mRestriction[key];
717 }
718 
719 template <typename TDomain, typename TAlgebra>
721 prolongate(GF& uFine, const GF& uCoarse)
722 {
723  PROFILE_FUNC_GROUP("gmg");
724 
725  if(!bCached)
726  UG_THROW("StdTransfer: currently only cached implemented.");
727 
728  const GridLevel& coarseGL = uCoarse.grid_level();
729  const GridLevel& fineGL = uFine.grid_level();
731  if(uCoarse.approx_space() != spApproxSpace)
732  UG_THROW("StdTransfer: cannot prolongate between grid functions from "
733  "different approximation spaces.");
734 
735  try{
736  //prolongation(fineGL, coarseGL, spApproxSpace)->apply(uFine, uCoarse);
737 #ifdef UG_PARALLEL
738  MatMultDirect(uFine, m_dampProl, *prolongation(fineGL, coarseGL, spApproxSpace), uCoarse);
739 #else
740  prolongation(fineGL, coarseGL, spApproxSpace)->axpy(uFine, 0.0, uFine, m_dampProl, uCoarse);
741 #endif
742 
743  // adjust using constraints
744  for (int type = 1; type < CT_ALL; type = type << 1)
745  {
746  for (size_t i = 0; i < m_vConstraint.size(); ++i)
747  {
748  if (m_vConstraint[i]->type() & type)
749  m_vConstraint[i]->adjust_prolongation(uFine, fineGL, uCoarse, coarseGL, type);
750  }
751  }
752 
753  }
754  UG_CATCH_THROW("StdTransfer:prolongation: Failed for fine = "<<fineGL<<" and "
755  " coarse = "<<coarseGL);
756 
757 // check CR functions
758 #ifdef UG_PARALLEL
759  bool bCROnly = true;
760  for(size_t fct = 0; fct < spApproxSpace->num_fct(); ++fct)
761  if(spApproxSpace->lfeid(fct).type() != LFEID::CROUZEIX_RAVIART &&
762  spApproxSpace->lfeid(fct).type() != LFEID::PIECEWISE_CONSTANT)
763  bCROnly = false;
764 
765  if(bCROnly){
766  ScaleLayoutValues(&uFine, uFine.layouts()->master(), 0.5);
767  ScaleLayoutValues(&uFine, uFine.layouts()->slave(), 0.5);
768  AdditiveToConsistent(&uFine, uFine.layouts()->master(), uFine.layouts()->slave(),
769  &uFine.layouts()->comm());
770  }
771 #endif
772 }
773 
774 template <typename TDomain, typename TAlgebra>
776 do_restrict(GF& uCoarse, const GF& uFine)
777 {
778  PROFILE_FUNC_GROUP("gmg");
779 
780  if(!bCached)
781  UG_THROW("StdTransfer: currently only cached implemented.");
782 
783  const GridLevel& coarseGL = uCoarse.grid_level();
784  const GridLevel& fineGL = uFine.grid_level();
786  if(uCoarse.approx_space() != spApproxSpace)
787  UG_THROW("StdTransfer: cannot prolongate between grid functions from "
788  "different approximation spaces.");
789  try{
790 
791  restriction(coarseGL, fineGL, spApproxSpace)->
792  apply_ignore_zero_rows(uCoarse, m_dampRes, uFine);
793 
794  // adjust using constraints
795  for (int type = 1; type < CT_ALL; type = type << 1)
796  {
797  for (size_t i = 0; i < m_vConstraint.size(); ++i)
798  {
799  if (m_vConstraint[i]->type() & type)
800  m_vConstraint[i]->adjust_restriction(uCoarse, coarseGL, uFine, fineGL, type);
801  }
802  }
803 
804  } UG_CATCH_THROW("StdTransfer:do_restrict: Failed for fine = "<<fineGL<<" and "
805  " coarse = "<<coarseGL);
806 }
807 
808 template <typename TDomain, typename TAlgebra>
811 {
813  for(size_t i = 0; i < m_vConstraint.size(); ++i)
814  op->add_constraint(m_vConstraint[i]);
815  op->set_restriction_damping(m_dampRes);
816  op->set_prolongation_damping(m_dampProl);
817  op->set_debug(m_spDebugWriter);
818  op->enable_p1_lagrange_optimization(p1_lagrange_optimization_enabled());
819  op->set_use_transposed(m_bUseTransposed);
820  return op;
821 }
822 
823 template <typename TDomain, typename TAlgebra>
825 write_debug(const matrix_type& mat, std::string name,
826  const GridLevel& glTo, const GridLevel& glFrom)
827 {
828  PROFILE_FUNC_GROUP("debug");
829 // if no debug writer set, we're done
830  if(m_spDebugWriter.invalid()) return;
831 
832 // cast dbg writer
834  m_spDebugWriter.template cast_dynamic<GridFunctionDebugWriter<TDomain, TAlgebra> >();
835 
836 // check success
837  if(dbgWriter.invalid()) return;
838 
839 // add iter count to name
840  name.append("_").append(ToString(glTo.level()));
841  name.append("_").append(ToString(glFrom.level()));
842  name.append(".mat");
843 
844 // write
845  GridLevel gridLev = dbgWriter->grid_level();
846  dbgWriter->set_grid_levels(glFrom, glTo);
847  dbgWriter->write_matrix(mat, name.c_str());
848  dbgWriter->set_grid_level(gridLev);
849 }
850 
851 } // end namespace ug
852 
853 #endif /* __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__STD_TRANSFER_IMPL__ */
parameterString p
location name
Definition: checkpoint_util.lua:128
Definition: smart_pointer.h:108
T * get()
returns encapsulated pointer
Definition: smart_pointer.h:197
bool invalid() const
returns true if the pointer is invalid, false if not.
Definition: smart_pointer.h:212
base class for approximation spaces without type of algebra or dof distribution
Definition: approximation_space.h:279
Definition: dof_distribution.h:51
size_t dof_indices(GridObject *elem, size_t fct, std::vector< DoFIndex > &ind, bool bHang=false, bool bClear=true) const
extracts all multiindices for a function (sorted)
Definition: dof_distribution.cpp:1227
void collect_associated(std::vector< TBaseElem * > &vAssElem, TElem *elem, bool clearContainer=true) const
returns the adjacent elements
Definition: dof_distribution.h:176
size_t inner_algebra_indices(GridObject *elem, std::vector< size_t > &ind, bool bClear=true) const
extracts all algebra indices in the inner of the element (not sorted)
Definition: dof_distribution.cpp:1276
size_t inner_dof_indices(GridObject *elem, size_t fct, std::vector< DoFIndex > &ind, bool bClear=true) const
extracts all multiindices of a function in the inner (sorted)
Definition: dof_distribution.cpp:1243
size_t num_indices() const
return the number of dofs distributed
Definition: dof_distribution.h:218
bool is_contained(TGeomObj *obj) const
returns if the grid object is part of the dof distribution
Definition: dof_distribution.h:208
SmartPtr< MultiGrid > multi_grid()
Definition: dof_distribution.h:69
int num_subsets() const
returns number of subsets
Definition: dof_distribution_info.h:192
bool is_def_in_subset(size_t fct, int si) const
returns if a function is defined on a subset
Definition: dof_distribution_info.h:217
size_t max_fct_dofs(const size_t fct, int dim) const
returns the maximal number of dofs on a dimension for a function component
Definition: dof_distribution_info.h:250
const LFEID & lfeid(size_t fct) const
Definition: dof_distribution_info.h:226
size_t max_dofs(const int dim) const
returns the maximum number of dofs on grid objects in a dimension
Definition: dof_distribution_info.h:231
size_t num_fct() const
number of discrete functions on subset si
Definition: dof_distribution_info.h:176
Base-class for edges.
Definition: grid_base_objects.h:397
virtual Vertex * vertex(size_t index) const
Definition: grid_base_objects.h:366
Faces are 2-dimensional objects.
Definition: grid_base_objects.h:510
virtual Vertex * vertex(size_t index) const
Definition: grid_base_objects.h:486
represents numerical solutions on a grid using an algebraic vector
Definition: grid_function.h:121
SmartPtr< ApproximationSpace< TDomain > > approx_space()
returns approx space
Definition: grid_function.h:348
const GridLevel & grid_level() const
returns the grid level
Definition: grid_function.h:247
Definition: grid_level.h:42
ViewType type() const
returns the type
Definition: grid_level.h:77
int level() const
returns the level
Definition: grid_level.h:74
The base class for all geometric objects, such as vertices, edges, faces, volumes,...
Definition: grid_base_objects.h:157
virtual int base_object_id() const =0
virtual ReferenceObjectID reference_object_id() const =0
Identifier for Local Finite Elements.
Definition: local_finite_element_id.h:98
SpaceType type() const
returns the type of the local finite element
Definition: local_finite_element_id.h:132
int order() const
returns the order of the local finite element
Definition: local_finite_element_id.h:126
int dim() const
returns the space dimension of the local finite element
Definition: local_finite_element_id.h:129
@ CROUZEIX_RAVIART
Definition: local_finite_element_id.h:105
@ PIECEWISE_CONSTANT
Definition: local_finite_element_id.h:106
@ LAGRANGE
Definition: local_finite_element_id.h:104
Definition: multi_grid.h:72
GridObject * get_parent(GridObject *parent) const
Definition: multi_grid.cpp:180
size_t num_children(TElem *elem) const
returns the number of children of the given child-type
Definition: multi_grid.h:225
void set_storage_type(uint type)
sets the storage type
Definition: parallel_matrix.h:101
Standard Prolongation Operator.
Definition: std_transfer.h:59
void assemble_restriction(matrix_type &mat, const DoFDistribution &coarseDD, const DoFDistribution &fineDD, ConstSmartPtr< TDomain > spDomain)
Definition: std_transfer_impl.h:410
void assemble_prolongation_p1(matrix_type &mat, const DoFDistribution &fineDD, const DoFDistribution &coarseDD)
Definition: std_transfer_impl.h:47
virtual SmartPtr< matrix_type > restriction(const GridLevel &coarseGL, const GridLevel &fineGL, ConstSmartPtr< ApproximationSpace< TDomain > > spApproxSpace)
returns restriction as a matrix
Definition: std_transfer_impl.h:668
TAlgebra::matrix_type matrix_type
Type of Matrix.
Definition: std_transfer.h:71
virtual void do_restrict(vector_type &uCoarse, const vector_type &uFine)
apply transposed Operator, restrict function
Definition: std_transfer.h:138
virtual SmartPtr< matrix_type > prolongation(const GridLevel &fineGL, const GridLevel &coarseGL, ConstSmartPtr< ApproximationSpace< TDomain > > spApproxSpace)
returns prolongation as a matrix
Definition: std_transfer_impl.h:605
virtual void prolongate(vector_type &uFine, const vector_type &uCoarse)
apply Operator, interpolate function
Definition: std_transfer.h:128
virtual SmartPtr< ITransferOperator< TDomain, TAlgebra > > clone()
returns new instance with same setting
Definition: std_transfer_impl.h:810
void write_debug(const matrix_type &mat, std::string name, const GridLevel &glTo, const GridLevel &glFrom)
debug writing of matrix
Definition: std_transfer_impl.h:825
void assemble_prolongation(matrix_type &mat, const DoFDistribution &fineDD, const DoFDistribution &coarseDD, ConstSmartPtr< TDomain > spDomain)
Definition: std_transfer_impl.h:217
Const iterator to traverse the surface of a multi-grid hierarchy.
Definition: surface_view.h:237
Base-class for all vertex-types.
Definition: grid_base_objects.h:231
Volumes are 3-dimensional objects.
Definition: grid_base_objects.h:754
virtual Vertex * vertex(size_t index) const
Definition: grid_base_objects.h:727
void ScaleLayoutValues(TVector *pVec, const IndexLayout &layout, number scale)
scales the values of a vector by a given number only on the layout indices
Definition: parallelization_util.h:350
void AdditiveToConsistent(TVector *pVec, const IndexLayout &masterLayout, const IndexLayout &slaveLayout, pcl::InterfaceCommunicator< IndexLayout > *pCom=NULL)
changes parallel storage type from additive to consistent
Definition: parallelization_util.h:160
@ PST_CONSISTENT
Definition: parallel_storage_type.h:68
std::string ElementDebugInfo(const Grid &grid, GridObject *e)
Returns a string containing information on the given element.
Definition: debug_util.cpp:991
static const int dim
std::string ToString(const T &t)
Convert a object supporting 'std::cout << obj' to a string.
Definition: string_util.h:358
#define UG_ASSERT(expr, msg)
Definition: assert.h:70
#define UG_CATCH_THROW(msg)
Definition: error.h:64
#define UG_THROW(msg)
Definition: error.h:57
the ug namespace
@ CT_ALL
Definition: ass_tuner.h:60
ReferenceObjectID
these ids are used to identify the shape of a geometric object.
Definition: grid_base_objects.h:74
@ ROID_QUADRILATERAL
Definition: grid_base_objects.h:79
@ ROID_EDGE
Definition: grid_base_objects.h:77
@ ROID_HEXAHEDRON
Definition: grid_base_objects.h:81
@ ROID_VERTEX
Definition: grid_base_objects.h:76
number & DoFRef(TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
Definition: multi_index.h:276
void ShapesAtGlobalPosition(std::vector< std::vector< number > > &vvShape, const std::vector< MathVector< dim > > &vGlobPos, const ReferenceObjectID roid, const std::vector< MathVector< dim > > &vCornerCoord, const LFEID &lfeID)
Definition: dof_position_util.cpp:285
bool MatMultDirect(ParallelVector< vector_type > &dest, const number &beta1, const ParallelMatrix< matrix_type > &A1, const ParallelVector< vector_type > &w1)
Definition: parallel_matrix_impl.h:224
@ VOLUME
Definition: grid_base_objects.h:63
@ VERTEX
Definition: grid_base_objects.h:60
@ EDGE
Definition: grid_base_objects.h:61
@ FACE
Definition: grid_base_objects.h:62
bool InnerDoFPosition(std::vector< MathVector< dim > > &vPos, const ReferenceObjectID roid, const std::vector< MathVector< dim > > &vCornerCoord, const LFEID &lfeID)
Definition: dof_position_util.cpp:112
#define PROFILE_FUNC_GROUP(groups)
Definition: profiler.h:258
struct to distinguish already assembled operators
Definition: std_transfer.h:195