Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
42namespace ug{
43
44
45template <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;
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/*
170template <typename TDomain>
171void 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
214template <typename TDomain, typename TAlgebra>
215template <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
389template <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
407template <typename TDomain, typename TAlgebra>
408template <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
584template <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
602template <typename TDomain, typename TAlgebra>
605prolongation(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
656 P->set_storage_type(PST_CONSISTENT);
657 #endif
658
659 write_debug(*P, "P", fineGL, coarseGL);
660 }
661
662 return m_mProlongation[key];
663}
664
665template <typename TDomain, typename TAlgebra>
668restriction(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
701 R->set_storage_type(PST_CONSISTENT);
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
719template <typename TDomain, typename TAlgebra>
721prolongate(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
774template <typename TDomain, typename TAlgebra>
776do_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
808template <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
823template <typename TDomain, typename TAlgebra>
825write_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:296
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
SmartPtr< MultiGrid > multi_grid()
Definition dof_distribution.h:69
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
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
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
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
std::string ToString(const T &t)
Convert a object supporting 'std::cout << obj' to a string.
Definition string_util.h:362
#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
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
number & DoFRef(TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
Definition multi_index.h:276
#define PROFILE_FUNC_GROUP(groups)
Definition profiler.h:258
SurfaceView::traits< TElem >::const_iterator const_iterator
Definition dof_distribution.h:82
struct to distinguish already assembled operators
Definition std_transfer.h:195