ug4
p1_continuity_constraints_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__SPATIAL_DISC__CONSTRAINTS__CONTINUITY_CONSTRAINTS__P1_CONTINUITY_CONSTRAINTS_IMPL__
34 #define __H__UG__LIB_DISC__SPATIAL_DISC__CONSTRAINTS__CONTINUITY_CONSTRAINTS__P1_CONTINUITY_CONSTRAINTS_IMPL__
35 
37 #include "lib_disc/domain.h"
38 
39 namespace ug {
40 
42 template <typename TMatrix>
43 void SetInterpolation(TMatrix& A,
44  std::vector<size_t> & constrainedIndex,
45  std::vector<std::vector<size_t> >& vConstrainingIndex,
46  bool assembleLinearProblem = true)
47 {
48  //typedef typename TMatrix::row_iterator row_iterator;
49  //typedef typename TMatrix::value_type block_type;
50 
51  // check number of indices passed
52  for(size_t i = 0; i < vConstrainingIndex.size(); ++i)
53  UG_ASSERT(vConstrainingIndex[i].size() == constrainedIndex.size(),
54  "Wrong number of indices.");
55 
56 // loop all constrained dofs
57  for(size_t i = 0; i < constrainedIndex.size(); ++i)
58  {
59  const size_t ai = constrainedIndex[i];
60 
61  // remove all couplings
62  SetRow(A, ai, 0.0);
63 
64  // set diag of row to identity
65  A(ai, ai) = 1.0;
66 
67  // set coupling to all constraining dofs the inverse of the
68  // number of constraining dofs
69  // This is only required if assembling for a linear problem.
70  if (assembleLinearProblem)
71  {
72  const number frac = -1.0/(vConstrainingIndex.size());
73  for(size_t j=0; j < vConstrainingIndex.size(); ++j)
74  A(ai, vConstrainingIndex[j][i]) = frac;
75  }
76  }
77 }
78 
79 template <typename TVector>
80 void InterpolateValues(TVector& u,
81  std::vector<size_t>& constrainedIndex,
82  std::vector<std::vector<size_t> >& vConstrainingIndex)
83 {
84  typedef typename TVector::value_type block_type;
85 
86  // check number of indices passed
87  for(size_t i = 0; i < vConstrainingIndex.size(); ++i)
88  UG_ASSERT(vConstrainingIndex[i].size() == constrainedIndex.size(),
89  "Wrong number of indices.");
90 
91 // scaling factor
92  const number frac = 1./(vConstrainingIndex.size());
93 
94 // loop constrained indices
95  for(size_t i = 0; i < constrainedIndex.size(); ++i)
96  {
97  // get value to be interpolated
98  block_type& val = u[constrainedIndex[i]];
99 
100  // reset value
101  val = 0.0;
102 
103  // add equally from all constraining indices
104  for(size_t j=0; j < vConstrainingIndex.size(); ++j)
105  VecScaleAdd(val, 1.0, val, frac, u[vConstrainingIndex[j][i]]);
106  //val += frac * u[vConstrainingIndex[j][i]];
107  }
108 }
109 
110 
111 
112 template <typename TMatrix>
113 void SplitAddRow_Symmetric(TMatrix& A,
114  std::vector<size_t>& constrainedIndex,
115  std::vector<std::vector<size_t> >& vConstrainingIndex)
116 {
117  typedef typename TMatrix::value_type block_type;
118  typedef typename TMatrix::row_iterator row_iterator;
119 
120  size_t nConstrg = vConstrainingIndex.size();
121  UG_ASSERT(nConstrg, "There have to be constraining indices!");
122 
123  // check number of indices passed
124  for(size_t i = 0; i < nConstrg; ++i)
125  UG_ASSERT(vConstrainingIndex[i].size() == constrainedIndex.size(),
126  "Wrong number of indices.");
127 
128 // scaling factor
129  const number frac = 1.0 / nConstrg;
130 
131 // handle each constrained index
132  for(size_t i = 0; i < constrainedIndex.size(); ++i)
133  {
134  const size_t algInd = constrainedIndex[i];
135 
136  // add coupling constrained index -> constrained index
137  // we don't have to adjust the block itself, since the row of
138  // constraints will be set to interpolation afterwards
139  block_type diagEntry = A(algInd, algInd);
140 
141  // scale by weight
142  diagEntry *= frac*frac;
143 
144  // add coupling constrained dof -> constrained dof
145  for(size_t k = 0; k < vConstrainingIndex.size(); ++k)
146  for(size_t m = 0; m < vConstrainingIndex.size(); ++m)
147  A(vConstrainingIndex[k][i], vConstrainingIndex[m][i]) += diagEntry;
148 
149 #if 0
150 
151  // (handled separately as it would otherwise trigger an assert -
152  // manipulation of matrix row while iterating over it)
153  const block_type block = A(algInd, algInd);
154  size_t nBlockCols = GetCols(block);
155  UG_ASSERT(nBlockCols == constrainedIndex.size(),
156  "Number of block cols and number of constrained DoFs in hanging vertex not equal.");
157  for (size_t blockIndConn = 0; blockIndConn < nBlockCols; ++blockIndConn)
158  {
159  const number val = BlockRef(block, blockInd, blockIndConn) * frac*frac;
160  for (size_t k = 0; k < nConstrg; ++k)
161  for (size_t m = 0; m < nConstrg; ++m)
162  DoFRef(A, vConstrainingIndex[k][i], vConstrainingIndex[m][blockIndConn]) += val;
163  }
164 #endif
165 
166  // loop coupling between constrained dof -> any other dof
167  for(row_iterator conn = A.begin_row(algInd); conn != A.end_row(algInd); ++conn)
168  {
169  const size_t algIndConn = conn.index();
170 
171  // diagonal entry already handled
172  if (algIndConn == algInd)
173  continue;
174 
175  // warning: do NOT use references here!
176  // they might become invalid when A is accessed at an entry that does not exist yet
177  // FIXME: This will only work properly if there is an entry A(i,j) for any entry
178  // A(j,i) in the matrix! Is this always the case!?
179  block_type block = conn.value();
180  block_type blockT = A(algIndConn, algInd);
181 
182  // multiply the cpl value by the inverse number of constraining
183  block *= frac;
184  blockT *= frac;
185 
186  // add the coupling to the constraining indices rows
187  for (size_t k = 0; k < nConstrg; ++k)
188  {
189  UG_ASSERT(vConstrainingIndex[k][i] != constrainedIndex[i],
190  "Modifying 'this' (=conn referenced) matrix row is invalid!" << constrainedIndex[i]);
191  A(vConstrainingIndex[k][i], algIndConn) += block;
192  A(algIndConn, vConstrainingIndex[k][i]) += blockT;
193  }
194 
195  // set the split coupling to zero
196  // this needs to be done only in columns, since the row associated to
197  // the constrained index will be set to unity (or interpolation).
198  A(algIndConn, algInd) = 0.0;
199  }
200  }
201 }
202 
203 template <typename TMatrix>
204 void SplitAddRow_OneSide(TMatrix& A,
205  std::vector<size_t>& constrainedIndex,
206  std::vector<std::vector<size_t> >& vConstrainingIndex)
207 {
208  typedef typename TMatrix::value_type block_type;
209  typedef typename TMatrix::row_iterator row_iterator;
210 
211  UG_ASSERT(!vConstrainingIndex.empty(), "There have to be constraining indices!");
212 
213  // check number of indices passed
214  for(size_t i = 0; i < vConstrainingIndex.size(); ++i)
215  UG_ASSERT(vConstrainingIndex[i].size() == constrainedIndex.size(),
216  "Wrong number of indices.");
217 
218 // scaling factor
219  const number frac = 1./(vConstrainingIndex.size());
220 
221  for(size_t i = 0; i < constrainedIndex.size(); ++i)
222  {
223  const size_t algInd = constrainedIndex[i];
224 
225  // choose randomly the first dof to add whole row
226  const size_t addTo = vConstrainingIndex[0][i];
227 
228  block_type diagEntry = A(algInd, algInd);
229 
230  // scale by weight
231  diagEntry *= frac;
232 
233  // add coupling
234  for(size_t k = 0; k < vConstrainingIndex.size(); ++k)
235  A(addTo, vConstrainingIndex[k][i]) += diagEntry;
236 
237  // loop coupling between constrained dof -> any other dof
238  for(row_iterator conn = A.begin_row(algInd); conn != A.end_row(algInd); ++conn)
239  {
240  const size_t algIndConn = conn.index();
241 
242  // skip self-coupling (already handled)
243  if (algIndConn == algInd) continue;
244 
245  // warning: do NOT use references here!
246  // they might become invalid when A is accessed at an entry that does not exist yet
247  // FIXME: This will only work properly if there is an entry A(i,j) for any entry
248  // A(j,i) in the matrix! Is this always the case!?
249  const block_type block = conn.value();
250  block_type blockT = A(algIndConn, algInd);
251 
252  blockT *= frac;
253 
254  // add the coupling to the constraining indices rows
255  for(size_t k = 0; k < vConstrainingIndex.size(); ++k)
256  A(algIndConn, vConstrainingIndex[k][i]) += blockT;
257 
258  // coupling due to one side adding
259  A(addTo, algIndConn) += block;
260 
261  // set the split coupling to zero
262  // this must only be done in columns, since the row associated to
263  // the constrained index will be set to an interpolation.
264  A(algIndConn, algInd) = 0.0;
265  }
266  }
267 }
268 
269 template <typename TVector>
270 void SplitAddRhs_Symmetric(TVector& rhs,
271  std::vector<size_t> & constrainedIndex,
272  std::vector<std::vector<size_t> >& vConstrainingIndex)
273 {
274  typedef typename TVector::value_type block_type;
275 
276  // check number of indices passed
277  for(size_t i = 0; i < vConstrainingIndex.size(); ++i)
278  UG_ASSERT(vConstrainingIndex[i].size() == constrainedIndex.size(),
279  "Wrong number of indices.");
280 
281 // scaling factor
282  const number frac = 1./(vConstrainingIndex.size());
283 
284 // loop constrained indices
285  for(size_t i = 0; i < constrainedIndex.size(); ++i)
286  {
287  // get constrained rhs
288  // modify block directly since set to zero afterwards
289  block_type& val = rhs[constrainedIndex[i]];
290  val *= frac;
291 
292  // split equally on all constraining indices
293  for(size_t j=0; j < vConstrainingIndex.size(); ++j)
294  rhs[vConstrainingIndex[j][i]] += val;
295 
296  // set rhs to zero for constrained index
297  val = 0.0;
298  }
299 }
300 
301 template <typename TVector>
302 void SplitAddRhs_OneSide(TVector& rhs,
303  std::vector<size_t> & constrainedIndex,
304  std::vector<std::vector<size_t> >& vConstrainingIndex)
305 {
306  typedef typename TVector::value_type block_type;
307 
308  // check number of indices passed
309  for(size_t i = 0; i < vConstrainingIndex.size(); ++i)
310  UG_ASSERT(vConstrainingIndex[i].size() == constrainedIndex.size(),
311  "Wrong number of indices.");
312 
313  for(size_t i = 0; i < constrainedIndex.size(); ++i)
314  {
315  // choose randomly the first dof to add whole
316  // (must be the same as for row)
317  const size_t addTo = vConstrainingIndex[0][i];
318 
319  block_type& val = rhs[constrainedIndex[i]];
320  rhs[addTo] += val;
321  val = 0.0;
322  }
323 }
324 
325 
336  ConstrainedVertex* hgVrt,
337  std::vector<Vertex*>& vConstrainingVrt,
338  std::vector<size_t>& constrainedInd,
339  std::vector<std::vector<size_t> >& vConstrainingInd)
340 {
341 // get subset index
342  const int si = dd->subset_handler()->get_subset_index(hgVrt);
343 
344 // get constraining vertices
345  CollectConstraining(vConstrainingVrt, *dd->multi_grid(), hgVrt);
346 
347 // clear constrainedInd
348  constrainedInd.clear();
349 
350 // resize constraining indices
351  vConstrainingInd.clear();
352  vConstrainingInd.resize(vConstrainingVrt.size());
353 
354  if (dd->grouped()) // block algebra (assuming constrainers have exactly the same functions as constrained)
355  {
356  // get indices for constrained vertex
357  dd->inner_algebra_indices(hgVrt, constrainedInd, false);
358 
359  // get indices for constraining vertices
360  for (size_t i = 0; i < vConstrainingVrt.size(); ++i)
361  dd->inner_algebra_indices(vConstrainingVrt[i], vConstrainingInd[i], false);
362  }
363  else // scalar algebra
364  {
365  // get algebra indices for constrained and constraining vertices
366  for (size_t fct = 0; fct < dd->num_fct(); ++fct)
367  {
368  // check that function is defined on subset
369  if (!dd->is_def_in_subset(fct, si)) continue;
370 
371  // get indices for constrained vertex
372  dd->inner_algebra_indices_for_fct(hgVrt, constrainedInd, false, fct);
373 
374  // get indices for constraining vertices
375  for (size_t i = 0; i < vConstrainingVrt.size(); ++i)
376  {
377  const int siC = dd->subset_handler()->get_subset_index(vConstrainingVrt[i]);
378 
379  // check that function is defined on subset
380  UG_COND_THROW(!dd->is_def_in_subset(fct, siC),
381  "Function " << fct << " is defined for a constrained vertex, "
382  "but not for one of its constraining vertices!");
383 
384  dd->inner_algebra_indices_for_fct(vConstrainingVrt[i], vConstrainingInd[i], false, fct);
385  }
386  }
387  }
388 }
389 
392 // Sym P1 Constraints
395 
396 template <typename TDomain, typename TAlgebra>
397 void
400  ConstSmartPtr<DoFDistribution> dd, int type, number time,
402  const std::vector<number>* vScaleMass,
403  const std::vector<number>* vScaleStiff)
404 {
405  if(this->m_spAssTuner->single_index_assembling_enabled())
406  UG_THROW("index-wise assemble routine is not "
407  "implemented for SymP1Constraints \n");
408 
409 // storage for indices and vertices
410  std::vector<std::vector<size_t> > vConstrainingInd;
411  std::vector<size_t> constrainedInd;
412  std::vector<Vertex*> vConstrainingVrt;
413 
414 // get begin end of hanging vertices
416  iter = dd->begin<ConstrainedVertex>();
417  iterEnd = dd->end<ConstrainedVertex>();
418 
419 // loop constrained vertices
420  for(; iter != iterEnd; ++iter)
421  {
422  // get hanging vert
423  ConstrainedVertex* hgVrt = *iter;
424 
425  // get algebra indices for constrained and constraining vertices
426  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
427 
428  // adapt rhs
429  SplitAddRhs_Symmetric(d, constrainedInd, vConstrainingInd);
430  }
431 }
432 
433 
434 template <typename TDomain, typename TAlgebra>
435 void
437 adjust_rhs(vector_type& rhs, const vector_type& u,
438  ConstSmartPtr<DoFDistribution> dd, int type, number time)
439 {
440  if(this->m_spAssTuner->single_index_assembling_enabled())
441  UG_THROW("index-wise assemble routine is not "
442  "implemented for SymP1Constraints \n");
443 
444 // storage for indices and vertices
445  std::vector<std::vector<size_t> > vConstrainingInd;
446  std::vector<size_t> constrainedInd;
447  std::vector<Vertex*> vConstrainingVrt;
448 
449 // get begin end of hanging vertices
451  iter = dd->begin<ConstrainedVertex>();
452  iterEnd = dd->end<ConstrainedVertex>();
453 
454 // loop constrained vertices
455  for(; iter != iterEnd; ++iter)
456  {
457  // get hanging vert
458  ConstrainedVertex* hgVrt = *iter;
459 
460  // get algebra indices for constrained and constraining vertices
461  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
462 
463  // adapt rhs
464  SplitAddRhs_Symmetric(rhs, constrainedInd, vConstrainingInd);
465  }
466 }
467 
468 template <typename TDomain, typename TAlgebra>
469 void
472  ConstSmartPtr<DoFDistribution> dd, int type, number time,
474  const number s_a0)
475 {
476  if(this->m_spAssTuner->single_index_assembling_enabled())
477  UG_THROW("index-wise assemble routine is not "
478  "implemented for SymP1Constraints \n");
479 
480 // storage for indices and vertices
481  std::vector<std::vector<size_t> > vConstrainingInd;
482  std::vector<size_t> constrainedInd;
483  std::vector<Vertex*> vConstrainingVrt;
484 
485 // get begin end of hanging vertices
487  iter = dd->begin<ConstrainedVertex>();
488  iterEnd = dd->end<ConstrainedVertex>();
489 
490 // loop constrained vertices
491  for(; iter != iterEnd; ++iter)
492  {
493  // get hanging vert
494  ConstrainedVertex* hgVrt = *iter;
495 
496  // get algebra indices for constrained and constraining vertices
497  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
498 
499  // Split using indices
500  SplitAddRow_Symmetric(J, constrainedInd, vConstrainingInd);
501 
502  // set interpolation
503  SetInterpolation(J, constrainedInd, vConstrainingInd, m_bAssembleLinearProblem);
504  }
505 }
506 
507 template <typename TDomain, typename TAlgebra>
508 void
511  ConstSmartPtr<DoFDistribution> dd, int type, number time)
512 {
513  m_bAssembleLinearProblem = true;
514 
515  if(this->m_spAssTuner->single_index_assembling_enabled())
516  UG_THROW("index-wise assemble routine is not "
517  "implemented for SymP1Constraints \n");
518 
519 // storage for indices and vertices
520  std::vector<std::vector<size_t> > vConstrainingInd;
521  std::vector<size_t> constrainedInd;
522  std::vector<Vertex*> vConstrainingVrt;
523 
524 // get begin end of hanging vertices
526  iter = dd->begin<ConstrainedVertex>();
527  iterEnd = dd->end<ConstrainedVertex>();
528 
529 // loop constrained vertices
530  for(; iter != iterEnd; ++iter)
531  {
532  // get hanging vert
533  ConstrainedVertex* hgVrt = *iter;
534 
535  // get algebra indices for constrained and constraining vertices
536  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
537 
538  // Split using indices
539  SplitAddRow_Symmetric(mat, constrainedInd, vConstrainingInd);
540 
541  // set interpolation
542  SetInterpolation(mat, constrainedInd, vConstrainingInd, true);
543 
544  // adapt rhs
545  SplitAddRhs_Symmetric(rhs, constrainedInd, vConstrainingInd);
546  }
547 }
548 
549 template <typename TDomain, typename TAlgebra>
550 void
553  int type, number time)
554 {
555  if(this->m_spAssTuner->single_index_assembling_enabled())
556  UG_THROW("index-wise assemble routine is not "
557  "implemented for SymP1Constraints \n");
558 
559 // storage for indices and vertices
560  std::vector<std::vector<size_t> > vConstrainingInd;
561  std::vector<size_t> constrainedInd;
562  std::vector<Vertex*> vConstrainingVrt;
563 
564 // get begin end of hanging vertices
566  iter = dd->begin<ConstrainedVertex>();
567  iterEnd = dd->end<ConstrainedVertex>();
568 
569 // loop constraining edges
570  for(; iter != iterEnd; ++iter)
571  {
572  // get hanging vert
573  ConstrainedVertex* hgVrt = *iter;
574 
575  // get algebra indices for constrained and constraining vertices
576  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
577 
578  // Interpolate values
579  InterpolateValues(u, constrainedInd, vConstrainingInd);
580  }
581 }
582 
583 
584 template <typename TDomain, typename TAlgebra>
585 void
588 (
589  matrix_type& P,
592  int type,
593  number time
594 )
595 {
596  if (m_bAssembleLinearProblem) return;
597 
598  if (this->m_spAssTuner->single_index_assembling_enabled())
599  UG_THROW("index-wise assemble routine is not "
600  "implemented for SymP1Constraints \n");
601 
602 // storage for indices and vertices
603  std::vector<std::vector<size_t> > vConstrainingInd;
604  std::vector<size_t> constrainedInd;
605  std::vector<Vertex*> vConstrainingVrt;
606 
607 // get begin end of hanging vertices
609  iter = ddFine->begin<ConstrainedVertex>();
610  iterEnd = ddFine->end<ConstrainedVertex>();
611 
612 // loop constrained vertices
613  for(; iter != iterEnd; ++iter)
614  {
615  // get hanging vert
616  ConstrainedVertex* hgVrt = *iter;
617 
618  // get algebra indices for constrained and constraining vertices
619  get_algebra_indices(ddFine, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
620 
621  // set zero row
622  size_t sz = constrainedInd.size();
623  for (size_t i = 0; i < sz; ++i)
624  SetRow(P, constrainedInd[i], 0.0);
625  }
626 }
627 
628 
629 template <typename TDomain, typename TAlgebra>
630 void
633 (
634  matrix_type& R,
637  int type,
638  number time
639 )
640 {
641 
642 }
643 
644 
645 
646 template <typename TDomain, typename TAlgebra>
647 void
650 ( vector_type& u,
652  int type,
653  number time
654 )
655 {
656  //typedef typename vector_type::value_type block_type;
657 
658  if (this->m_spAssTuner->single_index_assembling_enabled())
659  UG_THROW("index-wise assemble routine is not "
660  "implemented for OneSideP1Constraints \n");
661 
662  // storage for indices and vertices
663  std::vector<std::vector<size_t> > vConstrainingInd;
664  std::vector<size_t> constrainedInd;
665  std::vector<Vertex*> vConstrainingVrt;
666 
667  // get begin end of hanging vertices
669  iter = dd->begin<ConstrainedVertex>();
670  iterEnd = dd->end<ConstrainedVertex>();
671 
672  // loop constrained vertices
673  for (; iter != iterEnd; ++iter)
674  {
675  // get hanging vert
676  ConstrainedVertex* hgVrt = *iter;
677 
678  // get algebra indices for constrained and constraining vertices
679  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
680 
681  // set all entries corresponding to constrained dofs to zero
682  for (size_t i = 0; i < constrainedInd.size(); ++i)
683  u[constrainedInd[i]] = 0.0;
684  }
685 }
686 
687 
690 // OneSide P1 Constraints
693 
694 template<int dim>
696 
698  : m_aaPos(spDomain->position_accessor())
699  {}
700 
701  inline bool operator() (Vertex* vrt1, Vertex* vrt2)
702  {UG_THROW(dim <<" not implemented.");}
703 
704  protected:
706 };
707 
708 template<>
709 inline bool SortVertexPos<1>::operator() (Vertex* vrt1, Vertex* vrt2)
710 {
711  if(m_aaPos[vrt1][0] < m_aaPos[vrt2][0]) {
712  return true;
713  }
714  return false;
715 }
716 
717 template<>
718 inline bool SortVertexPos<2>::operator() (Vertex* vrt1, Vertex* vrt2)
719 {
720  if(m_aaPos[vrt1][0] < m_aaPos[vrt2][0]) {
721  return true;
722  }
723  else if(m_aaPos[vrt1][0] == m_aaPos[vrt2][0]) {
724  if(m_aaPos[vrt1][1] < m_aaPos[vrt2][1])
725  return true;
726  }
727  return false;
728 }
729 
730 template<>
731 inline bool SortVertexPos<3>::operator() (Vertex* vrt1, Vertex* vrt2)
732 {
733  if(m_aaPos[vrt1][0] < m_aaPos[vrt2][0]) {
734  return true;
735  }
736  else if(m_aaPos[vrt1][0] == m_aaPos[vrt2][0]) {
737  if(m_aaPos[vrt1][1] < m_aaPos[vrt2][1]){
738  return true;
739  }
740  else if(m_aaPos[vrt1][1] == m_aaPos[vrt2][1]){
741  if(m_aaPos[vrt1][2] < m_aaPos[vrt2][2])
742  return true;
743  }
744  return false;
745  }
746  return false;
747 }
748 
749 
764 template <typename TDomain>
766  ConstrainedVertex* hgVrt,
767  std::vector<Vertex*>& vConstrainingVrt,
768  std::vector<size_t>& constrainedInd,
769  std::vector<std::vector<size_t> >& vConstrainingInd,
770  const SortVertexPos<TDomain::dim>& sortVertexPos)
771 {
772 // get subset index
773  const int si = dd->subset_handler()->get_subset_index(hgVrt);
774 
775 // get constraining vertices
776  CollectConstraining(vConstrainingVrt, *dd->multi_grid(), hgVrt);
777 
778 #ifdef UG_PARALLEL
779  std::sort(vConstrainingVrt.begin(), vConstrainingVrt.end(), sortVertexPos);
780 #endif
781 
782 // clear constrainedInd
783  constrainedInd.clear();
784 
785 // resize constraining indices
786  vConstrainingInd.clear();
787  vConstrainingInd.resize(vConstrainingVrt.size());
788 
789 // get algebra indices for constrained and constraining vertices
790  if (dd->grouped()) // block algebra (assuming constrainers have exactly the same functions as constrained)
791  {
792  // get indices for constrained vertex
793  dd->inner_algebra_indices(hgVrt, constrainedInd, false);
794 
795  // get indices for constraining vertices
796  for (size_t i = 0; i < vConstrainingVrt.size(); ++i)
797  dd->inner_algebra_indices(vConstrainingVrt[i], vConstrainingInd[i], false);
798  }
799  else // scalar algebra
800  {
801  for (size_t fct = 0; fct < dd->num_fct(); fct++)
802  {
803  // check that function is defined on subset
804  if (!dd->is_def_in_subset(fct, si)) continue;
805 
806  // get indices for constrained vertex
807  dd->inner_algebra_indices_for_fct(hgVrt, constrainedInd, false, fct);
808 
809  // get indices for constraining vertices
810  for (size_t i = 0; i < vConstrainingVrt.size(); ++i)
811  {
812  const int siC = dd->subset_handler()->get_subset_index(vConstrainingVrt[i]);
813 
814  // check that function is defined on subset
815  UG_COND_THROW(!dd->is_def_in_subset(fct, siC),
816  "Function " << fct << " is defined for a constrained vertex, "
817  "but not for one of its constraining vertices!");
818 
819  dd->inner_algebra_indices_for_fct(vConstrainingVrt[i], vConstrainingInd[i], false, fct);
820  }
821  }
822  }
823 }
824 
825 
826 template <typename TDomain, typename TAlgebra>
827 void
830  ConstSmartPtr<DoFDistribution> dd, int type, number time,
832  const std::vector<number>* vScaleMass,
833  const std::vector<number>* vScaleStiff)
834 {
835  if(this->m_spAssTuner->single_index_assembling_enabled())
836  UG_THROW("index-wise assemble routine is not "
837  "implemented for OneSideP1Constraints \n");
838 
839 // storage for indices and vertices
840  std::vector<std::vector<size_t> > vConstrainingInd;
841  std::vector<size_t> constrainedInd;
842  std::vector<Vertex*> vConstrainingVrt;
843 
844 #ifdef UG_PARALLEL
845  SortVertexPos<TDomain::dim> sortVertexPos(this->approximation_space()->domain());
846 #endif
847 
848 // get begin end of hanging vertices
850  iter = dd->begin<ConstrainedVertex>();
851  iterEnd = dd->end<ConstrainedVertex>();
852 
853 // loop constrained vertices
854  for(; iter != iterEnd; ++iter)
855  {
856  // get hanging vert
857  ConstrainedVertex* hgVrt = *iter;
858 
859  // get algebra indices for constrained and constraining vertices
860 #ifdef UG_PARALLEL
861  get_algebra_indices<TDomain>(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd, sortVertexPos);
862 #else
863  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
864 #endif
865 
866  // adapt rhs
867  SplitAddRhs_OneSide(d, constrainedInd, vConstrainingInd);
868  }
869 }
870 
871 
872 template <typename TDomain, typename TAlgebra>
873 void
875 adjust_rhs(vector_type& rhs, const vector_type& u,
876  ConstSmartPtr<DoFDistribution> dd, int type, number time)
877 {
878  if(this->m_spAssTuner->single_index_assembling_enabled())
879  UG_THROW("index-wise assemble routine is not "
880  "implemented for OneSideP1Constraints \n");
881 
882 // storage for indices and vertices
883  std::vector<std::vector<size_t> > vConstrainingInd;
884  std::vector<size_t> constrainedInd;
885  std::vector<Vertex*> vConstrainingVrt;
886 
887 #ifdef UG_PARALLEL
888  SortVertexPos<TDomain::dim> sortVertexPos(this->approximation_space()->domain());
889 #endif
890 
891 // get begin end of hanging vertices
893  iter = dd->begin<ConstrainedVertex>();
894  iterEnd = dd->end<ConstrainedVertex>();
895 
896 // loop constrained vertices
897  for(; iter != iterEnd; ++iter)
898  {
899  // get hanging vert
900  ConstrainedVertex* hgVrt = *iter;
901 
902  // get algebra indices for constrained and constraining vertices
903 #ifdef UG_PARALLEL
904  get_algebra_indices<TDomain>(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd, sortVertexPos);
905 #else
906  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
907 #endif
908 
909  // adapt rhs
910  SplitAddRhs_OneSide(rhs, constrainedInd, vConstrainingInd);
911  }
912 }
913 
914 template <typename TDomain, typename TAlgebra>
915 void
918  ConstSmartPtr<DoFDistribution> dd, int type, number time,
920  const number s_a0)
921 {
922  if(this->m_spAssTuner->single_index_assembling_enabled())
923  UG_THROW("index-wise assemble routine is not "
924  "implemented for OneSideP1Constraints \n");
925 
926 // storage for indices and vertices
927  std::vector<std::vector<size_t> > vConstrainingInd;
928  std::vector<size_t> constrainedInd;
929  std::vector<Vertex*> vConstrainingVrt;
930 
931 #ifdef UG_PARALLEL
932  SortVertexPos<TDomain::dim> sortVertexPos(this->approximation_space()->domain());
933 #endif
934 
935 // get begin end of hanging vertices
937  iter = dd->begin<ConstrainedVertex>();
938  iterEnd = dd->end<ConstrainedVertex>();
939 
940 // loop constrained vertices
941  for(; iter != iterEnd; ++iter)
942  {
943  // get hanging vert
944  ConstrainedVertex* hgVrt = *iter;
945 
946  // get algebra indices for constrained and constraining vertices
947 #ifdef UG_PARALLEL
948  get_algebra_indices<TDomain>(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd, sortVertexPos);
949 #else
950  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
951 #endif
952 
953  // Split using indices
954  SplitAddRow_OneSide(J, constrainedInd, vConstrainingInd);
955 
956  // set interpolation
957  SetInterpolation(J, constrainedInd, vConstrainingInd, m_bAssembleLinearProblem);
958  }
959 }
960 
961 template <typename TDomain, typename TAlgebra>
962 void
965  ConstSmartPtr<DoFDistribution> dd, int type, number time)
966 {
967  m_bAssembleLinearProblem = true;
968 
969  if(this->m_spAssTuner->single_index_assembling_enabled())
970  UG_THROW("index-wise assemble routine is not "
971  "implemented for OneSideP1Constraints \n");
972 
973 // storage for indices and vertices
974  std::vector<std::vector<size_t> > vConstrainingInd;
975  std::vector<size_t> constrainedInd;
976  std::vector<Vertex*> vConstrainingVrt;
977 
978 #ifdef UG_PARALLEL
979  SortVertexPos<TDomain::dim> sortVertexPos(this->approximation_space()->domain());
980 #endif
981 
982 // get begin end of hanging vertices
984  iter = dd->begin<ConstrainedVertex>();
985  iterEnd = dd->end<ConstrainedVertex>();
986 
987 // loop constraining edges
988  for(; iter != iterEnd; ++iter)
989  {
990  // get hanging vert
991  ConstrainedVertex* hgVrt = *iter;
992 
993  // get algebra indices for constrained and constraining vertices
994 #ifdef UG_PARALLEL
995  get_algebra_indices<TDomain>(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd, sortVertexPos);
996 #else
997  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
998 #endif
999 
1000  // Split using indices
1001  SplitAddRow_OneSide(mat, constrainedInd, vConstrainingInd);
1002 
1003  // Set interpolation
1004  SetInterpolation(mat, constrainedInd, vConstrainingInd, true);
1005 
1006  // adapt rhs
1007  SplitAddRhs_OneSide(rhs, constrainedInd, vConstrainingInd);
1008  }
1009 }
1010 
1011 template <typename TDomain, typename TAlgebra>
1012 void
1015  int type, number time)
1016 {
1017  if(this->m_spAssTuner->single_index_assembling_enabled())
1018  UG_THROW("index-wise assemble routine is not "
1019  "implemented for OneSideP1Constraints \n");
1020 
1021 // storage for indices and vertices
1022  std::vector<std::vector<size_t> > vConstrainingInd;
1023  std::vector<size_t> constrainedInd;
1024  std::vector<Vertex*> vConstrainingVrt;
1025 
1026 // get begin end of hanging vertices
1028  iter = dd->begin<ConstrainedVertex>();
1029  iterEnd = dd->end<ConstrainedVertex>();
1030 
1031 // loop constraining edges
1032  for(; iter != iterEnd; ++iter)
1033  {
1034  // get hanging vert
1035  ConstrainedVertex* hgVrt = *iter;
1036 
1037  // get algebra indices for constrained and constraining vertices
1038  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
1039 
1040  // Interpolate values
1041  InterpolateValues(u, constrainedInd, vConstrainingInd);
1042  }
1043 }
1044 
1045 
1046 
1047 template <typename TDomain, typename TAlgebra>
1048 void
1051 (
1052  matrix_type& P,
1055  int type,
1056  number time
1057 )
1058 {
1059  if (m_bAssembleLinearProblem) return;
1060 
1061  if (this->m_spAssTuner->single_index_assembling_enabled())
1062  UG_THROW("index-wise assemble routine is not "
1063  "implemented for SymP1Constraints \n");
1064 
1065 // storage for indices and vertices
1066  std::vector<std::vector<size_t> > vConstrainingInd;
1067  std::vector<size_t> constrainedInd;
1068  std::vector<Vertex*> vConstrainingVrt;
1069 
1070 // get begin end of hanging vertices
1072  iter = ddFine->begin<ConstrainedVertex>();
1073  iterEnd = ddFine->end<ConstrainedVertex>();
1074 
1075 // loop constrained vertices
1076  for(; iter != iterEnd; ++iter)
1077  {
1078  // get hanging vert
1079  ConstrainedVertex* hgVrt = *iter;
1080 
1081  // get algebra indices for constrained and constraining vertices
1082  get_algebra_indices(ddFine, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
1083 
1084  // set zero row
1085  size_t sz = constrainedInd.size();
1086  for (size_t i = 0; i < sz; ++i)
1087  SetRow(P, constrainedInd[i], 0.0);
1088  }
1089 }
1090 
1091 
1092 template <typename TDomain, typename TAlgebra>
1093 void
1096 (
1097  matrix_type& R,
1100  int type,
1101  number time
1102 )
1103 {}
1104 
1105 
1106 
1107 
1108 template <typename TDomain, typename TAlgebra>
1109 void
1112 ( vector_type& u,
1114  int type,
1115  number time
1116 )
1117 {
1118  //typedef typename vector_type::value_type block_type;
1119 
1120  if (this->m_spAssTuner->single_index_assembling_enabled())
1121  UG_THROW("index-wise assemble routine is not "
1122  "implemented for OneSideP1Constraints \n");
1123 
1124  // storage for indices and vertices
1125  std::vector<std::vector<size_t> > vConstrainingInd;
1126  std::vector<size_t> constrainedInd;
1127  std::vector<Vertex*> vConstrainingVrt;
1128 
1129  // get begin end of hanging vertices
1131  iter = dd->begin<ConstrainedVertex>();
1132  iterEnd = dd->end<ConstrainedVertex>();
1133 
1134  // loop constrained vertices
1135  for (; iter != iterEnd; ++iter)
1136  {
1137  // get hanging vert
1138  ConstrainedVertex* hgVrt = *iter;
1139 
1140  // get algebra indices for constrained and constraining vertices
1141  get_algebra_indices(dd, hgVrt, vConstrainingVrt, constrainedInd, vConstrainingInd);
1142 
1143  // set all entries corresponding to constrained dofs to zero
1144  for (size_t i = 0; i < constrainedInd.size(); ++i)
1145  u[constrainedInd[i]] = 0.0;
1146  }
1147 }
1148 
1149 
1150 }; // namespace ug
1151 
1152 
1153 
1154 #endif /* __H__UG__LIB_DISC__SPATIAL_DISC__CONSTRAINTS__CONTINUITY_CONSTRAINTS__P1_CONTINUITY_CONSTRAINTS_IMPL__ */
Definition: smart_pointer.h:296
Definition: smart_pointer.h:108
A vertex appearing on edges or faces.
Definition: grid_objects_0d.h:110
Definition: domain.h:287
algebra_type::vector_type vector_type
Type of algebra vector.
Definition: constraint_interface.h:72
algebra_type::matrix_type matrix_type
Type of algebra matrix.
Definition: constraint_interface.h:69
void adjust_jacobian(matrix_type &J, const vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0, ConstSmartPtr< VectorTimeSeries< vector_type > > vSol=NULL, const number s_a0=1.0)
adapts jacobian to enforce constraints
Definition: p1_continuity_constraints_impl.h:917
virtual void adjust_correction(vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0)
Definition: p1_continuity_constraints_impl.h:1112
void adjust_prolongation(matrix_type &P, ConstSmartPtr< DoFDistribution > ddFine, ConstSmartPtr< DoFDistribution > ddCoarse, int type, number time=0.0)
sets constraints in prolongation
Definition: p1_continuity_constraints_impl.h:1051
void adjust_rhs(vector_type &rhs, const vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0)
adapts a rhs to enforce constraints
Definition: p1_continuity_constraints_impl.h:875
void adjust_solution(vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0)
sets the constraints in a solution vector
Definition: p1_continuity_constraints_impl.h:1014
void adjust_defect(vector_type &d, const vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0, ConstSmartPtr< VectorTimeSeries< vector_type > > vSol=NULL, const std::vector< number > *vScaleMass=NULL, const std::vector< number > *vScaleStiff=NULL)
adapts defect to enforce constraints
Definition: p1_continuity_constraints_impl.h:829
void adjust_restriction(matrix_type &R, ConstSmartPtr< DoFDistribution > ddCoarse, ConstSmartPtr< DoFDistribution > ddFine, int type, number time=0.0)
sets constraints in restriction
Definition: p1_continuity_constraints_impl.h:1096
void adjust_linear(matrix_type &mat, vector_type &rhs, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0)
adapts matrix and rhs (linear case) to enforce constraints
Definition: p1_continuity_constraints_impl.h:964
Const iterator to traverse the surface of a multi-grid hierarchy.
Definition: surface_view.h:237
void adjust_defect(vector_type &d, const vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0, ConstSmartPtr< VectorTimeSeries< vector_type > > vSol=NULL, const std::vector< number > *vScaleMass=NULL, const std::vector< number > *vScaleStiff=NULL)
adapts defect to enforce constraints
Definition: p1_continuity_constraints_impl.h:399
void adjust_prolongation(matrix_type &P, ConstSmartPtr< DoFDistribution > ddFine, ConstSmartPtr< DoFDistribution > ddCoarse, int type, number time=0.0)
sets constraints in prolongation
Definition: p1_continuity_constraints_impl.h:588
void adjust_restriction(matrix_type &R, ConstSmartPtr< DoFDistribution > ddCoarse, ConstSmartPtr< DoFDistribution > ddFine, int type, number time=0.0)
sets constraints in restriction
Definition: p1_continuity_constraints_impl.h:633
void adjust_rhs(vector_type &rhs, const vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0)
adapts a rhs to enforce constraints
Definition: p1_continuity_constraints_impl.h:437
void adjust_jacobian(matrix_type &J, const vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0, ConstSmartPtr< VectorTimeSeries< vector_type > > vSol=NULL, const number s_a0=1.0)
adapts jacobian to enforce constraints
Definition: p1_continuity_constraints_impl.h:471
virtual void adjust_correction(vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0)
Definition: p1_continuity_constraints_impl.h:650
void adjust_linear(matrix_type &mat, vector_type &rhs, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0)
adapts matrix and rhs (linear case) to enforce constraints
Definition: p1_continuity_constraints_impl.h:510
void adjust_solution(vector_type &u, ConstSmartPtr< DoFDistribution > dd, int type, number time=0.0)
sets the constraints in a solution vector
Definition: p1_continuity_constraints_impl.h:552
time series of solutions and corresponding time point
Definition: solution_time_series.h:59
Base-class for all vertex-types.
Definition: grid_base_objects.h:231
void SetRow(TSparseMatrix &A, size_t i, size_t alpha, number val=0.0)
Definition: sparsematrix_util.h:710
static const int dim
#define UG_ASSERT(expr, msg)
Definition: assert.h:70
#define UG_THROW(msg)
Definition: error.h:57
#define UG_COND_THROW(cond, msg)
UG_COND_THROW(cond, msg) : performs a UG_THROW(msg) if cond == true.
Definition: error.h:61
double number
Definition: types.h:124
void VecScaleAdd(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1, typename vector_t::value_type s2, const vector_t &v2)
Scales two Vectors, adds them and returns the sum in a third vector.
Definition: math_vector_functions_common_impl.hpp:265
parameterNumber frac
the ug namespace
size_t GetCols(const T &t)
number & DoFRef(TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
Definition: multi_index.h:276
void SetInterpolation(TMatrix &A, std::vector< size_t > &constrainedIndex, std::vector< std::vector< size_t > > &vConstrainingIndex, bool assembleLinearProblem=true)
sets a matrix row corresponding to averaging the constrained index
Definition: p1_continuity_constraints_impl.h:43
void InterpolateValues(TVector &u, std::vector< size_t > &constrainedIndex, std::vector< std::vector< size_t > > &vConstrainingIndex)
Definition: p1_continuity_constraints_impl.h:80
void SplitAddRhs_OneSide(TVector &rhs, std::vector< size_t > &constrainedIndex, std::vector< std::vector< size_t > > &vConstrainingIndex)
Definition: p1_continuity_constraints_impl.h:302
double & BlockRef(T &vec, size_t i)
Definition: blocks.h:66
void SplitAddRow_Symmetric(TMatrix &A, std::vector< size_t > &constrainedIndex, std::vector< std::vector< size_t > > &vConstrainingIndex)
Definition: p1_continuity_constraints_impl.h:113
void get_algebra_indices(ConstSmartPtr< DoFDistribution > dd, ConstrainedVertex *hgVrt, std::vector< Vertex * > &vConstrainingVrt, std::vector< size_t > &constrainedInd, std::vector< std::vector< size_t > > &vConstrainingInd)
Extract algebra indices for constrained and constraining indices from DoF distribution.
Definition: p1_continuity_constraints_impl.h:335
void SplitAddRhs_Symmetric(TVector &rhs, std::vector< size_t > &constrainedIndex, std::vector< std::vector< size_t > > &vConstrainingIndex)
Definition: p1_continuity_constraints_impl.h:270
void CollectConstraining(std::vector< Vertex * > &vConstrainingVrt, const Grid &grid, ConstrainedVertex *hgVrt, bool bClearContainer)
returns the vertices of the object constraining a hanging vertex
Definition: p1_continuity_constraints.cpp:41
void SplitAddRow_OneSide(TMatrix &A, std::vector< size_t > &constrainedIndex, std::vector< std::vector< size_t > > &vConstrainingIndex)
Definition: p1_continuity_constraints_impl.h:204
T value_type
Definition: sparsematrix_interface.h:2
Definition: p1_continuity_constraints_impl.h:695
SortVertexPos(SmartPtr< Domain< dim, MultiGrid, MGSubsetHandler > > spDomain)
Definition: p1_continuity_constraints_impl.h:697
Domain< dim, MultiGrid, MGSubsetHandler >::position_accessor_type & m_aaPos
Definition: p1_continuity_constraints_impl.h:705
bool operator()(Vertex *vrt1, Vertex *vrt2)
Definition: p1_continuity_constraints_impl.h:701