albertagrid/refinement.hh

Go to the documentation of this file.
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     // Internal Forward Declarations
00024     // -----------------------------
00025 
00026     template< int dim, int codim >
00027     struct ForEachInteriorSubChild;
00028 
00029 
00030 
00031     // Patch
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     // ForEachInteriorSubChild
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         // see alberta/src/2d/lagrange_2_2d.c for details
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         // see alberta/src/3d/lagrange_3_3d.c for details
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         // see alberta/src/3d/lagrange_2_3d.c for details
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     // GeometryInFather
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

Generated on Tue Jul 28 22:28:20 2009 for dune-grid by  doxygen 1.5.6