dune-geometry  2.2.0
subtopologies.hh
Go to the documentation of this file.
1 #ifndef DUNE_GEOMETRY_GENERICGEOMETRY_SUBTOPOLOGIES_HH
2 #define DUNE_GEOMETRY_GENERICGEOMETRY_SUBTOPOLOGIES_HH
3 
4 #include <cassert>
5 #include <vector>
6 
7 #include <dune/common/forloop.hh>
8 #include <dune/common/static_assert.hh>
9 #include <dune/common/typetraits.hh>
10 
13 
14 namespace Dune
15 {
16 
17  namespace GenericGeometry
18  {
19 
20  template< class Topology, unsigned int codim >
21  struct Size;
22 
23  template< class Topology, unsigned int codim, unsigned int i >
24  struct SubTopology;
25 
26  template< class Topology, unsigned int codim, unsigned int subcodim >
27  class SubTopologySize;
28 
29  template< class Topology, unsigned int codim, unsigned int subcodim >
30  class GenericSubTopologyNumbering;
31 
32  template< class Topology, unsigned int codim, unsigned int subcodim >
33  class SubTopologyNumbering;
34 
35 
36 
37  // Size
38  // ----
39 
40  template< class Topology, unsigned int dim, unsigned int codim >
41  class SizeImpl;
42 
43  template< unsigned int dim, unsigned int codim >
44  class SizeImpl< Point, dim, codim >
45  {
46  typedef Point Topology;
47  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
48  dune_static_assert( (codim <= dim), "Invalid codimension" );
49 
50  public:
51  enum { value = 1 };
52  };
53 
54  template< class BaseTopology, unsigned int dim, unsigned int codim >
55  class SizeImpl< Prism< BaseTopology >, dim, codim >
56  {
58  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
59  dune_static_assert( (codim <= dim), "Invalid codimension" );
60 
61  enum { m = Size< BaseTopology, codim-1 > :: value };
62  enum { n = Size< BaseTopology, codim > :: value };
63 
64  public:
65  enum { value = n + 2*m };
66  };
67 
68  template< class BaseTopology, unsigned int dim >
69  class SizeImpl< Prism< BaseTopology >, dim, 0 >
70  {
72  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
73 
74  public:
75  enum { value = 1 };
76  };
77 
78  template< class BaseTopology, unsigned int dim >
79  class SizeImpl< Prism< BaseTopology >, dim, dim >
80  {
82  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
83 
84  enum { m = Size< BaseTopology, dim-1 > :: value };
85 
86  public:
87  enum { value = 2*m };
88  };
89 
90  template< class BaseTopology, unsigned int dim, unsigned int codim >
91  class SizeImpl< Pyramid< BaseTopology >, dim, codim >
92  {
94  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
95  dune_static_assert( (codim <= dim), "Invalid codimension" );
96 
97  enum { m = Size< BaseTopology, codim-1 > :: value };
98  enum { n = Size< BaseTopology, codim > :: value };
99 
100  public:
101  enum { value = m+n };
102  };
103 
104  template< class BaseTopology, unsigned int dim >
105  class SizeImpl< Pyramid< BaseTopology >, dim, 0 >
106  {
108  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
109 
110  public:
111  enum { value = 1 };
112  };
113 
114  template< class BaseTopology, unsigned int dim >
115  class SizeImpl< Pyramid< BaseTopology >, dim, dim >
116  {
118  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
119 
120  enum { m = Size< BaseTopology, dim-1 > :: value };
121 
122  public:
123  enum { value = m+1 };
124  };
125 
126 
127  template< class Topology, unsigned int codim >
128  struct Size
129  {
130  enum { value = SizeImpl< Topology, Topology :: dimension, codim > :: value };
131  };
132 
133 
134 
135  // SubTopology
136  // -----------
137 
138  template< class Topology, unsigned int dim, unsigned int codim, unsigned int i >
139  class SubTopologyImpl;
140 
141  template< unsigned int dim, unsigned int codim, unsigned int i >
142  class SubTopologyImpl< Point, dim, codim, i >
143  {
144  typedef Point Topology;
145  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
146  dune_static_assert( (codim <= dim), "Invalid codimension" );
147  dune_static_assert( (i < Size< Topology, codim > :: value),
148  "Invalid subentity index" );
149 
150  public:
151  typedef Topology type;
152  };
153 
154  template< class BaseTopology, unsigned int dim, unsigned int codim, unsigned int i >
155  class SubTopologyImpl< Prism< BaseTopology >, dim, codim, i >
156  {
158  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
159  dune_static_assert( (codim <= dim), "Invalid codimension" );
160  dune_static_assert( (i < Size< Topology, codim > :: value),
161  "Invalid subentity index" );
162 
163  enum { m = Size< BaseTopology, codim-1 > :: value };
164  enum { n = Size< BaseTopology, codim > :: value };
165 
166  enum { s = (i < n+m ? 0 : 1) };
167 
168  template< bool >
169  struct PrismSub
170  {
172  };
173 
174  template< bool >
175  struct BaseSub
176  {
177  typedef typename SubTopology< BaseTopology, codim-1, i-(n+s*m) > :: type type;
178  };
179 
180  public:
181  typedef typename SelectType< (i < n), PrismSub<true>, BaseSub<false> > :: Type :: type type;
182  };
183 
184  template< class BaseTopology, unsigned int dim, unsigned int i >
185  class SubTopologyImpl< Prism< BaseTopology >, dim, 0, i >
186  {
188  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
189  dune_static_assert( (i < Size< Topology, 0 > :: value),
190  "Invalid subentity index" );
191  public:
192  typedef Topology type;
193  };
194 
195  template< class BaseTopology, unsigned int dim, unsigned int i >
196  class SubTopologyImpl< Prism< BaseTopology >, dim, dim, i >
197  {
199  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
200  dune_static_assert( (i < Size< Topology, dim > :: value),
201  "Invalid subentity index" );
202  public:
203  typedef Point type;
204  };
205 
206  template< class BaseTopology, unsigned int dim, unsigned int codim, unsigned int i >
207  class SubTopologyImpl< Pyramid< BaseTopology >, dim, codim, i >
208  {
210  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
211  dune_static_assert( (codim <= dim), "Invalid codimension" );
212  dune_static_assert( (i < Size< Topology, codim > :: value),
213  "Invalid subentity index" );
214 
215  enum { m = Size< BaseTopology, codim-1 > :: value };
216 
217  template< bool >
218  struct BaseSub
219  {
220  typedef typename SubTopology< BaseTopology, codim-1, i > :: type type;
221  };
222 
223  template< bool >
224  struct PyramidSub
225  {
226  typedef Pyramid< typename SubTopology< BaseTopology, codim, i-m > :: type > type;
227  };
228 
229  public:
230  typedef typename SelectType< (i < m), BaseSub<true>, PyramidSub<false> > :: Type :: type type;
231  };
232 
233  template< class BaseTopology, unsigned int dim, unsigned int i >
234  class SubTopologyImpl< Pyramid< BaseTopology >, dim, 0, i >
235  {
237  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
238  dune_static_assert( (i < Size< Topology, 0 > :: value),
239  "Invalid subentity index" );
240 
241  public:
242  typedef Topology type;
243  };
244 
245  template< class BaseTopology, unsigned int dim, unsigned int i >
246  class SubTopologyImpl< Pyramid< BaseTopology >, dim, dim, i >
247  {
249  dune_static_assert( (dim == Topology :: dimension), "Wrong dimension" );
250  dune_static_assert( (i < Size< Topology, dim > :: value),
251  "Invalid subentity index" );
252 
253  public:
254  typedef Point type;
255  };
256 
257  template< class Topology, unsigned int codim, unsigned int i >
258  struct SubTopology
259  {
260  typedef typename SubTopologyImpl< Topology, Topology :: dimension, codim, i > :: type type;
261  };
262 
263 
264 
265  // SubTopologySize
266  // ---------------
267 
268  template< class Topology, unsigned int codim, unsigned int subcodim >
270  {
271  template< int i >
272  struct Builder;
273 
274  unsigned int size_[ Size< Topology, codim > :: value ];
275 
276  SubTopologySize ()
277  {
278  ForLoop< Builder, 0, Size< Topology, codim > :: value-1 >
279  :: apply( *this );
280  }
281 
282  SubTopologySize ( const SubTopologySize & );
283 
284  static const SubTopologySize &instance ()
285  {
286  static SubTopologySize inst;
287  return inst;
288  }
289 
290  public:
291  static unsigned int size ( unsigned int i )
292  {
293  assert( (i < Size< Topology, codim > :: value) );
294  return instance().size_[ i ];
295  }
296  };
297 
298  template< class Topology, unsigned int codim, unsigned int subcodim >
299  template< int i >
300  struct SubTopologySize< Topology, codim, subcodim > :: Builder
301  {
306 
307  static void apply ( SubTopologySize &subTopologySize )
308  {
309  subTopologySize.size_[ i ] = Size< SubTopology, subcodim > :: value;
310  }
311  };
312 
313 
314 
315  // GenericSubTopologyNumbering
316  // ---------------------------
317 
318  template< class Topology, unsigned int codim,
319  unsigned int subdim, unsigned int subcodim >
320  struct GenericSubTopologyNumberingHelper;
321 
322  template< class BaseTopology, unsigned int codim,
323  unsigned int subdim, unsigned int subcodim >
324  struct GenericSubTopologyNumberingHelper
325  < Prism< BaseTopology >, codim, subdim, subcodim >
326  {
328 
329  enum { m = Size< BaseTopology, codim-1 > :: value };
330  enum { n = Size< BaseTopology, codim > :: value };
331 
332  enum { mb = Size< BaseTopology, codim+subcodim-1 > :: value };
333  enum { nb = Size< BaseTopology, codim+subcodim > :: value };
334 
335  static unsigned int number ( unsigned int i, unsigned int j )
336  {
337  const unsigned int s = (i < n+m ? 0 : 1);
338  if( i < n )
339  {
342  const unsigned int ss = (j < ns+ms ? 0 : 1);
343  if( j < ns )
345  :: number( i, j );
346  else
348  :: number( i, j-(ns+ss*ms) ) + nb + ss*mb;
349  }
350  else
352  :: number( i-(n+s*m), j ) + nb + s*mb;
353  }
354  };
355 
356  template< class BaseTopology, unsigned int codim, unsigned int subdim >
357  struct GenericSubTopologyNumberingHelper
358  < Prism< BaseTopology >, codim, subdim, 0 >
359  {
361 
362  static unsigned int number ( unsigned int i, unsigned int j )
363  {
364  return i;
365  }
366  };
367 
368  template< class BaseTopology, unsigned int codim, unsigned int subdim >
369  struct GenericSubTopologyNumberingHelper
370  < Prism< BaseTopology >, codim, subdim, subdim >
371  {
373 
374  enum { m = Size< BaseTopology, codim-1 > :: value };
375  enum { n = Size< BaseTopology, codim > :: value };
376 
377  enum { mb = Size< BaseTopology, codim+subdim-1 > :: value };
378 
379  static unsigned int number ( unsigned int i, unsigned int j )
380  {
381  const unsigned int s = (i < n+m ? 0 : 1);
382  if( i < n )
383  {
385  const unsigned int ss = (j < ms ? 0 : 1);
387  :: number( i, j-ss*ms ) + ss*mb;
388  }
389  else
391  :: number( i-(n+s*m), j ) + s*mb;
392  }
393  };
394 
395  template< class BaseTopology, unsigned int codim,
396  unsigned int subdim, unsigned int subcodim >
397  struct GenericSubTopologyNumberingHelper
398  < Pyramid< BaseTopology >, codim, subdim, subcodim >
399  {
401 
402  enum { m = Size< BaseTopology, codim-1 > :: value };
403 
404  enum { mb = Size< BaseTopology, codim+subcodim-1 > :: value };
405 
406  static unsigned int number ( unsigned int i, unsigned int j )
407  {
408  if( i < m )
410  :: number( i, j );
411  else
412  {
413  const unsigned int ms = SubTopologySize< BaseTopology, codim, subcodim-1 > :: size( i-m );
414  if( j < ms )
416  :: number( i-m, j );
417  else
419  :: number( i-m, j-ms ) + mb;
420  }
421  }
422  };
423 
424  template< class BaseTopology, unsigned int codim, unsigned int subdim >
425  struct GenericSubTopologyNumberingHelper
426  < Pyramid< BaseTopology >, codim, subdim, 0 >
427  {
429 
430  static unsigned int number ( unsigned int i, unsigned int j )
431  {
432  return i;
433  }
434  };
435 
436  template< class BaseTopology, unsigned int codim, unsigned int subdim >
437  struct GenericSubTopologyNumberingHelper
438  < Pyramid< BaseTopology >, codim, subdim, subdim >
439  {
441 
442  enum { m = Size< BaseTopology, codim-1 > :: value };
443 
444  enum { mb = Size< BaseTopology, codim+subdim-1 > :: value };
445 
446  static unsigned int number ( unsigned int i, unsigned int j )
447  {
448  if( i < m )
450  :: number( i, j );
451  else
452  {
453  const unsigned int ms = SubTopologySize< BaseTopology, codim, subdim-1 > :: size( i-m );
454  if( j < ms )
456  :: number( i-m, j );
457  else
458  return mb;
459  }
460  }
461  };
462 
463  template< class Topology, unsigned int codim, unsigned int subcodim >
465  {
466  dune_static_assert( (codim <= Topology :: dimension), "Invalid codimension" );
467  dune_static_assert( (codim + subcodim <= Topology :: dimension),
468  "Invalid subcodimension" );
469 
470  template< bool >
471  struct BorderCodim
472  {
473  static unsigned int number ( unsigned int i, unsigned int j )
474  {
475  return (codim == 0 ? j : i );
476  }
477  };
478 
479  template< bool >
480  struct InnerCodim
481  {
482  static unsigned int number ( unsigned int i, unsigned int j )
483  {
484  return GenericSubTopologyNumberingHelper
485  < Topology, codim, Topology :: dimension - codim, subcodim >
486  :: number( i, j );
487  }
488  };
489 
490  public:
491  static unsigned int number ( unsigned int i, unsigned int j )
492  {
494  return SelectType
495  < (codim == 0) || (codim == Topology :: dimension), BorderCodim<true>, InnerCodim<false> >
496  :: Type :: number( i, j );
497  }
498  };
499 
500 
501 
502  // SubTopologyNumbering
503  // --------------------
504 
505  template< class Topology, unsigned int codim, unsigned int subcodim >
507  {
510 
511  std :: vector< unsigned int > numbering_[ Size< Topology, codim > :: value ];
512 
513  public:
514  static unsigned int number ( unsigned int i, unsigned int j )
515  {
517  return instance().numbering_[ i ][ j ];
518  }
519 
520  private:
522  {
523  for( unsigned int i = 0; i < Size< Topology, codim > :: value; ++i )
524  {
525  const unsigned int size = SubTopologySize< Topology, codim, subcodim > :: size( i );
526  numbering_[ i ].resize( size );
527  for( unsigned int j = 0; j < size; ++j )
528  numbering_[ i ][ j ] = GenericNumbering :: number( i, j );
529  }
530  }
531 
532  static const SubTopologyNumbering &instance ()
533  {
534  static SubTopologyNumbering inst;
535  return inst;
536  }
537  };
538 
539 
540 
541  // IsCodimHybrid
542  // -------------
543 
544  template< class Topology, unsigned int codim >
546  {
547  static const bool value = (codim != 0) && IsHybrid< Topology >::value;
548  };
549 
550 
551 
552  // SubTopologyMapper
553  // -----------------
554 
555  template< class Topology >
557  {
558  static const unsigned int dimension = Topology::dimension;
559 
560  template< class A, class B >
561  struct StaticSum
562  {
563  static const unsigned int value = A::value + B::value;
564  };
565 
566  template< int codim >
567  struct Size
568  {
569  static const unsigned int value = GenericGeometry::Size< Topology, codim >::value;
570  };
571 
572  template< int codim >
573  struct CalcOffset
574  {
575  static void apply ( unsigned int (&offsets)[ dimension+2 ] )
576  {
577  offsets[ codim+1 ] = offsets[ codim ] + Size< codim >::value;
578  }
579  };
580 
581  public:
582  static const unsigned int staticSize = GenericForLoop< StaticSum, Size, 0, dimension >::value;
583 
585  {
586  offsets_[ 0 ] = 0;
587  ForLoop< CalcOffset, 0, dimension >::apply( offsets_ );
588  assert( size() == staticSize );
589  };
590 
591  unsigned int operator() ( const unsigned int codim, const unsigned int subEntity ) const
592  {
593  const unsigned int offset = offsets_[ codim ];
594  assert( offset + subEntity < offsets_[ codim+1 ] );
595  return offset + subEntity;
596  }
597 
598  unsigned int size () const
599  {
600  return offsets_[ dimension+1 ];
601  }
602 
603  private:
604  unsigned int offsets_[ dimension+2 ];
605  };
606 
607  }
608 
609 }
610 
611 #endif // #ifndef DUNE_GEOMETRY_GENERICGEOMETRY_SUBTOPOLOGIES_HH