macrodata.hh

00001 #ifndef DUNE_ALBERTA_MACRODATA_HH
00002 #define DUNE_ALBERTA_MACRODATA_HH
00003 
00004 #include <dune/common/fvector.hh>
00005 #include <dune/common/fmatrix.hh>
00006 
00007 #include <dune/grid/albertagrid/misc.hh>
00008 #include <dune/grid/albertagrid/albertaheader.hh>
00009 #include <dune/grid/albertagrid/referencetopo.hh>
00010 
00011 #if HAVE_ALBERTA
00012 
00013 namespace Dune
00014 {
00015 
00016   namespace Alberta
00017   {
00018 
00019     template< int dim >
00020     class MacroData
00021     {
00022       typedef MacroData< dim > This;
00023 
00024       typedef ALBERTA MACRO_DATA Data;
00025 
00026       static const int dimension = dim;
00027       static const int numVertices = NumSubEntities< dimension, dimension >::value;
00028       static const int numEdges = NumSubEntities< dimension, dimension-1 >::value;
00029 
00030       static const int initialSize = 4096;
00031 
00032     public:
00033       typedef int ElementId[ numVertices ];
00034 
00035       static const int supportPeriodicity = (DUNE_ALBERTA_VERSION >= 0x201);
00036 
00037     private:
00038       Data *data_;
00039       int vertexCount_;
00040       int elementCount_;
00041 
00042     public:
00043       MacroData ()
00044       : data_( NULL ),
00045         vertexCount_( -1 ),
00046         elementCount_( -1 )
00047       {}
00048 
00049       operator Data * () const
00050       {
00051         return data_;
00052       }
00053 
00054       int vertexCount () const
00055       {
00056         return (vertexCount_ < 0 ? data_->n_total_vertices : vertexCount_);
00057       }
00058 
00059       int elementCount () const
00060       {
00061         return (elementCount_ < 0 ? data_->n_macro_elements : elementCount_);
00062       }
00063 
00064       ElementId &element ( int i ) const;
00065       GlobalVector &vertex ( int i ) const;
00066       int &neighbor ( int element, int i ) const;
00067       BoundaryId &boundaryId ( int element, int i ) const;
00068 
00073       void create ();
00074 
00083       void finalize ();
00084 
00093       void markLongestEdge ();
00094 
00096       void release ()
00097       {
00098         if( data_ != NULL )
00099         {
00100           ALBERTA free_macro_data( data_ );
00101           data_ = NULL;
00102         }
00103         vertexCount_ = elementCount_ = -1;
00104       }
00105 
00111       int insertElement ( const ElementId &id )
00112       {
00113         assert( elementCount_ >= 0 );
00114         if( elementCount_ >= data_->n_macro_elements )
00115           resizeElements( 2*elementCount_ );
00116 
00117         ElementId &e = element( elementCount_ );
00118         for( int i = 0; i < numVertices; ++i )
00119         {
00120           e[ i ] = id[ i ];
00121           boundaryId( elementCount_, i ) = InteriorBoundary;
00122         }
00123 
00124         return elementCount_++;
00125       }
00126 
00132       int insertVertex ( const GlobalVector &coords )
00133       {
00134         assert( vertexCount_ >= 0 );
00135         if( vertexCount_ >= data_->n_total_vertices )
00136           resizeVertices( 2*vertexCount_ );
00137         copy( coords, vertex( vertexCount_ ) );
00138         return vertexCount_++;
00139       }
00140 
00146       int insertVertex ( const FieldVector< Real, dimWorld > &coords )
00147       {
00148         assert( vertexCount_ >= 0 );
00149         if( vertexCount_ >= data_->n_total_vertices )
00150           resizeVertices( 2*vertexCount_ );
00151         copy( coords, vertex( vertexCount_ ) );
00152         return vertexCount_++;
00153       }
00154 
00155       void insertWallTrafo ( const GlobalMatrix &m, const GlobalVector &t );
00156       void insertWallTrafo ( const FieldMatrix< Real, dimWorld, dimWorld > &matrix,
00157                              const FieldVector< Real, dimWorld > &shift );
00158 
00159       void read ( const std::string &filename, bool binary = false );
00160 
00161       bool write ( const std::string &filename, bool binary = false ) const
00162       {
00163         if( binary )
00164           return ALBERTA write_macro_data_xdr( data_, filename.c_str() );
00165         else
00166           return ALBERTA write_macro_data( data_, filename.c_str() );
00167       }
00168 
00169     private:
00170       Real edgeLength ( const ElementId &e, int edge ) const;
00171       int longestEdge ( const ElementId &e ) const;
00172 
00173       template< class Vector >
00174       void copy ( const Vector &x, GlobalVector &y )
00175       {
00176         for( int i = 0; i < dimWorld; ++i )
00177           y[ i ] = x[ i ];
00178       }
00179 
00180 #if DUNE_ALBERTA_VERSION >= 0x200
00181       template< class Type >
00182       void rotate ( Type *array, int i, int shift );
00183 #else
00184       template< class Type >
00185       void rotate ( Type (*array)[ numVertices ], int i, int shift );
00186 #endif
00187 
00188       void resizeElements ( const int newSize );
00189 
00190       void resizeVertices ( const int newSize )
00191       {
00192         const int oldSize = data_->n_total_vertices;
00193         data_->n_total_vertices = newSize;
00194         data_->coords = memReAlloc< GlobalVector >( data_->coords, oldSize, newSize );
00195         assert( (data_->coords != NULL) || (newSize == 0) );
00196       }
00197     };
00198 
00199 
00200 #if DUNE_ALBERTA_VERSION >= 0x200
00201     template< int dim >
00202     inline typename MacroData< dim >::ElementId &
00203     MacroData< dim >::element ( int i ) const
00204     {
00205       assert( (i >= 0) && (i < data_->n_macro_elements) );
00206       const int offset = i * numVertices;
00207       return *reinterpret_cast< ElementId * >( data_->mel_vertices + offset );
00208     }
00209 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00210 
00211 #if DUNE_ALBERTA_VERSION < 0x200
00212     template< int dim >
00213     inline typename MacroData< dim >::ElementId &
00214     MacroData< dim >::element ( int i ) const
00215     {
00216       assert( (i >= 0) && (i < data_->n_macro_elements) );
00217       return data_->mel_vertices[ i ];
00218     }
00219 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00220 
00221 
00222     template< int dim >
00223     inline GlobalVector &MacroData< dim >::vertex ( int i ) const
00224     {
00225       assert( (i >= 0) && (i < data_->n_total_vertices) );
00226       return data_->coords[ i ];
00227     }
00228 
00229 
00230 #if DUNE_ALBERTA_VERSION >= 0x200
00231     template< int dim >
00232     inline int &MacroData< dim >::neighbor ( int element, int i ) const
00233     {
00234       assert( (element >= 0) && (element < data_->n_macro_elements) );
00235       assert( (i >= 0) && (i < numVertices) );
00236       return data_->neigh[ element*numVertices + i ];
00237     }
00238 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00239 
00240 #if DUNE_ALBERTA_VERSION < 0x200
00241     template< int dim >
00242     inline int &MacroData< dim >::neighbor ( int element, int i ) const
00243     {
00244       assert( (element >= 0) && (element < data_->n_macro_elements) );
00245       assert( (i >= 0) && (i < numVertices) );
00246       return data_->neigh[ element ][ i ];
00247     }
00248 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00249 
00250 
00251 #if DUNE_ALBERTA_VERSION >= 0x200
00252     template< int dim >
00253     inline BoundaryId &MacroData< dim >::boundaryId ( int element, int i ) const
00254     {
00255       assert( (element >= 0) && (element < data_->n_macro_elements) );
00256       assert( (i >= 0) && (i < numVertices) );
00257       return data_->boundary[ element*numVertices + i ];
00258     }
00259 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00260 
00261 #if DUNE_ALBERTA_VERSION < 0x200
00262     template< int dim >
00263     inline BoundaryId &MacroData< dim >::boundaryId ( int element, int i ) const
00264     {
00265       assert( (element >= 0) && (element < data_->n_macro_elements) );
00266       assert( (i >= 0) && (i < numVertices) );
00267       return data_->boundary[ element ][ i ];
00268     }
00269 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00270 
00271 
00272 #if DUNE_ALBERTA_VERSION >= 0x201
00273     template< int dim >
00274     inline void MacroData< dim >::create ()
00275     {
00276       release();
00277       data_ = ALBERTA alloc_macro_data( dim, initialSize, initialSize );
00278       data_->boundary = memAlloc< BoundaryId >( initialSize*numVertices );
00279       vertexCount_ = elementCount_ = 0;
00280       elementCount_ = 0;
00281     }
00282 #endif // #if DUNE_ALBERTA_VERSION >= 0x201
00283 
00284 #if DUNE_ALBERTA_VERSION == 0x200
00285     template< int dim >
00286     inline void MacroData< dim >::create ()
00287     {
00288       release();
00289       data_ = ALBERTA alloc_macro_data( dim, initialSize, initialSize, 0 );
00290       data_->boundary = memAlloc< BoundaryId >( initialSize*numVertices );
00291       vertexCount_ = elementCount_ = 0;
00292       elementCount_ = 0;
00293     }
00294 #endif // #if DUNE_ALBERTA_VERSION == 0x200
00295 
00296 #if DUNE_ALBERTA_VERSION < 0x200
00297     template< int dim >
00298     inline void MacroData< dim >::create ()
00299     {
00300       dune_static_assert( dimension == dimGrid,
00301                           "Wrong grid dimension used for ALBERTA 1.2." );
00302       release();
00303       data_ = ALBERTA alloc_macro_data( initialSize, initialSize, 0 );
00304       data_->boundary = memAlloc< BoundaryId[ numVertices ] >( initialSize );
00305       vertexCount_ = elementCount_ = 0;
00306       elementCount_ = 0;
00307     }
00308 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00309 
00310 
00311 #if DUNE_ALBERTA_VERSION >= 0x200
00312     template< int dim >
00313     inline void MacroData< dim >::finalize ()
00314     {
00315       if( (vertexCount_ >= 0) && (elementCount_ >= 0) )
00316       {
00317         resizeVertices( vertexCount_ );
00318         resizeElements( elementCount_ );
00319         ALBERTA compute_neigh_fast( data_ );
00320 
00321         // assign default boundary id (if none is assigned)
00322         for( int element = 0; element < elementCount_; ++element )
00323         {
00324           for( int i = 0; i < numVertices; ++i )
00325           {
00326             BoundaryId &id = boundaryId( element, i );
00327             if( neighbor( element, i ) >= 0 )
00328             {
00329               assert( id == InteriorBoundary );
00330               id = InteriorBoundary;
00331             }
00332             else
00333               id = (id == InteriorBoundary ? DirichletBoundary : id);
00334           }
00335         }
00336 
00337         vertexCount_ = elementCount_ = -1;
00338       }
00339       assert( (vertexCount_ < 0) && (elementCount_ < 0) );
00340     }
00341 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00342 
00343 #if DUNE_ALBERTA_VERSION < 0x200
00344     template< int dim >
00345     inline void MacroData< dim >::finalize ()
00346     {
00347       if( (vertexCount_ >= 0) && (elementCount_ >= 0) )
00348       {
00349         resizeVertices( vertexCount_ );
00350         resizeElements( elementCount_ );
00351 
00352         std::cerr << "Warning: GridFactory for ALBERTA 1.2 does not support "
00353                   << "boundary ids, yet." << std::endl << std::endl;
00354         memFree( data_->boundary, elementCount_ );
00355         data_->boundary = NULL;
00356 
00357         vertexCount_ = elementCount_ = -1;
00358       }
00359       assert( (vertexCount_ < 0) && (elementCount_ < 0) );
00360     }
00361 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00362 
00363 
00364     template< int dim >
00365     inline void MacroData< dim >::markLongestEdge ()
00366     {
00367       assert( data_ != NULL );
00368       if( dimension == 1 )
00369         return;
00370 
00371       const int count = elementCount();
00372       for( int i = 0; i < count; ++i )
00373       {
00374         const int refEdge = RefinementEdge< dimension >::value;
00375         const int edge = longestEdge( element( i ) );
00376         if( edge == refEdge )
00377           continue;
00378 
00379         // shift vertices such that the refinement edge is the longest edge
00380         const int shift = edge + (numVertices - refEdge);
00381 
00382         // rotate necessary fields
00383         rotate( data_->mel_vertices, i, shift );
00384 
00385         // correct opposite vertices
00386 #if DUNE_ALBERTA_VERSION >= 0x201
00387         if( data_->opp_vertex != NULL )
00388         {
00389           assert( data_->neigh != NULL );
00390           const int shiftBack = numVertices - (shift % numVertices);
00391           for( int j = 0; j < numVertices; ++j )
00392           {
00393             const int nb = data_->neigh[ i*numVertices + j ];
00394             if( nb < 0 )
00395               continue;
00396             const int ov = data_->opp_vertex[ i*numVertices + j ];
00397             assert( data_->neigh[ nb*numVertices + ov ] == i );
00398             assert( data_->opp_vertex[ nb*numVertices + ov ] == j );
00399             data_->opp_vertex[ nb*numVertices + ov ] = (j+shiftBack) % numVertices;
00400           }
00401           rotate( data_->opp_vertex, i, shift );
00402         }
00403 #endif
00404 
00405         // correct neighbors and boundaries
00406         rotate( data_->neigh, i, shift );
00407         rotate( data_->boundary, i, shift );
00408       }
00409     }
00410 
00411 
00412 #if DUNE_ALBERTA_VERSION >= 0x201
00413     template< int dim >
00414     inline void MacroData< dim >
00415       ::insertWallTrafo ( const GlobalMatrix &matrix, const GlobalVector &shift )
00416     {
00417       int &count = data_->n_wall_trafos;
00418       AffineTransformation *&array = data_->wall_trafos;
00419 
00420       // resize wall trafo array
00421       array = memReAlloc< AffineTransformation >( array, count, count+1 );
00422       assert( data_->wall_trafos != NULL );
00423 
00424       // copy matrix and shift
00425       for( int i = 0; i < dimWorld; ++i )
00426         copy( matrix[ i ], array[ count ].M[ i ] );
00427       copy( shift, array[ count ].t );
00428       ++count;
00429     }
00430       
00431     template< int dim >
00432     inline void MacroData< dim >
00433       ::insertWallTrafo ( const FieldMatrix< Real, dimWorld, dimWorld > &matrix,
00434                           const FieldVector< Real, dimWorld > &shift )
00435     {
00436       int &count = data_->n_wall_trafos;
00437       AffineTransformation *&array = data_->wall_trafos;
00438 
00439       // resize wall trafo array
00440       array = memReAlloc< AffineTransformation >( array, count, count+1 );
00441       assert( data_->wall_trafos != NULL );
00442 
00443       // copy matrix and shift
00444       for( int i = 0; i < dimWorld; ++i )
00445         copy( matrix[ i ], array[ count ].M[ i ] );
00446       copy( shift, array[ count ].t );
00447       ++count;
00448     }
00449 #endif // #if DUNE_ALBERTA_VERSION >= 0x201
00450 
00451 #if DUNE_ALBERTA_VERSION <= 0x200
00452     template< int dim >
00453     inline void MacroData< dim >
00454       ::insertWallTrafo ( const GlobalMatrix &m, const GlobalVector &t )
00455     {
00456       DUNE_THROW( AlbertaError,
00457                   "Periodic grids are only supported in ALBERTA 2.1 or higher." );
00458     }
00459 
00460     template< int dim >
00461     inline void MacroData< dim >
00462       ::insertWallTrafo ( const FieldMatrix< Real, dimWorld, dimWorld > &matrix,
00463                           const FieldVector< Real, dimWorld > &shift )
00464     {
00465       DUNE_THROW( AlbertaError,
00466                   "Periodic grids are only supported in ALBERTA 2.1 or higher." );
00467     }
00468 #endif // #if DUNE_ALBERTA_VERSION <= 0x200
00469 
00470 
00471 #if DUNE_ALBERTA_VERSION >= 0x200
00472     template< int dim >
00473     inline void MacroData< dim >::read ( const std::string &filename, bool binary )
00474     {
00475       release();
00476       if( binary )
00477         data_ = ALBERTA read_macro_xdr( filename.c_str() );
00478       else
00479         data_ = ALBERTA read_macro( filename.c_str() );
00480     }
00481 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00482 
00483 #if DUNE_ALBERTA_VERSION < 0x200
00484     template< int dim >
00485     inline void MacroData< dim >::read ( const std::string &filename, bool binary )
00486     {
00487       release();
00488       DUNE_THROW( NotImplemented, "In ALBERTA 1.2, macro data cannot be read." );
00489     }
00490 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00491 
00492 
00493     template< int dim >
00494     inline Real MacroData< dim >::edgeLength ( const ElementId &e, int edge ) const
00495     {
00496       const int i = ALBERTA AlbertHelp::MapVertices< 1, dim >::mapVertices( edge, 0 );
00497       assert( (vertexCount_ < 0) || (e[ i ] < vertexCount_) );
00498       const GlobalVector &x = vertex( e[ i ] );
00499 
00500       const int j = ALBERTA AlbertHelp::MapVertices< 1, dim >::mapVertices( edge, 1 );
00501       assert( (vertexCount_ < 0) || (e[ j ] < vertexCount_) );
00502       const GlobalVector &y = vertex( e[ j ] );
00503 
00504       Real sum = (y[ 0 ] - x[ 0 ]) * (y[ 0 ] - x[ 0 ]);
00505       for( int i = 1; i < dimWorld; ++i )
00506         sum += (y[ i ] - x[ i ]) * (y[ i ] - x[ i ]);
00507       return sqrt( sum );
00508     }
00509 
00510 
00511     template< int dim >
00512     inline int MacroData< dim >::longestEdge ( const ElementId &e ) const
00513     {
00514       int maxEdge = 0;
00515       Real maxLength = edgeLength( e, 0 );
00516       for( int i = 1; i < numEdges; ++i )
00517       {
00518         const Real length = edgeLength( e, i );
00519         if( length <= maxLength )
00520           continue;
00521         maxEdge = i;
00522         maxLength = length;
00523       }
00524       return maxEdge;
00525     }
00526 
00527 
00528 #if DUNE_ALBERTA_VERSION >= 0x200
00529     template< int dim >
00530     template< class Type >
00531     inline void MacroData< dim >::rotate ( Type *array, int i, int shift )
00532     {
00533       assert( (i >= 0) && (i < data_->n_macro_elements) );
00534       if( array == NULL )
00535         return;
00536 
00537       const int offset = i*numVertices;
00538       Type old[ numVertices ];
00539       for( int j = 0; j < numVertices; ++j )
00540         old[ j ] = array[ offset + j ];
00541       for( int j = 0; j < numVertices; ++j )
00542         array[ offset + j ] = old[ (j+shift) % numVertices ];
00543     }
00544 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00545 
00546 #if DUNE_ALBERTA_VERSION < 0x200
00547     template< int dim >
00548     template< class Type >
00549     inline void MacroData< dim >::rotate ( Type (*array)[ numVertices ], int i, int shift )
00550     {
00551       assert( (i >= 0) && (i < data_->n_macro_elements) );
00552       if( array == NULL )
00553         return;
00554 
00555       Type old[ numVertices ];
00556       for( int j = 0; j < numVertices; ++j )
00557         old[ j ] = array[ i ][ j ];
00558       for( int j = 0; j < numVertices; ++j )
00559         array[ i ][ j ] = old[ (j+shift) % numVertices ];
00560     }
00561 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00562 
00563 
00564 #if DUNE_ALBERTA_VERSION >= 0x200
00565     template< int dim >
00566     inline void MacroData< dim >::resizeElements ( const int newSize )
00567     {
00568       const int oldSize = data_->n_macro_elements;
00569       data_->n_macro_elements = newSize;
00570       data_->mel_vertices = memReAlloc( data_->mel_vertices, oldSize*numVertices, newSize*numVertices );
00571       data_->boundary = memReAlloc( data_->boundary, oldSize*numVertices, newSize*numVertices );
00572       assert( (newSize == 0) || (data_->mel_vertices != NULL) );
00573     }
00574 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00575 
00576 #if DUNE_ALBERTA_VERSION < 0x200
00577     template< int dim >
00578     inline void MacroData< dim >::resizeElements ( const int newSize )
00579     {
00580       const int oldSize = data_->n_macro_elements;
00581       data_->n_macro_elements = newSize;
00582       data_->mel_vertices = memReAlloc( data_->mel_vertices, oldSize, newSize );
00583       assert( data_->mel_vertices != NULL );
00584     }
00585 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00586 
00587   }
00588 
00589 }
00590 
00591 #endif // #if HAVE_ALBERTA
00592 
00593 #endif

Generated on Sun Nov 15 22:28:42 2009 for dune-grid by  doxygen 1.5.6