dune-pdelab  2.5-dev
constraints.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 
4 #ifndef DUNE_PDELAB_CONSTRAINTS_COMMON_CONSTRAINTS_HH
5 #define DUNE_PDELAB_CONSTRAINTS_COMMON_CONSTRAINTS_HH
6 
7 #include<dune/common/exceptions.hh>
8 #include<dune/common/float_cmp.hh>
9 
17 
18 namespace Dune {
19  namespace PDELab {
20 
24 
25  namespace { // hide internals
26  // do method invocation only if class has the method
27 
28  template<typename C, bool doIt>
29  struct ConstraintsCallBoundary
30  {
31  template<typename P, typename IG, typename LFS, typename T>
32  static void boundary (const C& c, const P& p, const IG& ig, const LFS& lfs, T& trafo)
33  {
34  }
35  };
36  template<typename C, bool doIt>
37  struct ConstraintsCallProcessor
38  {
39  template<typename IG, typename LFS, typename T>
40  static void processor (const C& c, const IG& ig, const LFS& lfs, T& trafo)
41  {
42  }
43  };
44  template<typename C, bool doIt>
45  struct ConstraintsCallSkeleton
46  {
47  template<typename IG, typename LFS, typename T>
48  static void skeleton (const C& c, const IG& ig,
49  const LFS& lfs_e, const LFS& lfs_f,
50  T& trafo_e, T& trafo_f)
51  {
52  }
53  };
54  template<typename C, bool doIt>
55  struct ConstraintsCallVolume
56  {
57  template<typename P, typename EG, typename LFS, typename T>
58  static void volume (const C& c, const P&, const EG& eg, const LFS& lfs, T& trafo)
59  {
60  }
61  };
62 
63 
64  template<typename C>
65  struct ConstraintsCallBoundary<C,true>
66  {
67  template<typename P, typename IG, typename LFS, typename T>
68  static void boundary (const C& c, const P& p, const IG& ig, const LFS& lfs, T& trafo)
69  {
70  if (lfs.size())
71  c.boundary(p,ig,lfs,trafo);
72  }
73  };
74  template<typename C>
75  struct ConstraintsCallProcessor<C,true>
76  {
77  template<typename IG, typename LFS, typename T>
78  static void processor (const C& c, const IG& ig, const LFS& lfs, T& trafo)
79  {
80  if (lfs.size())
81  c.processor(ig,lfs,trafo);
82  }
83  };
84  template<typename C>
85  struct ConstraintsCallSkeleton<C,true>
86  {
87  template<typename IG, typename LFS, typename T>
88  static void skeleton (const C& c, const IG& ig,
89  const LFS& lfs_e, const LFS& lfs_f,
90  T& trafo_e, T& trafo_f)
91  {
92  if (lfs_e.size() || lfs_f.size())
93  c.skeleton(ig, lfs_e, lfs_f, trafo_e, trafo_f);
94  }
95  };
96  template<typename C>
97  struct ConstraintsCallVolume<C,true>
98  {
99  template<typename P, typename EG, typename LFS, typename T>
100  static void volume (const C& c, const P& p, const EG& eg, const LFS& lfs, T& trafo)
101  {
102  if (lfs.size())
103  c.volume(p,eg,lfs,trafo);
104  }
105  };
106 
107 
108  struct ParameterizedConstraintsBase
109  : public TypeTree::TreePairVisitor
110  {
111  // This acts as a catch-all for unsupported leaf- / non-leaf combinations in the two
112  // trees. It is necessary because otherwise, the visitor would fall back to the default
113  // implementation in TreeVisitor, which simply does nothing. The resulting bugs would
114  // probably be hell to find...
115  template<typename P, typename LFS, typename TreePath>
116  void leaf(const P& p, const LFS& lfs, TreePath treePath) const
117  {
118  static_assert((AlwaysFalse<P>::Value),
119  "unsupported combination of function and LocalFunctionSpace");
120  }
121  };
122 
123 
124  template<typename P, typename IG, typename CL>
125  struct BoundaryConstraintsForParametersLeaf
126  : public TypeTree::TreeVisitor
127  , public TypeTree::DynamicTraversal
128  {
129 
130  template<typename LFS, typename TreePath>
131  void leaf(const LFS& lfs, TreePath treePath) const
132  {
133 
134  // extract constraints type
135  typedef typename LFS::Traits::ConstraintsType C;
136 
137  // iterate over boundary, need intersection iterator
139  }
140 
141  BoundaryConstraintsForParametersLeaf(const P& p_, const IG& ig_, CL& cl_)
142  : p(p_)
143  , ig(ig_)
144  , cl(cl_)
145  {}
146 
147  const P& p;
148  const IG& ig;
149  CL& cl;
150 
151  };
152 
153 
154  template<typename IG, typename CL>
155  struct BoundaryConstraints
156  : public ParameterizedConstraintsBase
157  , public TypeTree::DynamicTraversal
158  {
159 
160  // standard case - leaf in both trees
161  template<typename P, typename LFS, typename TreePath>
162  typename std::enable_if<P::isLeaf && LFS::isLeaf>::type
163  leaf(const P& p, const LFS& lfs, TreePath treePath) const
164  {
165  // extract constraints type
166  typedef typename LFS::Traits::ConstraintsType C;
167 
168  // iterate over boundary, need intersection iterator
170  }
171 
172  // reuse constraints parameter information from p for all LFS children
173  template<typename P, typename LFS, typename TreePath>
174  typename std::enable_if<P::isLeaf && (!LFS::isLeaf)>::type
175  leaf(const P& p, const LFS& lfs, TreePath treePath) const
176  {
177  // traverse LFS tree and reuse parameter information
178  TypeTree::applyToTree(lfs,BoundaryConstraintsForParametersLeaf<P,IG,CL>(p,ig,cl));
179  }
180 
181  BoundaryConstraints(const IG& ig_, CL& cl_)
182  : ig(ig_)
183  , cl(cl_)
184  {}
185 
186  private:
187  const IG& ig;
188  CL& cl;
189 
190  };
191 
192 
193  template<typename IG, typename CL>
194  struct ProcessorConstraints
195  : public TypeTree::TreeVisitor
196  , public TypeTree::DynamicTraversal
197  {
198 
199  template<typename LFS, typename TreePath>
200  void leaf(const LFS& lfs, TreePath treePath) const
201  {
202  // extract constraints type
203  typedef typename LFS::Traits::ConstraintsType C;
204 
205  // iterate over boundary, need intersection iterator
207  }
208 
209  ProcessorConstraints(const IG& ig_, CL& cl_)
210  : ig(ig_)
211  , cl(cl_)
212  {}
213 
214  private:
215  const IG& ig;
216  CL& cl;
217 
218  };
219 
220 
221  template<typename IG, typename CL>
222  struct SkeletonConstraints
223  : public TypeTree::TreePairVisitor
224  , public TypeTree::DynamicTraversal
225  {
226 
227  template<typename LFS, typename TreePath>
228  void leaf(const LFS& lfs_e, const LFS& lfs_f, TreePath treePath) const
229  {
230  // extract constraints type
231  typedef typename LFS::Traits::ConstraintsType C;
232 
233  // as LFS::constraints() just returns the constraints of the
234  // GridFunctionSpace, lfs_e.constraints() is equivalent to
235  // lfs_f.constraints()
236  const C & c = lfs_e.constraints();
237 
238  // iterate over boundary, need intersection iterator
239  ConstraintsCallSkeleton<C,C::doSkeleton>::skeleton(c,ig,lfs_e,lfs_f,cl_e,cl_f);
240  }
241 
242  SkeletonConstraints(const IG& ig_, CL& cl_e_, CL& cl_f_)
243  : ig(ig_)
244  , cl_e(cl_e_)
245  , cl_f(cl_f_)
246  {}
247 
248  private:
249  const IG& ig;
250  CL& cl_e;
251  CL& cl_f;
252 
253  };
254 
255 
256  template<typename P, typename EG, typename CL>
257  struct VolumeConstraintsForParametersLeaf
258  : public TypeTree::TreeVisitor
259  , public TypeTree::DynamicTraversal
260  {
261 
262  template<typename LFS, typename TreePath>
263  void leaf(const LFS& lfs, TreePath treePath) const
264  {
265  // extract constraints type
266  typedef typename LFS::Traits::ConstraintsType C;
267  const C & c = lfs.constraints();
268 
269  // iterate over boundary, need intersection iterator
270  ConstraintsCallVolume<C,C::doVolume>::volume(c,p,eg,lfs,cl);
271  }
272 
273  VolumeConstraintsForParametersLeaf(const P& p_, const EG& eg_, CL& cl_)
274  : p(p_)
275  , eg(eg_)
276  , cl(cl_)
277  {}
278 
279  private:
280  const P& p;
281  const EG& eg;
282  CL& cl;
283 
284  };
285 
286 
287  template<typename EG, typename CL>
288  struct VolumeConstraints
289  : public ParameterizedConstraintsBase
290  , public TypeTree::DynamicTraversal
291  {
292 
293  // standard case - leaf in both trees
294  template<typename P, typename LFS, typename TreePath>
295  typename std::enable_if<P::isLeaf && LFS::isLeaf>::type
296  leaf(const P& p, const LFS& lfs, TreePath treePath) const
297  {
298  // allocate local constraints map
299  CL cl;
300 
301  // extract constraints type
302  typedef typename LFS::Traits::ConstraintsType C;
303  const C & c = lfs.constraints();
304 
305  // iterate over boundary, need intersection iterator
306  ConstraintsCallVolume<C,C::doVolume>::volume(c,p,eg,lfs,cl);
307  }
308 
309  // reuse constraints parameter information from p for all LFS children
310  template<typename P, typename LFS, typename TreePath>
311  typename std::enable_if<P::isLeaf && (!LFS::isLeaf)>::type
312  leaf(const P& p, const LFS& lfs, TreePath treePath) const
313  {
314  // traverse LFS tree and reuse parameter information
315  TypeTree::applyToTree(lfs,VolumeConstraintsForParametersLeaf<P,EG,CL>(p,eg,cl));
316  }
317 
318  VolumeConstraints(const EG& eg_, CL& cl_)
319  : eg(eg_)
320  , cl(cl_)
321  {}
322 
323  private:
324  const EG& eg;
325  CL& cl;
326 
327  };
328 
329 
330  } // anonymous namespace
331 
332  template<typename... Children>
334  : public TypeTree::CompositeNode<Children...>
335  {
336  typedef TypeTree::CompositeNode<Children...> BaseT;
337 
338  CompositeConstraintsOperator(Children&... children)
339  : BaseT(children...)
340  {}
341 
342  CompositeConstraintsOperator(std::shared_ptr<Children>... children)
343  : BaseT(children...)
344  {}
345 
346  // aggregate flags
347 
348  // forward methods to childs
349 
350  };
351 
352  template<typename... Children>
354  : public TypeTree::CompositeNode<Children...>
355  {
356  typedef TypeTree::CompositeNode<Children...> BaseT;
357 
358  CompositeConstraintsParameters(Children&... children)
359  : BaseT(children...)
360  {}
361 
362  CompositeConstraintsParameters(std::shared_ptr<Children>... children)
363  : BaseT(children...)
364  {}
365  };
366 
367  template<typename T, std::size_t k>
369  : public TypeTree::PowerNode<T,k>
370  {
371  typedef TypeTree::PowerNode<T,k> BaseT;
372 
374  : BaseT()
375  {}
376 
378  : BaseT(c)
379  {}
380 
382  T& c1)
383  : BaseT(c0,c1)
384  {}
385 
387  T& c1,
388  T& c2)
389  : BaseT(c0,c1,c2)
390  {}
391 
393  T& c1,
394  T& c2,
395  T& c3)
396  : BaseT(c0,c1,c2,c3)
397  {}
398 
400  T& c1,
401  T& c2,
402  T& c3,
403  T& c4)
404  : BaseT(c0,c1,c2,c3,c4)
405  {}
406 
408  T& c1,
409  T& c2,
410  T& c3,
411  T& c4,
412  T& c5)
413  : BaseT(c0,c1,c2,c3,c4,c5)
414  {}
415 
417  T& c1,
418  T& c2,
419  T& c3,
420  T& c4,
421  T& c5,
422  T& c6)
423  : BaseT(c0,c1,c2,c3,c4,c5,c6)
424  {}
425 
427  T& c1,
428  T& c2,
429  T& c3,
430  T& c4,
431  T& c5,
432  T& c6,
433  T& c7)
434  : BaseT(c0,c1,c2,c3,c4,c5,c6,c7)
435  {}
436 
438  T& c1,
439  T& c2,
440  T& c3,
441  T& c4,
442  T& c5,
443  T& c6,
444  T& c7,
445  T& c8)
446  : BaseT(c0,c1,c2,c3,c4,c5,c6,c7,c8)
447  {}
448 
450  T& c1,
451  T& c2,
452  T& c3,
453  T& c4,
454  T& c5,
455  T& c6,
456  T& c7,
457  T& c8,
458  T& c9)
459  : BaseT(c0,c1,c2,c3,c4,c5,c6,c7,c8,c9)
460  {}
461 
462  PowerConstraintsParameters (const std::array<std::shared_ptr<T>,k>& children)
463  : BaseT(children)
464  {}
465  };
466 
467 #ifndef DOXYGEN
468 
470  template<typename F>
471  class OldStyleConstraintsWrapper
472  : public TypeTree::LeafNode
473  {
474  std::shared_ptr<const F> _f;
475  unsigned int _i;
476  public:
477 
478  template<typename Transformation>
479  OldStyleConstraintsWrapper(std::shared_ptr<const F> f, const Transformation& t, unsigned int i=0)
480  : _f(f)
481  , _i(i)
482  {}
483 
484  template<typename Transformation>
485  OldStyleConstraintsWrapper(const F & f, const Transformation& t, unsigned int i=0)
486  : _f(stackobject_to_shared_ptr(f))
487  , _i(i)
488  {}
489 
490  template<typename I>
491  bool isDirichlet(const I & intersection, const FieldVector<typename I::ctype, I::dimension-1> & coord) const
492  {
493  typename F::Traits::RangeType bctype;
494  _f->evaluate(intersection,coord,bctype);
495  return bctype[_i] > 0;
496  }
497 
498  template<typename I>
499  bool isNeumann(const I & intersection, const FieldVector<typename I::ctype, I::dimension-1> & coord) const
500  {
501  typename F::Traits::RangeType bctype;
502  _f->evaluate(intersection,coord,bctype);
503  return bctype[_i] == 0;
504  }
505  };
506 
507  // Tag to name trafo GridFunction -> OldStyleConstraintsWrapper
508  struct gf_to_constraints {};
509 
510  // register trafos GridFunction -> OldStyleConstraintsWrapper
511  template<typename F, typename Transformation>
512  struct MultiComponentOldStyleConstraintsWrapperDescription
513  {
514 
515  static const bool recursive = false;
516 
517  enum { dim = F::Traits::dimRange };
518  typedef OldStyleConstraintsWrapper<F> node_type;
519  typedef PowerConstraintsParameters<node_type, dim> transformed_type;
520  typedef std::shared_ptr<transformed_type> transformed_storage_type;
521 
522  static transformed_type transform(const F& s, const Transformation& t)
523  {
524  std::shared_ptr<const F> sp = stackobject_to_shared_ptr(s);
525  std::array<std::shared_ptr<node_type>, dim> childs;
526  for (int i=0; i<dim; i++)
527  childs[i] = std::make_shared<node_type>(sp,t,i);
528  return transformed_type(childs);
529  }
530 
531  static transformed_storage_type transform_storage(std::shared_ptr<const F> s, const Transformation& t)
532  {
533  std::array<std::shared_ptr<node_type>, dim> childs;
534  for (int i=0; i<dim; i++)
535  childs[i] = std::make_shared<node_type>(s,t,i);
536  return std::make_shared<transformed_type>(childs);
537  }
538 
539  };
540  // trafos for leaf nodes
541  template<typename GridFunction>
542  typename std::conditional<
543  (GridFunction::Traits::dimRange == 1),
544  // trafo for scalar leaf nodes
545  TypeTree::GenericLeafNodeTransformation<GridFunction,gf_to_constraints,OldStyleConstraintsWrapper<GridFunction> >,
546  // trafo for multi component leaf nodes
547  MultiComponentOldStyleConstraintsWrapperDescription<GridFunction,gf_to_constraints>
548  >::type
549  registerNodeTransformation(GridFunction*, gf_to_constraints*, GridFunctionTag*);
550 
551  // trafo for power nodes
552  template<typename PowerGridFunction>
553  TypeTree::SimplePowerNodeTransformation<PowerGridFunction,gf_to_constraints,PowerConstraintsParameters>
555 
556  // trafos for composite nodes
557  template<typename CompositeGridFunction>
558  TypeTree::SimpleCompositeNodeTransformation<CompositeGridFunction,gf_to_constraints,CompositeConstraintsParameters>
560 
562 
572  template<typename P, typename GFS, typename CG, bool isFunction>
573  struct ConstraintsAssemblerHelper
574  {
576 
590  static void
591  assemble(const P& p, const GFS& gfs, CG& cg, const bool verbose)
592  {
593  // get some types
594  using ES = typename GFS::Traits::EntitySet;
595  using Element = typename ES::Traits::Element;
596  using Intersection = typename ES::Traits::Intersection;
597 
598  ES es = gfs.entitySet();
599 
600  // make local function space
601  using LFS = LocalFunctionSpace<GFS>;
602  LFS lfs_e(gfs);
603  LFSIndexCache<LFS> lfs_cache_e(lfs_e);
604  LFS lfs_f(gfs);
605  LFSIndexCache<LFS> lfs_cache_f(lfs_f);
606 
607  // get index set
608  auto& is = es.indexSet();
609 
610  // loop once over the grid
611  for (const auto& element : elements(es))
612  {
613 
614  auto id = is.uniqueIndex(element);
615 
616  // bind local function space to element
617  lfs_e.bind(element);
618 
619  using CL = typename CG::LocalTransformation;
620 
621  CL cl_self;
622 
623  using ElementWrapper = ElementGeometry<Element>;
624  using IntersectionWrapper = IntersectionGeometry<Intersection>;
625 
626  TypeTree::applyToTreePair(p,lfs_e,VolumeConstraints<ElementWrapper,CL>(ElementWrapper(element),cl_self));
627 
628  // iterate over intersections and call metaprogram
629  unsigned int intersection_index = 0;
630  for (const auto& intersection : intersections(es,element))
631  {
632 
633  auto intersection_data = classifyIntersection(es,intersection);
634  auto intersection_type = std::get<0>(intersection_data);
635  auto& outside_element = std::get<1>(intersection_data);
636 
637  switch (intersection_type) {
638 
641  {
642  auto idn = is.uniqueIndex(outside_element);
643 
644  if(id > idn){
645  // bind local function space to element in neighbor
646  lfs_f.bind(outside_element);
647 
648  CL cl_neighbor;
649 
650  TypeTree::applyToTreePair(lfs_e,lfs_f,SkeletonConstraints<IntersectionWrapper,CL>(IntersectionWrapper(intersection,intersection_index),cl_self,cl_neighbor));
651 
652  if (!cl_neighbor.empty())
653  {
654  lfs_cache_f.update();
655  cg.import_local_transformation(cl_neighbor,lfs_cache_f);
656  }
657 
658  }
659  break;
660  }
661 
663  TypeTree::applyToTreePair(p,lfs_e,BoundaryConstraints<IntersectionWrapper,CL>(IntersectionWrapper(intersection,intersection_index),cl_self));
664  break;
665 
667  TypeTree::applyToTree(lfs_e,ProcessorConstraints<IntersectionWrapper,CL>(IntersectionWrapper(intersection,intersection_index),cl_self));
668  break;
669 
670  }
671  ++intersection_index;
672  }
673 
674  if (!cl_self.empty())
675  {
676  lfs_cache_e.update();
677  cg.import_local_transformation(cl_self,lfs_cache_e);
678  }
679 
680  }
681 
682  // print result
683  if(verbose){
684  std::cout << "constraints:" << std::endl;
685 
686  std::cout << cg.size() << " constrained degrees of freedom" << std::endl;
687 
688  for (const auto& col : cg)
689  {
690  std::cout << col.first << ": "; // col index
691  for (const auto& row : col.second)
692  std::cout << "(" << row.first << "," << row.second << ") "; // row index , value
693  std::cout << std::endl;
694  }
695  }
696  }
697  }; // end ConstraintsAssemblerHelper
698 
699 
700 
701  // Disable constraints assembly for empty transformation
702  template<typename F, typename GFS>
703  struct ConstraintsAssemblerHelper<F, GFS, EmptyTransformation, true>
704  {
705  static void assemble(const F& f, const GFS& gfs, EmptyTransformation& cg, const bool verbose)
706  {}
707  };
708 
709  // Disable constraints assembly for empty transformation
710  template<typename F, typename GFS>
711  struct ConstraintsAssemblerHelper<F, GFS, EmptyTransformation, false>
712  {
713  static void assemble(const F& f, const GFS& gfs, EmptyTransformation& cg, const bool verbose)
714  {}
715  };
716 
717 
718 
719  // Backwards compatibility shim
720  template<typename F, typename GFS, typename CG>
721  struct ConstraintsAssemblerHelper<F, GFS, CG, true>
722  {
723  static void
724  assemble(const F& f, const GFS& gfs, CG& cg, const bool verbose)
725  {
726  // type of transformed tree
727  typedef typename TypeTree::TransformTree<F,gf_to_constraints> Transformation;
728  typedef typename Transformation::Type P;
729  // transform tree
730  P p = Transformation::transform(f);
731  // call parameter based implementation
733  }
734  };
735 #endif
736 
738 
750  template<typename GFS, typename CG>
751  void constraints(const GFS& gfs, CG& cg,
752  const bool verbose = false)
753  {
755  ConstraintsAssemblerHelper<NoConstraintsParameters, GFS, CG, false>::assemble(p,gfs,cg,verbose);
756  }
757 
759 
776  template<typename P, typename GFS, typename CG>
777  void constraints(const P& p, const GFS& gfs, CG& cg,
778  const bool verbose = false)
779  {
780  // clear global constraints
781  cg.clear();
783  }
784 
786 
797  template<typename CG, typename XG>
798  void set_constrained_dofs(const CG& cg,
799  typename XG::ElementType x,
800  XG& xg)
801  {
802  for (const auto& col : cg)
803  xg[col.first] = x;
804  }
805 
806 
807 #ifndef DOXYGEN
808 
809  // Specialized version for unconstrained spaces
810  template<typename XG>
811  void set_constrained_dofs(const EmptyTransformation& cg,
812  typename XG::ElementType x,
813  XG& xg)
814  {}
815 
816 #endif // DOXYGEN
817 
818 
820 
840  template<typename CG, typename XG, typename Cmp>
841  bool check_constrained_dofs(const CG& cg, typename XG::ElementType x,
842  XG& xg, const Cmp& cmp = Cmp())
843  {
844  for (const auto& col : cg)
845  if(cmp.ne(xg[col.first], x))
846  return false;
847  return true;
848  }
849 
851 
869  template<typename CG, typename XG>
870  bool check_constrained_dofs(const CG& cg, typename XG::ElementType x,
871  XG& xg)
872  {
873  return check_constrained_dofs(cg, x, xg,
874  FloatCmpOps<typename XG::ElementType>());
875  }
876 
877 
878 #ifndef DOXYGEN
879 
880  // Specialized version for unconstrained spaces
881  template<typename XG, typename Cmp>
882  bool check_constrained_dofs(const EmptyTransformation& cg, typename XG::ElementType x,
883  XG& xg, const Cmp& cmp = Cmp())
884  {
885  return true;
886  }
887 
888  // Specialized version for unconstrained spaces
889  template<typename XG>
890  bool check_constrained_dofs(const EmptyTransformation& cg, typename XG::ElementType x,
891  XG& xg)
892  {
893  return true;
894  }
895 
896 #endif // DOXYGEN
897 
898 
900 
905  template<typename CG, typename XG>
906  void constrain_residual (const CG& cg, XG& xg)
907  {
908  for (const auto& col : cg)
909  for (const auto& row : col.second)
910  xg[row.first] += row.second * xg[col.first];
911 
912  // extra loop because constrained dofs might have contributions
913  // to constrained dofs
914  for (const auto& col : cg)
915  xg[col.first] = typename XG::ElementType(0);
916  }
917 
918 
919 #ifndef DOXYGEN
920 
921  // Specialized version for unconstrained spaces
922  template<typename XG>
923  void constrain_residual (const EmptyTransformation& cg, XG& xg)
924  {}
925 
926 #endif // DOXYGEN
927 
931 
937  template<typename CG, typename XG>
938  void copy_constrained_dofs (const CG& cg, const XG& xgin, XG& xgout)
939  {
940  for (const auto& col : cg)
941  xgout[col.first] = xgin[col.first];
942  }
943 
944 
945 #ifndef DOXYGEN
946 
947  // Specialized version for unconstrained spaces
948  template<typename XG>
949  void copy_constrained_dofs (const EmptyTransformation& cg, const XG& xgin, XG& xgout)
950  {}
951 
952 #endif // DOXYGEN
953 
954 
961  template<typename CG, typename XG>
962  void set_nonconstrained_dofs (const CG& cg, typename XG::ElementType x, XG& xg)
963  {
964  XG tmp(xg);
965  xg = x;
966  copy_constrained_dofs(cg,tmp,xg);
967  }
968 
969 
970 #ifndef DOXYGEN
971 
972  // Specialized version for unconstrained spaces
973  template<typename XG>
974  void set_nonconstrained_dofs (const EmptyTransformation& cg, typename XG::ElementType x, XG& xg)
975  {
976  xg = x;
977  }
978 
979 #endif // DOXYGEN
980 
981 
988  template<typename CG, typename XG>
989  void copy_nonconstrained_dofs (const CG& cg, const XG& xgin, XG& xgout)
990  {
991  XG tmp(xgin);
992  copy_constrained_dofs(cg,xgout,tmp);
993  xgout = tmp;
994  }
995 
996 
997 #ifndef DOXYGEN
998 
999  // Specialized version for unconstrained spaces
1000  template<typename XG>
1001  void copy_nonconstrained_dofs (const EmptyTransformation& cg, const XG& xgin, XG& xgout)
1002  {
1003  xgout = xgin;
1004  }
1005 
1006 #endif // DOXYGEN
1007 
1008 
1015  template<typename CG, typename XG>
1016  void set_shifted_dofs (const CG& cg, typename XG::ElementType x, XG& xg)
1017  {
1018  XG tmp(xg);
1019  tmp = x;
1020 
1021  for (const auto& col : cg)
1022  {
1023  // this is our marker for Dirichlet constraints
1024  if (col.second.size() == 0)
1025  {
1026  tmp[col.first] = xg[col.first];
1027  }
1028  }
1029 
1030  xg = tmp;
1031  }
1032 
1033 
1034 #ifndef DOXYGEN
1035 
1036  // Specialized version for unconstrained spaces
1037  template<typename XG>
1038  void set_shifted_dofs (const EmptyTransformation& cg, typename XG::ElementType x, XG& xg)
1039  {}
1040 
1041 #endif // DOXYGEN
1042 
1044 
1046  } // namespace PDELab
1047 } // namespace Dune
1048 
1049 #endif // DUNE_PDELAB_CONSTRAINTS_COMMON_CONSTRAINTS_HH
void set_nonconstrained_dofs(const CG &cg, typename XG::ElementType x, XG &xg)
Definition: constraints.hh:962
PowerConstraintsParameters()
Definition: constraints.hh:373
const IG & ig
Definition: constraints.hh:148
periodic boundary intersection (neighbor() == true && boundary() == true)
static const int dim
Definition: adaptivity.hh:83
CL & cl
Definition: constraints.hh:149
PowerConstraintsParameters(T &c0, T &c1)
Definition: constraints.hh:381
Wrap intersection.
Definition: geometrywrapper.hh:56
void copy_nonconstrained_dofs(const CG &cg, const XG &xgin, XG &xgout)
Definition: constraints.hh:989
domain boundary intersection (neighbor() == false && boundary() == true)
Definition: constraints.hh:333
XG & xg
Definition: interpolate.hh:71
const std::string s
Definition: function.hh:830
void set_shifted_dofs(const CG &cg, typename XG::ElementType x, XG &xg)
Definition: constraints.hh:1016
CompositeConstraintsOperator(Children &... children)
Definition: constraints.hh:338
void set_constrained_dofs(const CG &cg, typename XG::ElementType x, XG &xg)
construct constraints from given boundary condition function
Definition: constraints.hh:798
skeleton intersection (neighbor() == true && boundary() == false)
Wrap element.
Definition: geometrywrapper.hh:15
Definition: function.hh:287
PowerConstraintsParameters(T &c0, T &c1, T &c2, T &c3)
Definition: constraints.hh:392
std::tuple< IntersectionType, typename EntitySet::Element > classifyIntersection(const EntitySet &entity_set, const Intersection &is)
Classifies the type of an intersection wrt to the passed EntitySet.
Definition: intersectiontype.hh:37
void update()
Definition: lfsindexcache.hh:300
PowerConstraintsParameters(T &c0, T &c1, T &c2)
Definition: constraints.hh:386
TypeTree::CompositeNode< Children... > BaseT
Definition: constraints.hh:356
PowerConstraintsParameters(T &c0, T &c1, T &c2, T &c3, T &c4, T &c5)
Definition: constraints.hh:407
CompositeConstraintsParameters(std::shared_ptr< Children >... children)
Definition: constraints.hh:362
composite functions
Definition: function.hh:528
Dune::TypeTree::GenericLeafNodeTransformation< LeafNode, GridFunctionToLocalViewTransformation, Imp::LocalGridViewFunctionAdapter< LeafNode > > registerNodeTransformation(LeafNode *l, GridFunctionToLocalViewTransformation *t, GridFunctionTag *tag)
PowerConstraintsParameters(T &c)
Definition: constraints.hh:377
PowerConstraintsParameters(T &c0, T &c1, T &c2, T &c3, T &c4, T &c5, T &c6, T &c7, T &c8)
Definition: constraints.hh:437
For backward compatibility – Do not use this!
Definition: adaptivity.hh:27
const P & p
Definition: constraints.hh:147
Definition: function.hh:356
Definition: constraintsparameters.hh:293
bool check_constrained_dofs(const CG &cg, typename XG::ElementType x, XG &xg, const Cmp &cmp=Cmp())
check that constrained dofs match a certain value
Definition: constraints.hh:841
void constrain_residual(const CG &cg, XG &xg)
transform residual into transformed basis: r -> r~
Definition: constraints.hh:906
TypeTree::CompositeNode< Children... > BaseT
Definition: constraints.hh:336
PowerConstraintsParameters(T &c0, T &c1, T &c2, T &c3, T &c4, T &c5, T &c6, T &c7)
Definition: constraints.hh:426
PowerConstraintsParameters(T &c0, T &c1, T &c2, T &c3, T &c4)
Definition: constraints.hh:399
PowerConstraintsParameters(const std::array< std::shared_ptr< T >, k > &children)
Definition: constraints.hh:462
Definition: function.hh:516
Definition: constraints.hh:368
void copy_constrained_dofs(const CG &cg, const XG &xgin, XG &xgout)
Definition: constraints.hh:938
TypeTree::PowerNode< T, k > BaseT
Definition: constraints.hh:371
PowerConstraintsParameters(T &c0, T &c1, T &c2, T &c3, T &c4, T &c5, T &c6)
Definition: constraints.hh:416
CompositeConstraintsOperator(std::shared_ptr< Children >... children)
Definition: constraints.hh:342
product of identical functions
Definition: function.hh:366
void constraints(const GFS &gfs, CG &cg, const bool verbose=false)
construct constraints
Definition: constraints.hh:751
CompositeConstraintsParameters(Children &... children)
Definition: constraints.hh:358
static const unsigned int value
Definition: gridfunctionspace/tags.hh:139
processor boundary intersection (neighbor() == false && boundary() == false) or outside entity not in...
PowerConstraintsParameters(T &c0, T &c1, T &c2, T &c3, T &c4, T &c5, T &c6, T &c7, T &c8, T &c9)
Definition: constraints.hh:449
Definition: constraints.hh:353