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       // in 2d, only the first el_info structure is fully valid!
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     // ForEachInteriorSubChild
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         // see alberta/src/2d/lagrange_2_2d.c for details
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         // see alberta/src/3d/lagrange_3_3d.c for details
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         // see alberta/src/3d/lagrange_2_3d.c for details
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     // GeometryInFather
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

Generated on Thu Apr 2 10:40:43 2009 for dune-grid by  doxygen 1.5.6