macrodata.hh

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

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