dune-grid  2.2.0
albertagrid/refinement.hh
Go to the documentation of this file.
1 #ifndef DUNE_ALBERTA_REFINEMENT_HH
2 #define DUNE_ALBERTA_REFINEMENT_HH
3 
10 #include <cassert>
11 
14 
15 #if HAVE_ALBERTA
16 
17 namespace Dune
18 {
19 
20  namespace Alberta
21  {
22 
23  // Internal Forward Declarations
24  // -----------------------------
25 
26  template< int dim, int codim >
27  struct ForEachInteriorSubChild;
28 
29 
30 
31  // Patch
32  // -----
33 
34  template< int dim >
35  class Patch
36  {
37  typedef Patch< dim > This;
38 
39  dune_static_assert( ((dim >= 1) && (dim <= 3)),
40  "Alberta supports only dimensions 1, 2, 3" );
41 
42  public:
43  static const int dimension = dim;
44 
46 
47  typedef ALBERTA RC_LIST_EL ElementList;
48 
49  private:
50  ElementList *list_;
51  int count_;
52 
53  public:
54  Patch ( ElementList *list, int count )
55  : list_( list ),
56  count_( count )
57  {
58  assert( count > 0 );
59  }
60 
61  Element *operator[] ( int i ) const;
62 
63  int count () const
64  {
65  return count_;
66  }
67 
68  template< class LevelProvider >
69  ElementInfo elementInfo ( int i, const LevelProvider &levelProvider ) const;
70 
71  int elementType ( int i ) const;
72  bool hasNeighbor ( int i, int neighbor ) const;
73  int neighborIndex ( int i, int neighbor ) const;
74 
75  template< class Functor >
76  void forEach ( Functor &functor ) const
77  {
78  for( int i = 0; i < count(); ++i )
79  functor( (*this)[ i ] );
80  }
81 
82  template< int codim, class Functor >
83  void forEachInteriorSubChild ( Functor &functor ) const
84  {
85  ForEachInteriorSubChild< dim, codim >::apply( functor, *this );
86  }
87  };
88 
89 
90  template< int dim >
91  inline Element *Patch< dim >::operator[] ( int i ) const
92  {
93  assert( (i >= 0) && (i < count()) );
94  return list_[ i ].el_info.el;
95  }
96 
97 
98  template< int dim >
99  template< class LevelProvider >
100  inline typename Patch< dim >::ElementInfo
101  Patch< dim >::elementInfo ( int i, const LevelProvider &levelProvider ) const
102  {
103  assert( (i >= 0) && (i < count()) );
104  return ElementInfo::createFake( list_[ i ].el_info );
105  }
106 
107  template<>
108  template< class LevelProvider >
109  inline typename Patch< 2 >::ElementInfo
110  Patch< 2 >::elementInfo ( int i, const LevelProvider &levelProvider ) const
111  {
112  assert( (i >= 0) && (i < count()) );
113  const MeshPointer< 2 > &mesh = levelProvider.mesh();
114  const Element *element = (*this)[ i ];
115  const int level = levelProvider( element );
116  return ElementInfo::createFake( mesh, element, level );
117  }
118 
119 
120  template< int dim >
121  inline int Patch< dim >::elementType ( int i ) const
122  {
123  assert( (i >= 0) && (i < count()) );
124  return list_[ i ].el_info.el_type;
125  }
126 
127 
128  template< int dim >
129  inline bool Patch< dim >::hasNeighbor ( int i, int neighbor ) const
130  {
131  return (list_[ i ].neigh[ neighbor ] != NULL);
132  }
133 
134  template< int dim >
135  inline int Patch< dim >::neighborIndex ( int i, int neighbor ) const
136  {
137  assert( hasNeighbor( i, neighbor ) );
138  return (list_[ i ].neigh[ neighbor ]->no);
139  }
140 
141 
142 
143  // ForEachInteriorSubChild
144  // -----------------------
145 
146  template< int dim >
147  struct ForEachInteriorSubChild< dim, 0 >
148  {
149  template< class Functor >
150  static void apply ( Functor &functor, const Patch< dim > &patch )
151  {
152  for( int i = 0; i < patch.count(); ++i )
153  {
154  Element *const father = patch[ i ];
155  functor( father->child[ 0 ], 0 );
156  functor( father->child[ 1 ], 0 );
157  }
158  }
159  };
160 
161  template< int dim >
162  struct ForEachInteriorSubChild< dim, dim >
163  {
164  template< class Functor >
165  static void apply ( Functor &functor, const Patch< dim > &patch )
166  {
167  functor( patch[ 0 ]->child[ 0 ], dim );
168  }
169  };
170 
171  template<>
172  struct ForEachInteriorSubChild< 2, 1 >
173  {
174  template< class Functor >
175  static void apply ( Functor &functor, const Patch< 2 > &patch )
176  {
177  // see alberta/src/2d/lagrange_2_2d.c for details
178  Element *const firstFather = patch[ 0 ];
179 
180  Element *const firstChild = firstFather->child[ 0 ];
181  functor( firstChild, 0 );
182  functor( firstChild, 1 );
183 
184  functor( firstFather->child[ 1 ], 1 );
185 
186  if( patch.count() > 1 )
187  {
188  Element *const father = patch[ 1 ];
189  functor( father->child[ 0 ], 1 );
190  }
191  }
192  };
193 
194  template<>
195  struct ForEachInteriorSubChild< 3, 1 >
196  {
197  template< class Functor >
198  static void apply ( Functor &functor, const Patch< 3 > &patch )
199  {
200  // see alberta/src/3d/lagrange_3_3d.c for details
201  Element *const firstFather = patch[ 0 ];
202 
203  Element *const firstChild = firstFather->child[ 0 ];
204  functor( firstChild, 0 );
205  functor( firstChild, 1 );
206  functor( firstChild, 2 );
207 
208  Element *const secondChild = firstFather->child[ 1 ];
209  functor( secondChild, 1 );
210  functor( secondChild, 2 );
211 
212  for( int i = 1; i < patch.count(); ++i )
213  {
214  Element *const father = patch[ i ];
215  const int type = patch.elementType( i );
216 
217  int lr_set = 0;
218  if( patch.hasNeighbor( i, 0 ) && (patch.neighborIndex( i, 0 ) < i) )
219  lr_set |= 1;
220  if( patch.hasNeighbor( i, 1 ) && (patch.neighborIndex( i, 1 ) < i) )
221  lr_set |= 2;
222  assert( lr_set != 0 );
223 
224  functor( father->child[ 0 ], 0 );
225  switch( lr_set )
226  {
227  case 1:
228  functor( father->child[ 0 ], 2 );
229  functor( father->child[ 1 ], (type == 0 ? 1 : 2) );
230  break;
231 
232  case 2:
233  functor( father->child[ 0 ], 1 );
234  functor( father->child[ 1 ], (type == 0 ? 2 : 1) );
235  break;
236  }
237  }
238  }
239  };
240 
241  template<>
242  struct ForEachInteriorSubChild< 3, 2 >
243  {
244  template< class Functor >
245  static void apply ( Functor &functor, const Patch< 3 > &patch )
246  {
247  // see alberta/src/3d/lagrange_2_3d.c for details
248  Element *const firstFather = patch[ 0 ];
249 
250  Element *const firstChild = firstFather->child[ 0 ];
251  functor( firstChild, 2 );
252  functor( firstChild, 4 );
253  functor( firstChild, 5 );
254 
255  functor( firstFather->child[ 1 ], 2 );
256 
257  for( int i = 1; i < patch.count(); ++i )
258  {
259  Element *const father = patch[ i ];
260 
261  int lr_set = 0;
262  if( patch.hasNeighbor( i, 0 ) && (patch.neighborIndex( i, 0 ) < i) )
263  lr_set = 1;
264  if( patch.hasNeighbor( i, 1 ) && (patch.neighborIndex( i, 1 ) < i) )
265  lr_set += 2;
266  assert( lr_set != 0 );
267 
268  switch( lr_set )
269  {
270  case 1:
271  functor( father->child[ 0 ], 4 );
272  break;
273 
274  case 2:
275  functor( father->child[ 0 ], 5 );
276  break;
277  }
278  }
279  }
280  };
281 
282 
283 
284  // GeometryInFather
285  // ----------------
286 
287  template< int dim >
288  struct GeometryInFather;
289 
290  template<>
291  struct GeometryInFather< 1 >
292  {
293  static const int dim = 1;
294 
295  typedef Real LocalVector[ dim ];
296 
297  static const LocalVector &
298  coordinate ( int child, int orientation, int i )
299  {
300  static const Real coords[ 2 ][ dim+1 ][ dim ]
301  = { { {0.0}, {0.5} }, { {0.5}, {1.0} } };
302  assert( (i >= 0) && (i <= dim) );
303  return coords[ child ][ i ];
304  }
305  };
306 
307  template<>
308  struct GeometryInFather< 2 >
309  {
310  static const int dim = 2;
311 
312  typedef Real LocalVector[ dim ];
313 
314  static const LocalVector &
315  coordinate ( int child, int orientation, int i )
316  {
317  static const Real coords[ 2 ][ dim+1 ][ dim ]
318  = { { {0.0, 1.0}, {0.0, 0.0}, {0.5, 0.0} },
319  { {1.0, 0.0}, {0.0, 1.0}, {0.5, 0.0} } };
320  assert( (i >= 0) && (i <= dim) );
321  return coords[ child ][ i ];
322  }
323  };
324 
325  template<>
326  struct GeometryInFather< 3 >
327  {
328  static const int dim = 3;
329 
330  typedef Real LocalVector[ dim ];
331 
332  static const LocalVector &
333  coordinate ( int child, int orientation, int i )
334  {
335  static const Real coords[ 2 ][ dim+1 ][ dim ]
336  = { { {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {0.5, 0.0, 0.0} },
337  { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {0.5, 0.0, 0.0} } };
338  static const int flip[ 2 ][ 2 ][ dim+1 ]
339  = { { {0, 1, 2, 3}, {0, 1, 2, 3} }, { {0, 2, 1, 3}, {0, 1, 2, 3} } };
340  assert( (i >= 0) && (i <= dim) );
341  i = flip[ child ][ orientation ][ i ];
342  return coords[ child ][ i ];
343  }
344  };
345 
346  }
347 
348 }
349 
350 #endif // #if HAVE_ALBERTA
351 
352 #endif