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 const MeshPointer< 2 > &mesh = levelProvider.mesh();
00144 const Element *element = (*this)[ i ];
00145 const int level = levelProvider( element );
00146 return ElementInfo::createFake( mesh, element, level );
00147 }
00148 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00149
00150
00151 #if DUNE_ALBERTA_VERSION < 0x200
00152 template< int dim >
00153 inline int Patch< dim >::elementType ( int i ) const
00154 {
00155 assert( (i >= 0) && (i < count()) );
00156 #if DIM == 3
00157 return list_[ i ].el_type;
00158 #else
00159 return 0;
00160 #endif
00161 }
00162 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00163
00164 #if DUNE_ALBERTA_VERSION >= 0x200
00165 template< int dim >
00166 inline int Patch< dim >::elementType ( int i ) const
00167 {
00168 assert( (i >= 0) && (i < count()) );
00169 return list_[ i ].el_info.el_type;
00170 }
00171 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00172
00173
00174 #if (DUNE_ALBERTA_VERSION >= 0x200) || (DIM == 3)
00175 template< int dim >
00176 inline bool Patch< dim >::hasNeighbor ( int i, int neighbor ) const
00177 {
00178 return (list_[ i ].neigh[ neighbor ] != NULL);
00179 }
00180
00181 template< int dim >
00182 inline int Patch< dim >::neighborIndex ( int i, int neighbor ) const
00183 {
00184 assert( hasNeighbor( i, neighbor ) );
00185 return (list_[ i ].neigh[ neighbor ]->no);
00186 }
00187 #endif // #if (DUNE_ALBERTA_VERSION >= 0x200) || (DIM == 3)
00188
00189
00190
00191
00192
00193
00194 template< int dim >
00195 struct ForEachInteriorSubChild< dim, 0 >
00196 {
00197 template< class Functor >
00198 static void apply ( Functor &functor, const Patch< dim > &patch )
00199 {
00200 for( int i = 0; i < patch.count(); ++i )
00201 {
00202 Element *const father = patch[ i ];
00203 functor( father->child[ 0 ], 0 );
00204 functor( father->child[ 1 ], 0 );
00205 }
00206 }
00207 };
00208
00209 template< int dim >
00210 struct ForEachInteriorSubChild< dim, dim >
00211 {
00212 template< class Functor >
00213 static void apply ( Functor &functor, const Patch< dim > &patch )
00214 {
00215 functor( patch[ 0 ]->child[ 0 ], dim );
00216 }
00217 };
00218
00219 template<>
00220 struct ForEachInteriorSubChild< 2, 1 >
00221 {
00222 template< class Functor >
00223 static void apply ( Functor &functor, const Patch< 2 > &patch )
00224 {
00225
00226 Element *const firstFather = patch[ 0 ];
00227
00228 Element *const firstChild = firstFather->child[ 0 ];
00229 functor( firstChild, 0 );
00230 functor( firstChild, 1 );
00231
00232 functor( firstFather->child[ 1 ], 1 );
00233
00234 if( patch.count() > 1 )
00235 {
00236 Element *const father = patch[ 1 ];
00237 functor( father->child[ 0 ], 1 );
00238 }
00239 }
00240 };
00241
00242 template<>
00243 struct ForEachInteriorSubChild< 3, 1 >
00244 {
00245 template< class Functor >
00246 static void apply ( Functor &functor, const Patch< 3 > &patch )
00247 {
00248
00249 Element *const firstFather = patch[ 0 ];
00250
00251 Element *const firstChild = firstFather->child[ 0 ];
00252 functor( firstChild, 0 );
00253 functor( firstChild, 1 );
00254 functor( firstChild, 2 );
00255
00256 Element *const secondChild = firstFather->child[ 1 ];
00257 functor( secondChild, 1 );
00258 functor( secondChild, 2 );
00259
00260 for( int i = 1; i < patch.count(); ++i )
00261 {
00262 Element *const father = patch[ i ];
00263 const int type = patch.elementType( i );
00264
00265 int lr_set = 0;
00266 if( patch.hasNeighbor( i, 0 ) && (patch.neighborIndex( i, 0 ) < i) )
00267 lr_set = 1;
00268 if( patch.hasNeighbor( i, 1 ) && (patch.neighborIndex( i, 1 ) < i) )
00269 lr_set += 2;
00270 assert( lr_set != 0 );
00271
00272 functor( father->child[ 0 ], 0 );
00273 switch( lr_set )
00274 {
00275 case 1:
00276 functor( father->child[ 0 ], 2 );
00277 functor( father->child[ 1 ], (type == 0 ? 1 : 2) );
00278 break;
00279
00280 case 2:
00281 functor( father->child[ 0 ], 1 );
00282 functor( father->child[ 1 ], (type == 0 ? 2 : 1) );
00283 break;
00284 }
00285 }
00286 }
00287 };
00288
00289 template<>
00290 struct ForEachInteriorSubChild< 3, 2 >
00291 {
00292 template< class Functor >
00293 static void apply ( Functor &functor, const Patch< 3 > &patch )
00294 {
00295
00296 Element *const firstFather = patch[ 0 ];
00297
00298 Element *const firstChild = firstFather->child[ 0 ];
00299 functor( firstChild, 2 );
00300 functor( firstChild, 4 );
00301 functor( firstChild, 5 );
00302
00303 functor( firstFather->child[ 1 ], 2 );
00304
00305 for( int i = 1; i < patch.count(); ++i )
00306 {
00307 Element *const father = patch[ i ];
00308
00309 int lr_set = 0;
00310 if( patch.hasNeighbor( i, 0 ) && (patch.neighborIndex( i, 0 ) < i) )
00311 lr_set = 1;
00312 if( patch.hasNeighbor( i, 1 ) && (patch.neighborIndex( i, 1 ) < i) )
00313 lr_set += 2;
00314 assert( lr_set != 0 );
00315
00316 switch( lr_set )
00317 {
00318 case 1:
00319 functor( father->child[ 0 ], 4 );
00320 break;
00321
00322 case 2:
00323 functor( father->child[ 0 ], 5 );
00324 break;
00325 }
00326 }
00327 }
00328 };
00329
00330
00331
00332
00333
00334
00335 template< int dim >
00336 struct GeometryInFather;
00337
00338 template<>
00339 struct GeometryInFather< 1 >
00340 {
00341 static const int dim = 1;
00342
00343 typedef Real LocalVector[ dim ];
00344
00345 static const LocalVector &
00346 coordinate ( int child, int orientation, int i )
00347 {
00348 static const Real coords[ 2 ][ dim+1 ][ dim ]
00349 = { { {0.0}, {0.5} }, { {0.5}, {1.0} } };
00350 assert( (i >= 0) && (i <= dim) );
00351 return coords[ child ][ i ];
00352 }
00353 };
00354
00355 template<>
00356 struct GeometryInFather< 2 >
00357 {
00358 static const int dim = 2;
00359
00360 typedef Real LocalVector[ dim ];
00361
00362 static const LocalVector &
00363 coordinate ( int child, int orientation, int i )
00364 {
00365 static const Real coords[ 2 ][ dim+1 ][ dim ]
00366 = { { {0.0, 1.0}, {0.0, 0.0}, {0.5, 0.0} },
00367 { {1.0, 0.0}, {0.0, 1.0}, {0.5, 0.0} } };
00368 assert( (i >= 0) && (i <= dim) );
00369 return coords[ child ][ i ];
00370 }
00371 };
00372
00373 template<>
00374 struct GeometryInFather< 3 >
00375 {
00376 static const int dim = 3;
00377
00378 typedef Real LocalVector[ dim ];
00379
00380 static const LocalVector &
00381 coordinate ( int child, int orientation, int i )
00382 {
00383 static const Real coords[ 2 ][ dim+1 ][ dim ]
00384 = { { {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {0.5, 0.0, 0.0} },
00385 { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {0.5, 0.0, 0.0} } };
00386 static const int flip[ 2 ][ 2 ][ dim+1 ]
00387 = { { {0, 1, 2, 3}, {0, 1, 2, 3} }, { {0, 2, 1, 3}, {0, 1, 2, 3} } };
00388 assert( (i >= 0) && (i <= dim) );
00389 i = flip[ child ][ orientation ][ i ];
00390 return coords[ child ][ i ];
00391 }
00392 };
00393
00394 }
00395
00396 }
00397
00398 #endif // #if HAVE_ALBERTA
00399
00400 #endif