Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
line_smoothers.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2015: G-CSC, Goethe University Frankfurt
3 * Author: Christian Wehner
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/*
34 * Gauss-Seidel type smoothers using alternating directions
35 * for handling of anisotropic problems
36 * Steps forward and backward in all coordinate directions
37 */
38
39#ifndef __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__LINE_SMOOTHERS__
40#define __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__LINE_SMOOTHERS__
41
44
48//#include "lib_disc/dof_manager/ordering/lexorder.h"
53#ifdef UG_PARALLEL
56#endif
57
58namespace ug{
59
60// extern definition (in cpp file, avoiding conflicts)
61template<int dim>
62extern bool ComparePosDimYDir(const std::pair<MathVector<dim>, size_t> &p1,
63 const std::pair<MathVector<dim>, size_t> &p2);
64
65template<int dim>
66extern bool ComparePosDimZDir(const std::pair<MathVector<dim>, size_t> &p1,
67 const std::pair<MathVector<dim>, size_t> &p2);
68
69
70// ORDER IN Y DIRECTION
71
72template<int dim>
73void ComputeDirectionYOrder(std::vector<std::pair<MathVector<dim>, size_t> >& vPos,std::vector<size_t>& indY)
74{
75 indY.resize(indY.size()+vPos.size());
76 // sort indices based on their position
77 std::sort(vPos.begin(), vPos.end(), ComparePosDimYDir<dim>);
78 // write mapping
79 for (size_t i=0; i < vPos.size(); ++i){
80 indY[i] = vPos[i].second;
81 };
82}
83
84template <typename TDomain>
86 ConstSmartPtr<TDomain> domain,std::vector<size_t>& indY)
87{
88 // Lex Ordering is only possible in this cases:
89 // b) Same number of DoFs on each geometric object (or no DoFs on object)
90 // --> in this case we can order all dofs
91 // a) different trial spaces, but DoFs for each trial spaces only on separate
92 // geometric objects. (e.g. one space only vertices, one space only on edges)
93 // --> in this case we can order all geometric objects separately
94
95 // a) check for same number of DoFs on every geometric object
96 bool bEqualNumDoFOnEachGeomObj = true;
97 int numDoFOnGeomObj = -1;
98 for(int si = 0; si < dd->num_subsets(); ++si){
99 for(int roid = 0; roid < NUM_REFERENCE_OBJECTS; ++roid){
100 const int numDoF = dd->num_dofs((ReferenceObjectID)roid, si);
101
102 if(numDoF == 0) continue;
103
104 if(numDoFOnGeomObj == -1){
105 numDoFOnGeomObj = numDoF;
106 }
107 else{
108 if(numDoFOnGeomObj != numDoF)
109 bEqualNumDoFOnEachGeomObj = false;
110 }
111 }
112 }
113
114 // b) check for non-mixed spaces
115 std::vector<bool> bSingleSpaceUsage(NUM_REFERENCE_OBJECTS, true);
116 std::vector<bool> vHasDoFs(NUM_REFERENCE_OBJECTS, false);
117 for(size_t fct = 0; fct < dd->num_fct(); ++fct){
118
119 LFEID lfeID = dd->local_finite_element_id(fct);
121
122 for(int roid = 0; roid < NUM_REFERENCE_OBJECTS; ++roid){
123 const int numDoF = locDoF.num_dof((ReferenceObjectID)roid);
124
125 if(numDoF <= 0) continue;
126
127 if(vHasDoFs[roid] == false){
128 vHasDoFs[roid] = true;
129 }
130 else{
131 bSingleSpaceUsage[roid] = false;
132 }
133 }
134 }
135 std::vector<bool> bSortableComp(dd->num_fct(), true);
136 for(size_t fct = 0; fct < dd->num_fct(); ++fct){
137
138 LFEID lfeID = dd->local_finite_element_id(fct);
140
141 for(int roid = 0; roid < NUM_REFERENCE_OBJECTS; ++roid){
142 if(locDoF.num_dof((ReferenceObjectID)roid) != 0){
143 if(bSingleSpaceUsage[roid] == false)
144 bSortableComp[fct] = false;
145 }
146 }
147 }
148
149 // get position attachment
150 typedef typename std::pair<MathVector<TDomain::dim>, size_t> pos_type;
151
152 // get positions of indices
153 std::vector<pos_type> vPositions;
154
155 // a) we can order globally
156 if(bEqualNumDoFOnEachGeomObj)
157 {
158 ExtractPositions(domain, dd, vPositions);
159
160 ComputeDirectionYOrder<TDomain::dim>(vPositions, indY);
161 }
162 // b) we can only order some spaces
163 else
164 {
165// UG_LOG("OrderLex: Cannot order globally, trying to order some components:\n");
166 for(size_t fct = 0; fct < dd->num_fct(); ++fct){
167 if(bSortableComp[fct] == false){
168// UG_LOG("OrderLex: "<<dd->name(fct)<<" NOT SORTED.\n");
169 continue;
170 }
171
172 ExtractPositions(domain, dd, fct, vPositions);
173
174 ComputeDirectionYOrder<TDomain::dim>(vPositions, indY);
175 }
176 }
177};
178
179
180// ORDER IN Z DIRECTION
181
182
183template<int dim>
184void ComputeDirectionZOrder(std::vector<std::pair<MathVector<dim>, size_t> >& vPos,std::vector<size_t>& indZ)
185{
186 indZ.resize(indZ.size()+vPos.size());
187 std::sort(vPos.begin(), vPos.end(), ComparePosDimZDir<dim>);
188 for (size_t i=0; i < vPos.size(); ++i){
189 indZ[i] = vPos[i].second;
190 };
191}
192
193template <typename TDomain>
195 ConstSmartPtr<TDomain> domain,std::vector<size_t>& indZ)
196{
197 // Lex Ordering is only possible in this cases:
198 // b) Same number of DoFs on each geometric object (or no DoFs on object)
199 // --> in this case we can order all dofs
200 // a) different trial spaces, but DoFs for each trial spaces only on separate
201 // geometric objects. (e.g. one space only vertices, one space only on edges)
202 // --> in this case we can order all geometric objects separately
203
204 // a) check for same number of DoFs on every geometric object
205 bool bEqualNumDoFOnEachGeomObj = true;
206 int numDoFOnGeomObj = -1;
207 for(int si = 0; si < dd->num_subsets(); ++si){
208 for(int roid = 0; roid < NUM_REFERENCE_OBJECTS; ++roid){
209 const int numDoF = dd->num_dofs((ReferenceObjectID)roid, si);
210
211 if(numDoF == 0) continue;
212
213 if(numDoFOnGeomObj == -1){
214 numDoFOnGeomObj = numDoF;
215 }
216 else{
217 if(numDoFOnGeomObj != numDoF)
218 bEqualNumDoFOnEachGeomObj = false;
219 }
220 }
221 }
222
223 // b) check for non-mixed spaces
224 std::vector<bool> bSingleSpaceUsage(NUM_REFERENCE_OBJECTS, true);
225 std::vector<bool> vHasDoFs(NUM_REFERENCE_OBJECTS, false);
226 for(size_t fct = 0; fct < dd->num_fct(); ++fct){
227
228 LFEID lfeID = dd->local_finite_element_id(fct);
230
231 for(int roid = 0; roid < NUM_REFERENCE_OBJECTS; ++roid){
232 const int numDoF = locDoF.num_dof((ReferenceObjectID)roid);
233
234 if(numDoF <= 0) continue;
235
236 if(vHasDoFs[roid] == false){
237 vHasDoFs[roid] = true;
238 }
239 else{
240 bSingleSpaceUsage[roid] = false;
241 }
242 }
243 }
244 std::vector<bool> bSortableComp(dd->num_fct(), true);
245 for(size_t fct = 0; fct < dd->num_fct(); ++fct){
246
247 LFEID lfeID = dd->local_finite_element_id(fct);
249
250 for(int roid = 0; roid < NUM_REFERENCE_OBJECTS; ++roid){
251 if(locDoF.num_dof((ReferenceObjectID)roid) != 0){
252 if(bSingleSpaceUsage[roid] == false)
253 bSortableComp[fct] = false;
254 }
255 }
256 }
257
258 // get position attachment
259 typedef typename std::pair<MathVector<TDomain::dim>, size_t> pos_type;
260
261 // get positions of indices
262 std::vector<pos_type> vPositions;
263
264 // a) we can order globally
265 if(bEqualNumDoFOnEachGeomObj)
266 {
267 ExtractPositions(domain, dd, vPositions);
268
269 // get mapping: old -> new index
270 ComputeDirectionZOrder<TDomain::dim>(vPositions, indZ);
271 }
272 // b) we can only order some spaces
273 else
274 {
275// UG_LOG("OrderLex: Cannot order globally, trying to order some components:\n");
276 for(size_t fct = 0; fct < dd->num_fct(); ++fct){
277 if(bSortableComp[fct] == false){
278 // UG_LOG("OrderLex: "<<dd->name(fct)<<" NOT SORTED.\n");
279 continue;
280 }
281
282 ExtractPositions(domain, dd, fct, vPositions);
283
284 // get mapping: old -> new index
285 ComputeDirectionZOrder<TDomain::dim>(vPositions, indZ);
286 }
287 }
288};
289
290
291template <typename TDomain, typename TBaseElem>
294 std::vector<size_t>& indarray,number alpha){
296// vector for positions
297 std::vector<MathVector<TDomain::dim> > vElemPos;
298
299// algebra indices vector
300 std::vector<DoFIndex> ind;
301
302 const typename TDomain::position_accessor_type& aaPos = domain->position_accessor();
303
304// loop all subsets
305 for(int si = 0; si < dd->num_subsets(); ++si)
306 {
307 // get iterators
308 iter = dd->template begin<TBaseElem>(si);
309 iterEnd = dd->template end<TBaseElem>(si);
310
311 // loop all elements
312 for(;iter != iterEnd; ++iter)
313 {
314 // get vertex
315 TBaseElem* elem = *iter;
316
317 // loop all functions
318 for(size_t fct = 0; fct < dd->num_fct(); ++fct)
319 {
320 // skip non-used function
321 if(!dd->is_def_in_subset(fct,si)) continue;
322 std::vector<Edge*> vEdge;
323 CollectEdgesSorted(vEdge, domain->grid, elem);
324 std::vector<number> edgeLength(vEdge.size());
325 std::vector<DoFIndex> ind;
326 MathVector<TDomain::dim> vCoord[2];
327 for (size_t i=0;i<vEdge.size();i++){
328 for (size_t j=0;j<2;j++) vCoord[i] = aaPos[vEdge[i]->vertex(i)];
329 edgeLength[i] = VecDistance(vCoord[0],vCoord[1]);
330 };
331 number minedgelength=edgeLength[0];
332 number maxedgelength=edgeLength[1];
333 for (size_t i=1;i<vEdge.size();i++){
334 if (edgeLength[i]<minedgelength) minedgelength=edgeLength[i];
335 if (edgeLength[i]>maxedgelength) maxedgelength=edgeLength[i];
336 };
337 if (maxedgelength/minedgelength>alpha){
338 // load indices associated with element function
339 dd->inner_dof_indices(elem, fct, ind);
340
341 // load positions associated with element and function
342 InnerDoFPosition(vElemPos, elem, *(const_cast<TDomain*>(domain.get())),
343 dd->local_finite_element_id(fct));
344
345 // check correct size
346 UG_ASSERT(ind.size() == vElemPos.size(), "Num MultiIndex ("<<ind.size()
347 <<") and Num Position ("<<vElemPos.size()<<") must match."
349
350 // write position
351 for(size_t sh = 0; sh < ind.size(); ++sh)
352 {
353 const size_t index = ind[sh][0];
354 indarray.push_back(index);
355 }
356 };
357 };
358 };
359 };
360};
361
362
363
364template <typename TDomain,typename TAlgebra>
365class LineGaussSeidel : public IPreconditioner<TAlgebra>
366{
367 public:
369 typedef TDomain domain_type;
370
371 // Algebra type
372 typedef TAlgebra algebra_type;
373
374 // Vector type
375 typedef typename TAlgebra::vector_type vector_type;
376
377 // Matrix type
378 typedef typename TAlgebra::matrix_type matrix_type;
379
382
385
386 protected:
390
391 protected:
392 // approximation space for level and surface grid
394
395 // index sets
396 std::vector<size_t> indY;
397 std::vector<size_t> indZ;
398 size_t m_ind_end;
399
406
408 static const int dim = domain_type::dim;
409
410 bool m_init;
411
412 public:
413 // Constructor
415 m_spApproxSpace = approxSpace;
416 m_init = false;
423 OrderLex<TDomain>(*m_spApproxSpace,"lr");
424 };
425
426 // Update ordering indices
427 bool update(size_t xsize){
428 indY.resize(0);
429 indZ.resize(0);
430 // lexicographic ordering of unknowns
432// OrderLex<TDomain>(*m_spApproxSpace,"lr");
433 }
435 size_t level=3289578756;
436 for (size_t i=0;i<m_spApproxSpace->num_levels();i++){
437 if (m_spApproxSpace->dof_distribution(GridLevel(i, GridLevel::LEVEL, true))->num_indices()==xsize){
438 level = i;
439 break;
440 };
441 };
442 if (level==3289578756){
443 return false;
444 }
445 if ((dim>1)&&(m_nr_forwardy+m_nr_backwardy>0)){
446 OrderDirectionYForDofDist<TDomain>(m_spApproxSpace->dof_distribution(GridLevel(level, GridLevel::LEVEL, true)), m_spApproxSpace->domain(),indY);
447 }
448 if ((dim>2)&&(m_nr_forwardz+m_nr_backwardz>0)){
449 OrderDirectionZForDofDist<TDomain>(m_spApproxSpace->dof_distribution(GridLevel(level, GridLevel::LEVEL, true)), m_spApproxSpace->domain(),indZ);
450 }
451 };
452 m_ind_end = indY.size();
453 m_init = true;
454 return true;
455 }
456
457 // Destructor
459 indY.clear();
460 indZ.clear();
461 };
462
463 void set_num_steps(size_t forwardx,size_t backwardx,size_t forwardy,size_t backwardy,size_t forwardz,size_t backwardz){
464 m_nr_forwardx=forwardx;
465 m_nr_backwardx=backwardx;
466 m_nr_forwardy=forwardy;
467 m_nr_backwardy=backwardy;
468 m_nr_forwardz=forwardz;
469 m_nr_backwardz=backwardz;
470 };
471
472 void set_num_steps(size_t forwardx,size_t backwardx,size_t forwardy,size_t backwardy){
473 m_nr_forwardx=forwardx;
474 m_nr_backwardx=backwardx;
475 m_nr_forwardy=forwardy;
476 m_nr_backwardy=backwardy;
479 };
480
481 void set_num_steps(size_t forwardx,size_t backwardx){
482 m_nr_forwardx=forwardx;
483 m_nr_backwardx=backwardx;
488 };
489
490 // Clone
492 {
494 newInst->set_debug(debug_writer());
495 newInst->set_damp(this->damping());
496 newInst->set_num_steps(this->get_num_forwardx(),this->get_num_backwardx(),this->get_num_forwardy(),this->get_num_backwardy(),
497 this->get_num_forwardz(),this->get_num_backwardz());
498 return newInst;
499 }
500
502 virtual bool supports_parallel() const {return true;}
503
504 public:
511
512 protected:
513 // Name of preconditioner
514 virtual const char* name() const {return "Line Gauss-Seidel";}
515
516 // Preprocess routine
518 {
519#ifdef UG_PARALLEL
520 if(pcl::NumProcs() > 1)
521 {
522 // copy original matrix
523 MakeConsistent(*pOp, m_A);
524 // set zero on slaves
525 std::vector<IndexLayout::Element> vIndex;
526 CollectUniqueElements(vIndex, m_A.layouts()->slave());
527 SetDirichletRow(m_A, vIndex);
528 }
529#endif
530 return true;
531 }
532
533 // Postprocess routine
534 virtual bool postprocess() {return true;}
535
536 // Stepping routine
538 {
539#ifdef UG_PARALLEL
540 if(pcl::NumProcs() > 1)
541 {
542 // make defect unique
543 // todo: change that copying
544 vector_type dhelp;
545 dhelp.resize(d.size()); dhelp = d;
546 dhelp.change_storage_type(PST_UNIQUE);
547 if (!linegs_step(m_A, c, dhelp)) return false;
548// if(!gs_step_LL(m_A, c, dhelp)) return false;
549 c.set_storage_type(PST_UNIQUE);
550 return true;
551 }
552 else
553#endif
554 {
555 if(!linegs_step(*pOp, c, d)) return false;
556 // if(!gs_step_LL(mat, c, d)) return false;
557#ifdef UG_PARALLEL
558 c.set_storage_type(PST_UNIQUE);
559#endif
560 return true;
561 }
562 }
563
564 protected:
565#ifdef UG_PARALLEL
567#endif
568
569 bool linegs_step(const matrix_type &A, vector_type &x, const vector_type &b)
570 {
571 // gs LL has preconditioning matrix
572 // (D-L)^{-1}
573 if (m_init==false) update(x.size());
574
575 size_t i;
576
577 typename vector_type::value_type s;
578
579 // forward in x direction
580 if (m_nr_forwardx>0){
581
582 for(i=0; i < x.size(); i++)
583 {
584 s = b[i];
585
586 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i) && it.index() < i; ++it)
587 // s -= it.value() * x[it.index()];
588 MatMultAdd(s, 1.0, s, -1.0, it.value(), x[it.index()]);
589
590 // x[i] = s/A(i,i)
591 InverseMatMult(x[i], 1.0, A(i,i), s);
592 }
593 for (size_t count=1;count<m_nr_forwardx;count++){
594 for(i=0; i < x.size(); i++)
595 {
596 s = b[i];
597 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i); ++it){
598 if (it.index()==i) continue;
599 // s -= it.value() * x[it.index()];
600 MatMultAdd(s, 1.0, s, -1.0, it.value(), x[it.index()]);
601 }
602 // x[i] = s/A(i,i)
603 InverseMatMult(x[i], 1.0, A(i,i), s);
604 }
605 };
606 };
607
608 // backward in x direction
609 for (size_t count=0;count<m_nr_backwardx;count++){
610 for (i=x.size()-1; (int)i>= 0; i--)
611 {
612 s = b[i];
613
614 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i); ++it){
615 if (it.index()==i) continue;
616 // s -= it.value() * x[it.index()];
617 MatMultAdd(s, 1.0, s, -1.0, it.value(), x[it.index()]);
618 }
619 // x[i] = s/A(i,i)
620 InverseMatMult(x[i], 1.0, A(i,i), s);
621 if (i==0) break;
622 };
623 };
624
625 if (dim==1) return true;
626
628
629 // forward in y direction
630 for (size_t count=0;count<m_nr_forwardy;count++){
631 for (size_t j=0;j < m_ind_end; j++){
632 i = indY[j];
633
634 s = b[i];
635
636 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i); ++it){
637 if (it.index()==i) continue;
638 // s -= it.value() * x[it.index()];
639 MatMultAdd(s, 1.0, s, -1.0, it.value(), x[it.index()]);
640 }
641 // x[i] = s/A(i,i)
642 InverseMatMult(x[i], 1.0, A(i,i), s);
643 }
644 };
645
646 // backward in y direction
647 for (size_t count=0;count<m_nr_backwardy;count++){
648 for (size_t j=m_ind_end-1;(int)j >= 0; j--){
649 i = indY[j];
650
651 s = b[i];
652
653 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i); ++it){
654 if (it.index()==i) continue;
655 // s -= it.value() * x[it.index()];
656 MatMultAdd(s, 1.0, s, -1.0, it.value(), x[it.index()]);
657 }
658 // x[i] = s/A(i,i)
659 InverseMatMult(x[i], 1.0, A(i,i), s);
660 if (j==0) break;
661 }
662 };
663 if (dim==2) return true;
664
665 // forward in z direction
666 for (size_t count=0;count<m_nr_forwardz;count++){
667 for (size_t j=0;j < m_ind_end; j++){
668 i = indZ[j];
669
670 s = b[i];
671
672 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i) ; ++it){
673 if (it.index()==i) continue;
674 // s -= it.value() * x[it.index()];
675 MatMultAdd(s, 1.0, s, -1.0, it.value(), x[it.index()]);
676 };
677 // x[i] = s/A(i,i)
678 InverseMatMult(x[i], 1.0, A(i,i), s);
679 }
680 }
681
682 // backward in z direction
683 for (size_t count=0;count<m_nr_backwardz;count++){
684 for (size_t j=m_ind_end-1;(int)j >= 0; j--){
685 i = indZ[j];
686
687 s = b[i];
688
689 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i) ; ++it){
690 if (it.index()==i) continue;
691 // s -= it.value() * x[it.index()];
692 MatMultAdd(s, 1.0, s, -1.0, it.value(), x[it.index()]);
693 };
694 // x[i] = s/A(i,i)
695 InverseMatMult(x[i], 1.0, A(i,i), s);
696 if (j==0) break;
697 }
698 }
699 return true;
700 }
701
702};
703
704template <typename TDomain,typename TAlgebra>
705class LineVanka : public IPreconditioner<TAlgebra>
706{
707 public:
709 typedef TDomain domain_type;
710
711 // Algebra type
712 typedef TAlgebra algebra_type;
713
714 // Vector type
715 typedef typename TAlgebra::vector_type vector_type;
716
717 // Matrix type
718 typedef typename TAlgebra::matrix_type matrix_type;
719
722
725
726 protected:
730
731 protected:
732 // approximation space for level and surface grid
734
735 // index sets
736 std::vector<size_t> indY;
737 std::vector<size_t> indZ;
738 size_t m_ind_end;
739
746
748 static const int dim = domain_type::dim;
749
750 bool m_init;
751
752 public:
754 void set_relax(number omega){m_relax=omega;};
755 number relax(){return m_relax;};
756
757 protected:
759
760 public:
761 // Constructor
763 m_spApproxSpace = approxSpace;
764 m_init = false;
771 m_relax=1;
772// OrderLex<TDomain>(*m_spApproxSpace,"lr");
773 };
774
775 // Update ordering indices
776 bool update(size_t xsize){
777 indY.resize(0);
778 indZ.resize(0);
779 // lexicographic ordering of unknowns
781// OrderLex<TDomain>(*m_spApproxSpace,"lr");
782 }
784 size_t level=3289578756;
785 for (size_t i=0;i<m_spApproxSpace->num_levels();i++){
786 if (m_spApproxSpace->dof_distribution(GridLevel(i, GridLevel::LEVEL, true))->num_indices()==xsize){
787 level = i;
788 break;
789 };
790 };
791 if (level==3289578756){
792 return false;
793 }
794 if ((dim>1)&&(m_nr_forwardy+m_nr_backwardy>0)){
795 OrderDirectionYForDofDist<TDomain>(m_spApproxSpace->dof_distribution(GridLevel(level, GridLevel::LEVEL, true)), m_spApproxSpace->domain(),indY);
796 }
797 if ((dim>2)&&(m_nr_forwardz+m_nr_backwardz>0)){
798 OrderDirectionZForDofDist<TDomain>(m_spApproxSpace->dof_distribution(GridLevel(level, GridLevel::LEVEL, true)), m_spApproxSpace->domain(),indZ);
799 }
800 };
801 m_ind_end = indY.size();
802 m_init = true;
803 return true;
804 }
805
806 // Destructor
808 indY.clear();
809 indZ.clear();
810 };
811
812 void set_num_steps(size_t forwardx,size_t backwardx,size_t forwardy,size_t backwardy,size_t forwardz,size_t backwardz){
813 m_nr_forwardx=forwardx;
814 m_nr_backwardx=backwardx;
815 m_nr_forwardy=forwardy;
816 m_nr_backwardy=backwardy;
817 m_nr_forwardz=forwardz;
818 m_nr_backwardz=backwardz;
819 };
820
821 void set_num_steps(size_t forwardx,size_t backwardx,size_t forwardy,size_t backwardy){
822 m_nr_forwardx=forwardx;
823 m_nr_backwardx=backwardx;
824 m_nr_forwardy=forwardy;
825 m_nr_backwardy=backwardy;
828 };
829
830 void set_num_steps(size_t forwardx,size_t backwardx){
831 m_nr_forwardx=forwardx;
832 m_nr_backwardx=backwardx;
837 };
838
839 // Clone
841 {
843 newInst->set_debug(debug_writer());
844 newInst->set_damp(this->damping());
845 newInst->set_num_steps(this->get_num_forwardx(),this->get_num_backwardx(),this->get_num_forwardy(),this->get_num_backwardy(),
846 this->get_num_forwardz(),this->get_num_backwardz());
847 newInst->set_relax(this->relax());
848 return newInst;
849 }
850
852 virtual bool supports_parallel() const {return true;}
853
854 public:
861
862 protected:
863 // Name of preconditioner
864 virtual const char* name() const {return "Line Vanka";}
865
866 // Preprocess routine
868 {
869#ifdef UG_PARALLEL
870 if(pcl::NumProcs() > 1)
871 {
872 // copy original matrix
873 MakeConsistent(*pOp, m_A);
874 // set zero on slaves
875 std::vector<IndexLayout::Element> vIndex;
876 CollectUniqueElements(vIndex, m_A.layouts()->slave());
877 SetDirichletRow(m_A, vIndex);
878 }
879#endif
880 return true;
881 }
882
883 // Postprocess routine
884 virtual bool postprocess() {return true;}
885
886 // Stepping routine
888 {
889#ifdef UG_PARALLEL
890 if(pcl::NumProcs() > 1)
891 {
892 // make defect unique
893 // todo: change that copying
894 vector_type dhelp;
895 dhelp.resize(d.size()); dhelp = d;
896 dhelp.change_storage_type(PST_UNIQUE);
897 if (!linevanka_step(m_A, c, dhelp)) return false;
898// if(!gs_step_LL(m_A, c, dhelp)) return false;
899 c.set_storage_type(PST_UNIQUE);
900 return true;
901 }
902 else
903#endif
904 {
905 if(!linevanka_step(*pOp, c, d)) return false;
906 // if(!gs_step_LL(mat, c, d)) return false;
907#ifdef UG_PARALLEL
908 c.set_storage_type(PST_UNIQUE);
909#endif
910 return true;
911 }
912 }
913
914 protected:
915#ifdef UG_PARALLEL
917#endif
918
920 {
924
925 static const int MAXBLOCKSIZE = 19;
926 size_t blockind[MAXBLOCKSIZE];
927 size_t blocksize;
928 // gs LL has preconditioning matrix
929 // (D-L)^{-1}
930 if (m_init==false) update(x.size());
931
932 size_t i;
933 size_t nrofelements=0;
934
935 for(i=0; i < x.size(); i++)
936 {
937 x[i]=0;
938 if (A(i,i)==0) nrofelements++;
939 };
940
941 // forward in x direction
942 for (size_t count=0;count<m_nr_forwardx;count++){
943 for(i=0; i < x.size(); i++){
944 if (A(i,i)!=0) continue;
945 blocksize=0;
946 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i) ; ++it){
947 blockind[blocksize] = it.index();
948 x[it.index()] = 0;
949 blocksize++;
950 };
951 mat.resize(blocksize,blocksize);
952 s.resize(blocksize);
953 localx.resize(blocksize);
954 for (size_t j=0;j<blocksize;j++){
955 // fill local block matrix
956 for (size_t k=0;k<blocksize;k++){
957 mat.subassign(j,k,A(blockind[j],blockind[k]));
958 };
959 // compute rhs
960 typename vector_type::value_type sj = b[blockind[j]];
961 for(typename matrix_type::const_row_iterator it = A.begin_row(blockind[j]); it != A.end_row(blockind[j]) ; ++it){
962 MatMultAdd(sj, 1.0, sj, -1.0, it.value(), x[it.index()]);
963 };
964 s.subassign(j,sj);
965 };
966 // solve block
967 InverseMatMult(localx,1,mat,s);
968 for (size_t j=0;j<blocksize;j++){
969 x[blockind[j]] = m_relax*localx[j];
970 };
971 };
972 };
973 // backward in x direction
974 for (size_t count=0;count<m_nr_backwardx;count++){
975 for (i=x.size()-1;(int)i>= 0; i--)
976 {
977 if (A(i,i)==0){
978 blocksize=0;
979 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i) ; ++it){
980 blockind[blocksize] = it.index();
981 x[it.index()] = 0;
982 blocksize++;
983 };
984 mat.resize(blocksize,blocksize);
985 s.resize(blocksize);
986 localx.resize(blocksize);
987 for (size_t j=0;j<blocksize;j++){
988 // fill local block matrix
989 for (size_t k=0;k<blocksize;k++){
990 mat.subassign(j,k,A(blockind[j],blockind[k]));
991 };
992 // compute rhs
993 typename vector_type::value_type sj = b[blockind[j]];
994 for(typename matrix_type::const_row_iterator it = A.begin_row(blockind[j]); it != A.end_row(blockind[j]) ; ++it){
995 MatMultAdd(sj, 1.0, sj, -1.0, it.value(), x[it.index()]);
996 };
997 s.subassign(j,sj);
998 };
999 // solve block
1000 InverseMatMult(localx,1,mat,s);
1001 for (size_t j=0;j<blocksize;j++){
1002 x[blockind[j]] = m_relax*localx[j];
1003 };
1004 };
1005 if (i==0) break;
1006 };
1007 };
1008
1009 if (dim==1) return true;
1010
1012
1013 // forward in y direction
1014 for (size_t count=0;count<m_nr_forwardy;count++){
1015 for (size_t sortedi=0;sortedi < m_ind_end; sortedi++){
1016 i = indY[sortedi];
1017 blocksize=0;
1018 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i) ; ++it){
1019 blockind[blocksize] = it.index();
1020 x[it.index()] = 0;
1021 blocksize++;
1022 };
1023 mat.resize(blocksize,blocksize);
1024 s.resize(blocksize);
1025 localx.resize(blocksize);
1026 for (size_t j=0;j<blocksize;j++){
1027 // fill local block matrix
1028 for (size_t k=0;k<blocksize;k++){
1029 mat.subassign(j,k,A(blockind[j],blockind[k]));
1030 };
1031 // compute rhs
1032 typename vector_type::value_type sj = b[blockind[j]];
1033 for(typename matrix_type::const_row_iterator it = A.begin_row(blockind[j]); it != A.end_row(blockind[j]) ; ++it){
1034 MatMultAdd(sj, 1.0, sj, -1.0, it.value(), x[it.index()]);
1035 };
1036 s.subassign(j,sj);
1037 };
1038 // solve block
1039 InverseMatMult(localx,1,mat,s);
1040 for (size_t j=0;j<blocksize;j++){
1041 x[blockind[j]] = m_relax*localx[j];
1042 };
1043 }
1044 };
1045
1046 // backward in y direction
1047 for (size_t count=0;count<m_nr_backwardy;count++){
1048 for (size_t sortedi=m_ind_end-1;(int)sortedi >= 0; sortedi--){
1049 i = indY[sortedi];
1050 blocksize=0;
1051 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i) ; ++it){
1052 blockind[blocksize] = it.index();
1053 x[it.index()] = 0;
1054 blocksize++;
1055 };
1056 mat.resize(blocksize,blocksize);
1057 s.resize(blocksize);
1058 localx.resize(blocksize);
1059 for (size_t j=0;j<blocksize;j++){
1060 // fill local block matrix
1061 for (size_t k=0;k<blocksize;k++){
1062 mat.subassign(j,k,A(blockind[j],blockind[k]));
1063 };
1064 // compute rhs
1065 typename vector_type::value_type sj = b[blockind[j]];
1066 for(typename matrix_type::const_row_iterator it = A.begin_row(blockind[j]); it != A.end_row(blockind[j]) ; ++it){
1067 MatMultAdd(sj, 1.0, sj, -1.0, it.value(), x[it.index()]);
1068 };
1069 s.subassign(j,sj);
1070 };
1071 // solve block
1072 InverseMatMult(localx,1,mat,s);
1073 for (size_t j=0;j<blocksize;j++){
1074 x[blockind[j]] = m_relax*localx[j];
1075 };
1076 if (sortedi==0) break;
1077 }
1078 };
1079 if (dim==2) return true;
1080
1081 // forward in z direction
1082 for (size_t count=0;count<m_nr_forwardz;count++){
1083 for (size_t sortedi=0;sortedi < m_ind_end; sortedi++){
1084 i = indZ[sortedi];
1085 blocksize=0;
1086 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i) ; ++it){
1087 blockind[blocksize] = it.index();
1088 x[it.index()] = 0;
1089 blocksize++;
1090 };
1091 mat.resize(blocksize,blocksize);
1092 s.resize(blocksize);
1093 localx.resize(blocksize);
1094 for (size_t j=0;j<blocksize;j++){
1095 // fill local block matrix
1096 for (size_t k=0;k<blocksize;k++){
1097 mat.subassign(j,k,A(blockind[j],blockind[k]));
1098 };
1099 // compute rhs
1100 typename vector_type::value_type sj = b[blockind[j]];
1101 for(typename matrix_type::const_row_iterator it = A.begin_row(blockind[j]); it != A.end_row(blockind[j]) ; ++it){
1102 MatMultAdd(sj, 1.0, sj, -1.0, it.value(), x[it.index()]);
1103 };
1104 s.subassign(j,sj);
1105 };
1106 // solve block
1107 InverseMatMult(localx,1,mat,s);
1108 for (size_t j=0;j<blocksize;j++){
1109 x[blockind[j]] = m_relax*localx[j];
1110 };
1111 }
1112 }
1113
1114 // backward in z direction
1115 for (size_t count=0;count<m_nr_backwardz;count++){
1116 for (size_t sortedi=m_ind_end-1;(int)sortedi >= 0; sortedi--){
1117 i = indZ[sortedi];
1118 blocksize=0;
1119 for(typename matrix_type::const_row_iterator it = A.begin_row(i); it != A.end_row(i) ; ++it){
1120 blockind[blocksize] = it.index();
1121 x[it.index()] = 0;
1122 blocksize++;
1123 };
1124 mat.resize(blocksize,blocksize);
1125 s.resize(blocksize);
1126 localx.resize(blocksize);
1127 for (size_t j=0;j<blocksize;j++){
1128 // fill local block matrix
1129 for (size_t k=0;k<blocksize;k++){
1130 mat.subassign(j,k,A(blockind[j],blockind[k]));
1131 };
1132 // compute rhs
1133 typename vector_type::value_type sj = b[blockind[j]];
1134 for(typename matrix_type::const_row_iterator it = A.begin_row(blockind[j]); it != A.end_row(blockind[j]) ; ++it){
1135 MatMultAdd(sj, 1.0, sj, -1.0, it.value(), x[it.index()]);
1136 };
1137 s.subassign(j,sj);
1138 };
1139 // solve block
1140 InverseMatMult(localx,1,mat,s);
1141 for (size_t j=0;j<blocksize;j++){
1142 x[blockind[j]] = m_relax*localx[j];
1143 };
1144 if (sortedi==0) break;
1145 }
1146 }
1147 return true;
1148 }
1149
1150};
1151
1152} // end namespace ug
1153
1154#endif // __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__LINE_SMOOTHERS__
parameterString s
Definition smart_pointer.h:296
const T * get() const
Definition smart_pointer.h:409
Definition smart_pointer.h:108
base class for approximation spaces without type of algebra or dof distribution
Definition approximation_space.h:279
Definition local_dof_set.h:195
int num_dof(ReferenceObjectID roid) const
number of dofs on a reference element type
Definition local_dof_set.h:210
virtual void set_debug(SmartPtr< IDebugWriter< algebra_type > > spDebugWriter)
set debug writer
Definition debug_writer.h:384
void write_debug(const matrix_type &mat, const char *filename)
write debug output for a matrix (if debug writer set)
Definition debug_writer.h:399
SmartPtr< IDebugWriter< algebra_type > > debug_writer()
returns the debug writer
Definition debug_writer.h:391
Definition densematrix.h:57
void subassign(size_t r, size_t c, const TStorage2 &t)
Definition densematrix.h:215
Definition densevector.h:101
Definition grid_level.h:42
@ LEVEL
Definition grid_level.h:48
SmartPtr< IDamping< TAlgebra::vector_type, TAlgebra::vector_type > > damping()
returns the scaling
Definition linear_iterator.h:173
describes a linear iterator that is based on a matrix operator
Definition preconditioner.h:103
Identifier for Local Finite Elements.
Definition local_finite_element_id.h:98
Definition line_smoothers.h:366
virtual bool supports_parallel() const
returns if parallel solving is supported
Definition line_smoothers.h:502
bool update(size_t xsize)
Definition line_smoothers.h:427
virtual const char * name() const
returns the name of iterator
Definition line_smoothers.h:514
void set_num_steps(size_t forwardx, size_t backwardx)
Definition line_smoothers.h:481
size_t get_num_forwardz()
Definition line_smoothers.h:509
matrix_type m_A
Definition line_smoothers.h:566
virtual SmartPtr< ILinearIterator< vector_type > > clone()
clone
Definition line_smoothers.h:491
SmartPtr< ApproximationSpace< TDomain > > m_spApproxSpace
Definition line_smoothers.h:393
LineGaussSeidel(SmartPtr< ApproximationSpace< TDomain > > approxSpace)
Definition line_smoothers.h:414
TAlgebra::vector_type vector_type
Definition line_smoothers.h:375
~LineGaussSeidel()
Definition line_smoothers.h:458
size_t get_num_forwardx()
Definition line_smoothers.h:505
TAlgebra algebra_type
Definition line_smoothers.h:372
size_t get_num_backwardz()
Definition line_smoothers.h:510
virtual bool step(SmartPtr< MatrixOperator< matrix_type, vector_type > > pOp, vector_type &c, const vector_type &d)
computes a new correction c = B*d
Definition line_smoothers.h:537
TDomain domain_type
Domain.
Definition line_smoothers.h:369
bool m_init
Definition line_smoothers.h:410
size_t m_ind_end
Definition line_smoothers.h:398
size_t m_nr_backwardz
Definition line_smoothers.h:405
IPreconditioner< TAlgebra > base_type
Base type.
Definition line_smoothers.h:384
size_t m_nr_backwardy
Definition line_smoothers.h:403
IPreconditioner< TAlgebra >::matrix_operator_type matrix_operator_type
Matrix Operator type.
Definition line_smoothers.h:381
size_t m_nr_forwardz
Definition line_smoothers.h:404
static const int dim
world dimension
Definition line_smoothers.h:408
bool linegs_step(const matrix_type &A, vector_type &x, const vector_type &b)
Definition line_smoothers.h:569
size_t get_num_forwardy()
Definition line_smoothers.h:507
void set_num_steps(size_t forwardx, size_t backwardx, size_t forwardy, size_t backwardy)
Definition line_smoothers.h:472
size_t get_num_backwardy()
Definition line_smoothers.h:508
TAlgebra::matrix_type matrix_type
Definition line_smoothers.h:378
virtual bool preprocess(SmartPtr< MatrixOperator< matrix_type, vector_type > > pOp)
initializes the preconditioner
Definition line_smoothers.h:517
std::vector< size_t > indZ
Definition line_smoothers.h:397
size_t m_nr_forwardx
Definition line_smoothers.h:400
size_t get_num_backwardx()
Definition line_smoothers.h:506
void set_num_steps(size_t forwardx, size_t backwardx, size_t forwardy, size_t backwardy, size_t forwardz, size_t backwardz)
Definition line_smoothers.h:463
virtual bool postprocess()
cleans the operator
Definition line_smoothers.h:534
size_t m_nr_forwardy
Definition line_smoothers.h:402
std::vector< size_t > indY
Definition line_smoothers.h:396
size_t m_nr_backwardx
Definition line_smoothers.h:401
Definition line_smoothers.h:706
size_t m_nr_forwardx
Definition line_smoothers.h:740
bool update(size_t xsize)
Definition line_smoothers.h:776
IPreconditioner< TAlgebra > base_type
Base type.
Definition line_smoothers.h:724
size_t m_nr_backwardz
Definition line_smoothers.h:745
virtual bool preprocess(SmartPtr< MatrixOperator< matrix_type, vector_type > > pOp)
initializes the preconditioner
Definition line_smoothers.h:867
void set_num_steps(size_t forwardx, size_t backwardx, size_t forwardy, size_t backwardy)
Definition line_smoothers.h:821
void set_num_steps(size_t forwardx, size_t backwardx)
Definition line_smoothers.h:830
TAlgebra::matrix_type matrix_type
Definition line_smoothers.h:718
virtual bool step(SmartPtr< MatrixOperator< matrix_type, vector_type > > pOp, vector_type &c, const vector_type &d)
computes a new correction c = B*d
Definition line_smoothers.h:887
size_t get_num_forwardz()
Definition line_smoothers.h:859
TAlgebra::vector_type vector_type
Definition line_smoothers.h:715
std::vector< size_t > indY
Definition line_smoothers.h:736
size_t m_ind_end
Definition line_smoothers.h:738
virtual SmartPtr< ILinearIterator< vector_type > > clone()
clone
Definition line_smoothers.h:840
virtual bool supports_parallel() const
returns if parallel solving is supported
Definition line_smoothers.h:852
bool m_init
Definition line_smoothers.h:750
size_t get_num_backwardy()
Definition line_smoothers.h:858
number m_relax
Definition line_smoothers.h:758
size_t get_num_forwardx()
Definition line_smoothers.h:855
SmartPtr< ApproximationSpace< TDomain > > m_spApproxSpace
Definition line_smoothers.h:733
virtual const char * name() const
returns the name of iterator
Definition line_smoothers.h:864
std::vector< size_t > indZ
Definition line_smoothers.h:737
TAlgebra algebra_type
Definition line_smoothers.h:712
size_t get_num_backwardx()
Definition line_smoothers.h:856
IPreconditioner< TAlgebra >::matrix_operator_type matrix_operator_type
Matrix Operator type.
Definition line_smoothers.h:721
static const int dim
world dimension
Definition line_smoothers.h:748
TDomain domain_type
Domain.
Definition line_smoothers.h:709
size_t m_nr_forwardz
Definition line_smoothers.h:744
size_t get_num_backwardz()
Definition line_smoothers.h:860
virtual bool postprocess()
cleans the operator
Definition line_smoothers.h:884
size_t m_nr_backwardx
Definition line_smoothers.h:741
LineVanka(SmartPtr< ApproximationSpace< TDomain > > approxSpace)
Definition line_smoothers.h:762
~LineVanka()
Definition line_smoothers.h:807
matrix_type m_A
Definition line_smoothers.h:916
size_t m_nr_backwardy
Definition line_smoothers.h:743
size_t get_num_forwardy()
Definition line_smoothers.h:857
bool linevanka_step(const matrix_type &A, vector_type &x, const vector_type &b)
Definition line_smoothers.h:919
void set_num_steps(size_t forwardx, size_t backwardx, size_t forwardy, size_t backwardy, size_t forwardz, size_t backwardz)
Definition line_smoothers.h:812
number relax()
Definition line_smoothers.h:755
void set_relax(number omega)
set m_relaxation parameter
Definition line_smoothers.h:754
size_t m_nr_forwardy
Definition line_smoothers.h:742
static const CommonLocalDoFSet & get_dofs(const LFEID &id, bool bCreate=true)
returns the common dof set for all reference objects of a dimension
Definition local_finite_element_provider.cpp:730
a mathematical Vector with N entries.
Definition math_vector.h:97
Definition grid_base_object_traits.h:68
@ PST_UNIQUE
Definition parallel_storage_type.h:70
void SetDirichletRow(TSparseMatrix &A, size_t i, size_t alpha)
Definition sparsematrix_util.h:796
void CollectEdgesSorted(vector< Edge * > &vEdgesOut, Grid &grid, Vertex *v, bool clearContainer)
Collects all edges of a vertex, thus, none.
Definition grid_util.cpp:205
int NumProcs()
returns the number of processes
Definition pcl_base.cpp:91
#define UG_ASSERT(expr, msg)
Definition assert.h:70
double number
Definition types.h:124
vector_t::value_type VecDistance(const vector_t &v1, const vector_t &v2)
returns the distance of two vector_ts.
Definition math_vector_functions_common_impl.hpp:375
the ug namespace
static const size_t MAXBLOCKSIZE
Definition vanka.h:47
ReferenceObjectID
these ids are used to identify the shape of a geometric object.
Definition grid_base_objects.h:74
@ NUM_REFERENCE_OBJECTS
Definition grid_base_objects.h:85
void ComputeDirectionYOrder(std::vector< std::pair< MathVector< dim >, size_t > > &vPos, std::vector< size_t > &indY)
Definition line_smoothers.h:73
void ExtractPositions(ConstSmartPtr< TDomain > domain, ConstSmartPtr< DoFDistribution > dd, std::vector< MathVector< TDomain::dim > > &vPos)
Definition dof_position_util.cpp:424
bool MakeConsistent(const ParallelMatrix< matrix_type > &_mat, ParallelMatrix< matrix_type > &newMat)
Definition parallel_matrix_overlap_impl.h:438
bool ComparePosDimYDir(const std::pair< MathVector< dim >, size_t > &p1, const std::pair< MathVector< dim >, size_t > &p2)
Definition line_smoothers.cpp:36
void OrderDirectionZForDofDist(SmartPtr< DoFDistribution > dd, ConstSmartPtr< TDomain > domain, std::vector< size_t > &indZ)
Definition line_smoothers.h:194
bool MatMultAdd(vector_t &dest, const number &alpha1, const vector_t &v1, const number &beta1, const matrix_t &A1, const vector_t &w1)
calculates dest = alpha1*v1 + beta1 * A1 *w1;
Definition operations_mat.h:68
bool ComparePosDimZDir(const std::pair< MathVector< dim >, size_t > &p1, const std::pair< MathVector< dim >, size_t > &p2)
Definition line_smoothers.cpp:82
void OrderDirectionYForDofDist(SmartPtr< DoFDistribution > dd, ConstSmartPtr< TDomain > domain, std::vector< size_t > &indY)
Definition line_smoothers.h:85
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
bool InverseMatMult(number &dest, const double &beta, const TMat &mat, const TVec &vec)
you can implement this function with GetInverse and MatMult
void collectStretchedElementIndices(ConstSmartPtr< TDomain > domain, ConstSmartPtr< DoFDistribution > dd, std::vector< size_t > &indarray, number alpha)
Definition line_smoothers.h:292
void ComputeDirectionZOrder(std::vector< std::pair< MathVector< dim >, size_t > > &vPos, std::vector< size_t > &indZ)
Definition line_smoothers.h:184
SurfaceView::traits< TElem >::const_iterator const_iterator
Definition dof_distribution.h:82