00001 #ifndef DUNE_ALBERTA_REFINEMENT_HH
00002 #define DUNE_ALBERTA_REFINEMENT_HH
00003
00010 #include <cassert>
00011
00012 #include <dune/grid/albertagrid/misc.hh>
00013 #include <dune/grid/albertagrid/elementinfo.hh>
00014
00015 #if HAVE_ALBERTA
00016
00017 namespace Dune
00018 {
00019
00020 namespace Alberta
00021 {
00022
00023
00024
00025
00026 template< int dim, int codim >
00027 struct ForEachInteriorSubChild;
00028
00029
00030
00031
00032
00033
00034 template< int dim >
00035 class Patch
00036 {
00037 typedef Patch< dim > This;
00038
00039 dune_static_assert( ((dim >= 1) && (dim <= 3)),
00040 "Alberta supports only dimensions 1, 2, 3" );
00041
00042 public:
00043 static const int dimension = dim;
00044
00045 typedef Alberta::ElementInfo< dimension > ElementInfo;
00046
00047 typedef ALBERTA RC_LIST_EL ElementList;
00048
00049 private:
00050 ElementList *list_;
00051 int count_;
00052
00053 public:
00054 Patch ( ElementList *list, int count )
00055 : list_( list ),
00056 count_( count )
00057 {
00058 assert( count > 0 );
00059 }
00060
00061 Element *operator[] ( int i ) const;
00062
00063 int count () const
00064 {
00065 return count_;
00066 }
00067
00068 template< class LevelProvider >
00069 ElementInfo elementInfo ( int i, const LevelProvider &levelProvider ) const;
00070
00071 int elementType ( int i ) const;
00072 bool hasNeighbor ( int i, int neighbor ) const;
00073 int neighborIndex ( int i, int neighbor ) const;
00074
00075 template< class Functor >
00076 void forEach ( Functor &functor ) const
00077 {
00078 for( int i = 0; i < count(); ++i )
00079 functor( (*this)[ i ] );
00080 }
00081
00082 template< class Functor >
00083 void forEachInteriorSubChild ( Functor &functor ) const
00084 {
00085 const int codim = Functor::codimension;
00086 ForEachInteriorSubChild< dim, codim >::apply( functor, *this );
00087 }
00088 };
00089
00090
00091 #if DUNE_ALBERTA_VERSION < 0x200
00092 template< int dim >
00093 inline Element *Patch< dim >::operator[] ( int i ) const
00094 {
00095 assert( (i >= 0) && (i < count()) );
00096 return list_[ i ].el;
00097 }
00098 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00099
00100 #if DUNE_ALBERTA_VERSION >= 0x200
00101 template< int dim >
00102 inline Element *Patch< dim >::operator[] ( int i ) const
00103 {
00104 assert( (i >= 0) && (i < count()) );
00105 return list_[ i ].el_info.el;
00106 }
00107 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00108
00109
00110 #if (DUNE_ALBERTA_VERSION < 0x200)
00111 template< int dim >
00112 template< class LevelProvider >
00113 inline typename Patch< dim >::ElementInfo
00114 Patch< dim >::elementInfo ( int i, const LevelProvider &levelProvider ) const
00115 {
00116 const MeshPointer< dim > &mesh = levelProvider.mesh();
00117 const Element *element = (*this)[ i ];
00118 const int level = levelProvider( element );
00119 #if (DIM == 3)
00120 return ElementInfo::createFake( mesh, element, level, list_[ i ].el_type );
00121 #else
00122 return ElementInfo::createFake( mesh, element, level );
00123 #endif
00124 }
00125 #endif // #if (DUNE_ALBERTA_VERSION < 0x200)
00126
00127 #if DUNE_ALBERTA_VERSION >= 0x200
00128 template< int dim >
00129 template< class LevelProvider >
00130 inline typename Patch< dim >::ElementInfo
00131 Patch< dim >::elementInfo ( int i, const LevelProvider &levelProvider ) const
00132 {
00133 assert( (i >= 0) && (i < count()) );
00134 return ElementInfo::createFake( list_[ i ].el_info );
00135 }
00136
00137 template<>
00138 template< class LevelProvider >
00139 inline typename Patch< 2 >::ElementInfo
00140 Patch< 2 >::elementInfo ( int i, const LevelProvider &levelProvider ) const
00141 {
00142 assert( (i >= 0) && (i < count()) );
00143
00144 if( i > 0 )
00145 {
00146 const MeshPointer< 2 > &mesh = levelProvider.mesh();
00147 const Element *element = (*this)[ i ];
00148 const int level = levelProvider( element );
00149 return ElementInfo::createFake( mesh, element, level );
00150 }
00151 else
00152 return ElementInfo::createFake( list_[ 0 ].el_info );
00153 }
00154 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00155
00156
00157 #if DUNE_ALBERTA_VERSION < 0x200
00158 template< int dim >
00159 inline int Patch< dim >::elementType ( int i ) const
00160 {
00161 assert( (i >= 0) && (i < count()) );
00162 #if DIM == 3
00163 return list_[ i ].el_type;
00164 #else
00165 return 0;
00166 #endif
00167 }
00168 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00169
00170 #if DUNE_ALBERTA_VERSION >= 0x200
00171 template< int dim >
00172 inline int Patch< dim >::elementType ( int i ) const
00173 {
00174 assert( (i >= 0) && (i < count()) );
00175 return list_[ i ].el_info.el_type;
00176 }
00177 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00178
00179
00180 #if (DUNE_ALBERTA_VERSION >= 0x200) || (DIM == 3)
00181 template< int dim >
00182 inline bool Patch< dim >::hasNeighbor ( int i, int neighbor ) const
00183 {
00184 return (list_[ i ].neigh[ neighbor ] != NULL);
00185 }
00186
00187 template< int dim >
00188 inline int Patch< dim >::neighborIndex ( int i, int neighbor ) const
00189 {
00190 assert( hasNeighbor( i, neighbor ) );
00191 return (list_[ i ].neigh[ neighbor ]->no);
00192 }
00193 #endif // #if (DUNE_ALBERTA_VERSION >= 0x200) || (DIM == 3)
00194
00195
00196
00197
00198
00199
00200 template< int dim >
00201 struct ForEachInteriorSubChild< dim, 0 >
00202 {
00203 template< class Functor >
00204 static void apply ( Functor &functor, const Patch< dim > &patch )
00205 {
00206 for( int i = 0; i < patch.count(); ++i )
00207 {
00208 Element *const father = patch[ i ];
00209 functor( father->child[ 0 ], 0 );
00210 functor( father->child[ 1 ], 0 );
00211 }
00212 }
00213 };
00214
00215 template< int dim >
00216 struct ForEachInteriorSubChild< dim, dim >
00217 {
00218 template< class Functor >
00219 static void apply ( Functor &functor, const Patch< dim > &patch )
00220 {
00221 functor( patch[ 0 ]->child[ 0 ], dim );
00222 }
00223 };
00224
00225 template<>
00226 struct ForEachInteriorSubChild< 2, 1 >
00227 {
00228 template< class Functor >
00229 static void apply ( Functor &functor, const Patch< 2 > &patch )
00230 {
00231
00232 Element *const firstFather = patch[ 0 ];
00233
00234 Element *const firstChild = firstFather->child[ 0 ];
00235 functor( firstChild, 0 );
00236 functor( firstChild, 1 );
00237
00238 functor( firstFather->child[ 1 ], 1 );
00239
00240 if( patch.count() > 1 )
00241 {
00242 Element *const father = patch[ 1 ];
00243 functor( father->child[ 0 ], 1 );
00244 }
00245 }
00246 };
00247
00248 template<>
00249 struct ForEachInteriorSubChild< 3, 1 >
00250 {
00251 template< class Functor >
00252 static void apply ( Functor &functor, const Patch< 3 > &patch )
00253 {
00254
00255 Element *const firstFather = patch[ 0 ];
00256
00257 Element *const firstChild = firstFather->child[ 0 ];
00258 functor( firstChild, 0 );
00259 functor( firstChild, 1 );
00260 functor( firstChild, 2 );
00261
00262 Element *const secondChild = firstFather->child[ 1 ];
00263 functor( secondChild, 1 );
00264 functor( secondChild, 2 );
00265
00266 for( int i = 1; i < patch.count(); ++i )
00267 {
00268 Element *const father = patch[ i ];
00269 const int type = patch.elementType( i );
00270
00271 int lr_set = 0;
00272 if( patch.hasNeighbor( i, 0 ) && (patch.neighborIndex( i, 0 ) < i) )
00273 lr_set = 1;
00274 if( patch.hasNeighbor( i, 1 ) && (patch.neighborIndex( i, 1 ) < i) )
00275 lr_set += 2;
00276 assert( lr_set != 0 );
00277
00278 functor( father->child[ 0 ], 0 );
00279 switch( lr_set )
00280 {
00281 case 1:
00282 functor( father->child[ 0 ], 2 );
00283 functor( father->child[ 1 ], (type == 0 ? 1 : 2) );
00284 break;
00285
00286 case 2:
00287 functor( father->child[ 0 ], 1 );
00288 functor( father->child[ 1 ], (type == 0 ? 2 : 1) );
00289 break;
00290 }
00291 }
00292 }
00293 };
00294
00295 template<>
00296 struct ForEachInteriorSubChild< 3, 2 >
00297 {
00298 template< class Functor >
00299 static void apply ( Functor &functor, const Patch< 3 > &patch )
00300 {
00301
00302 Element *const firstFather = patch[ 0 ];
00303
00304 Element *const firstChild = firstFather->child[ 0 ];
00305 functor( firstChild, 2 );
00306 functor( firstChild, 4 );
00307 functor( firstChild, 5 );
00308
00309 functor( firstFather->child[ 1 ], 2 );
00310
00311 for( int i = 1; i < patch.count(); ++i )
00312 {
00313 Element *const father = patch[ i ];
00314
00315 int lr_set = 0;
00316 if( patch.hasNeighbor( i, 0 ) && (patch.neighborIndex( i, 0 ) < i) )
00317 lr_set = 1;
00318 if( patch.hasNeighbor( i, 1 ) && (patch.neighborIndex( i, 1 ) < i) )
00319 lr_set += 2;
00320 assert( lr_set != 0 );
00321
00322 switch( lr_set )
00323 {
00324 case 1:
00325 functor( father->child[ 0 ], 4 );
00326 break;
00327
00328 case 2:
00329 functor( father->child[ 0 ], 5 );
00330 break;
00331 }
00332 }
00333 }
00334 };
00335
00336
00337
00338
00339
00340
00341 template< int dim >
00342 struct GeometryInFather;
00343
00344 template<>
00345 struct GeometryInFather< 1 >
00346 {
00347 static const int dim = 1;
00348
00349 typedef Real LocalVector[ dim ];
00350
00351 static const LocalVector &
00352 coordinate ( int child, int orientation, int i )
00353 {
00354 static const Real coords[ 2 ][ dim+1 ][ dim ]
00355 = { { {0.0}, {0.5} }, { {0.5}, {1.0} } };
00356 assert( (i >= 0) && (i <= dim) );
00357 return coords[ child ][ i ];
00358 }
00359 };
00360
00361 template<>
00362 struct GeometryInFather< 2 >
00363 {
00364 static const int dim = 2;
00365
00366 typedef Real LocalVector[ dim ];
00367
00368 static const LocalVector &
00369 coordinate ( int child, int orientation, int i )
00370 {
00371 static const Real coords[ 2 ][ dim+1 ][ dim ]
00372 = { { {0.0, 1.0}, {0.0, 0.0}, {0.5, 0.0} },
00373 { {1.0, 0.0}, {0.0, 1.0}, {0.5, 0.0} } };
00374 assert( (i >= 0) && (i <= dim) );
00375 return coords[ child ][ i ];
00376 }
00377 };
00378
00379 template<>
00380 struct GeometryInFather< 3 >
00381 {
00382 static const int dim = 3;
00383
00384 typedef Real LocalVector[ dim ];
00385
00386 static const LocalVector &
00387 coordinate ( int child, int orientation, int i )
00388 {
00389 static const Real coords[ 2 ][ dim+1 ][ dim ]
00390 = { { {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {0.5, 0.0, 0.0} },
00391 { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {0.5, 0.0, 0.0} } };
00392 static const int flip[ 2 ][ 2 ][ dim+1 ]
00393 = { { {0, 1, 2, 3}, {0, 1, 2, 3} }, { {0, 2, 1, 3}, {0, 1, 2, 3} } };
00394 assert( (i >= 0) && (i <= dim) );
00395 i = flip[ child ][ orientation ][ i ];
00396 return coords[ child ][ i ];
00397 }
00398 };
00399
00400 }
00401
00402 }
00403
00404 #endif // #if HAVE_ALBERTA
00405
00406 #endif