00001 #ifndef DUNE_ALBERTA_MESHPOINTER_HH
00002 #define DUNE_ALBERTA_MESHPOINTER_HH
00003
00009 #include <cassert>
00010 #include <string>
00011
00012 #include <dune/grid/albertagrid/misc.hh>
00013 #include <dune/grid/albertagrid/elementinfo.hh>
00014 #include <dune/grid/albertagrid/albertaextra.hh>
00015 #include <dune/grid/albertagrid/macrodata.hh>
00016
00017 #if HAVE_ALBERTA
00018
00019 namespace Dune
00020 {
00021
00022 namespace Alberta
00023 {
00024
00025
00026
00027
00028 template< int dim >
00029 class HierarchyDofNumbering;
00030
00031
00032
00033
00034
00035
00036 template< int dim >
00037 class MeshPointer
00038 {
00039 Mesh *mesh_;
00040
00041 typedef Alberta::ElementInfo< dim > ElementInfo;
00042 typedef typename ElementInfo::FillFlags FillFlags;
00043
00044 class BoundaryProvider;
00045 class MacroIteratorBase;
00046
00047 public:
00048 class MacroIterator;
00049
00050 MeshPointer ()
00051 : mesh_( NULL )
00052 {}
00053
00054 explicit MeshPointer ( Mesh *mesh )
00055 : mesh_( mesh )
00056 {}
00057
00058 operator Mesh * () const
00059 {
00060 return mesh_;
00061 }
00062
00063 bool operator! () const
00064 {
00065 return (mesh_ == NULL);
00066 }
00067
00068 MacroIterator begin () const
00069 {
00070 return MacroIterator( *this, false );
00071 }
00072
00073 MacroIterator end () const
00074 {
00075 return MacroIterator( *this, true );
00076 }
00077
00078 std::string name () const
00079 {
00080 if( mesh_ != NULL )
00081 return mesh_->name;
00082 else
00083 return std::string();
00084 }
00085
00086 int size ( int codim ) const;
00087
00088 void create ( const MacroData< dim > ¯oData, const std::string &name );
00089 void create ( const std::string &filename, const std::string &name, bool binary = false );
00090
00091 void read ( const std::string &filename, Real &time );
00092
00093 bool write ( const std::string &filename, Real time ) const;
00094
00095 void release ()
00096 {
00097 if( mesh_ != NULL )
00098 {
00099 #if (DUNE_ALBERTA_VERSION < 0x200) && (DIM == 3)
00100
00101 ALBERTA RC_LIST_EL *list = ALBERTA get_rc_list( mesh_ );
00102 list = 0;
00103 #endif
00104 ALBERTA free_mesh( mesh_ );
00105 mesh_ = NULL;
00106 }
00107 }
00108
00109 template< class Functor >
00110 void hierarchicTraverse ( Functor &functor,
00111 typename FillFlags::Flags fillFlags = FillFlags::standard ) const;
00112
00113 template< class Functor >
00114 void leafTraverse ( Functor &functor,
00115 typename FillFlags::Flags fillFlags = FillFlags::standard ) const;
00116
00117 bool coarsen ( typename FillFlags::Flags fillFlags = FillFlags::nothing );
00118
00119 bool refine ( typename FillFlags::Flags fillFlags = FillFlags::nothing );
00120
00121 #if DUNE_ALBERTA_VERSION < 0x200
00122 private:
00123 static void initDofAdmins ( Mesh *mesh )
00124 {
00125 mesh->preserve_coarse_dofs = 1;
00126 HierarchyDofNumbering< dim > dofNumbering;
00127 dofNumbering.create( MeshPointer< dim >( mesh ) );
00128 }
00129 #endif
00130 };
00131
00132
00133
00134 template<>
00135 inline int MeshPointer< 1 >::size( int codim ) const
00136 {
00137 assert( (codim >= 0) && (codim <= 1) );
00138 return (codim == 0 ? mesh_->n_elements : mesh_->n_vertices);
00139 }
00140
00141 #if (DUNE_ALBERTA_VERSION >= 0x200) || (DIM >= 2)
00142 template<>
00143 inline int MeshPointer< 2 >::size( int codim ) const
00144 {
00145 assert( (codim >= 0) && (codim <= 2) );
00146 if( codim == 0 )
00147 return mesh_->n_elements;
00148 else if( codim == 2 )
00149 return mesh_->n_vertices;
00150 else
00151 return mesh_->n_edges;
00152 }
00153 #endif // #if (DUNE_ALBERTA_VERSION >= 0x200) || (ALBERTA_DIM >= 2)
00154
00155 #if (DUNE_ALBERTA_VERSION >= 0x200) || (DIM == 3)
00156 template<>
00157 inline int MeshPointer< 3 >::size( int codim ) const
00158 {
00159 assert( (codim >= 0) && (codim <= 3) );
00160 if( codim == 0 )
00161 return mesh_->n_elements;
00162 else if( codim == 3 )
00163 return mesh_->n_vertices;
00164 else if( codim == 1 )
00165 return mesh_->n_faces;
00166 else
00167 return mesh_->n_edges;
00168 }
00169 #endif // #if (DUNE_ALBERTA_VERSION >= 0x200) || (ALBERTA_DIM == 3)
00170
00171
00172 #if DUNE_ALBERTA_VERSION >= 0x200
00173 template< int dim >
00174 inline void MeshPointer< dim >
00175 ::create ( const MacroData< dim > ¯oData, const std::string &name )
00176 {
00177 release();
00178
00179 #if DUNE_ALBERTA_VERSION >= 0x201
00180 mesh_ = GET_MESH( dim, name.c_str(), macroData, NULL, NULL );
00181 #else
00182 mesh_ = GET_MESH( dim, name.c_str(), macroData, NULL );
00183 #endif
00184
00185 if( mesh_ != NULL )
00186 {
00187 typedef AlbertHelp::AlbertLeafData< dim, dim+1 > LeafData;
00188 ALBERTA init_leaf_data( mesh_, sizeof( typename LeafData::Data ),
00189 LeafData::AlbertLeafRefine,
00190 LeafData::AlbertLeafCoarsen );
00191 }
00192 }
00193 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00194
00195 #if DUNE_ALBERTA_VERSION < 0x200
00196 template< int dim >
00197 inline void MeshPointer< dim >
00198 ::create ( const MacroData< dim > ¯oData, const std::string &name )
00199 {
00200 release();
00201
00202 typedef AlbertHelp::AlbertLeafData< dim, dim+1 > LeafData;
00203 mesh_ = ALBERTA get_mesh( name.c_str(), initDofAdmins, LeafData::initLeafData );
00204 if( mesh_ != NULL )
00205 ALBERTA macro_data2mesh( mesh_, macroData, BoundaryProvider::initBoundary );
00206 }
00207 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00208
00209
00210 #if DUNE_ALBERTA_VERSION >= 0x200
00211 template< int dim >
00212 inline void MeshPointer< dim >
00213 ::create ( const std::string &filename, const std::string &name, bool binary )
00214 {
00215 MacroData< dim > macroData;
00216 macroData.read( filename, binary );
00217 create( macroData, name );
00218 macroData.release();
00219 }
00220 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00221
00222 #if DUNE_ALBERTA_VERSION < 0x200
00223 template< int dim >
00224 inline void MeshPointer< dim >
00225 ::create ( const std::string &filename, const std::string &name, bool binary )
00226 {
00227 release();
00228
00229 typedef AlbertHelp::AlbertLeafData< dim, dim+1 > LeafData;
00230 mesh_ = ALBERTA get_mesh( name.c_str(), initDofAdmins, LeafData::initLeafData );
00231 if( mesh_ != NULL )
00232 {
00233 if( binary )
00234 ALBERTA read_macro_xdr( mesh_, filename.c_str(), BoundaryProvider::initBoundary );
00235 else
00236 ALBERTA read_macro( mesh_, filename.c_str(), BoundaryProvider::initBoundary );
00237 }
00238 }
00239 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00240
00241
00242
00243 #if DUNE_ALBERTA_VERSION < 0x200
00244 template< int dim >
00245 inline void MeshPointer< dim >::read ( const std::string &filename, Real &time )
00246 {
00247 release();
00248
00249 typedef AlbertHelp::AlbertLeafData< dim, dim+1 > LeafData;
00250 mesh_ = ALBERTA read_mesh_xdr( filename.c_str(), &time, LeafData::initLeafData, BoundaryProvider::initBoundary );
00251 }
00252 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00253
00254 #if DUNE_ALBERTA_VERSION >= 0x200
00255 template< int dim >
00256 inline void MeshPointer< dim >::read ( const std::string &filename, Real &time )
00257 {
00258 release();
00259 #if DUNE_ALBERTA_VERSION >= 0x201
00260 mesh_ = ALBERTA read_mesh_xdr( filename.c_str(), &time, NULL, NULL );
00261 #else
00262 mesh_ = ALBERTA read_mesh_xdr( filename.c_str(), &time, NULL );
00263 #endif
00264
00265 if( mesh_ != NULL )
00266 {
00267 typedef AlbertHelp::AlbertLeafData< dim, dim+1 > LeafData;
00268 ALBERTA init_leaf_data( mesh_, sizeof( typename LeafData::Data ),
00269 LeafData::AlbertLeafRefine,
00270 LeafData::AlbertLeafCoarsen );
00271 }
00272 }
00273 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00274
00275
00276 template< int dim >
00277 inline bool MeshPointer< dim >::write ( const std::string &filename, Real time ) const
00278 {
00279 int success = ALBERTA write_mesh_xdr( mesh_, filename.c_str(), time );
00280 return (success == 0);
00281 }
00282
00283
00284 template< int dim >
00285 template< class Functor >
00286 inline void MeshPointer< dim >
00287 ::hierarchicTraverse ( Functor &functor,
00288 typename FillFlags::Flags fillFlags ) const
00289 {
00290 const MacroIterator eit = end();
00291 for( MacroIterator it = begin(); it != eit; ++it )
00292 {
00293 const ElementInfo info = it.elementInfo( fillFlags );
00294 info.hierarchicTraverse( functor );
00295 }
00296 }
00297
00298
00299 template< int dim >
00300 template< class Functor >
00301 inline void MeshPointer< dim >
00302 ::leafTraverse ( Functor &functor,
00303 typename FillFlags::Flags fillFlags ) const
00304 {
00305 const MacroIterator eit = end();
00306 for( MacroIterator it = begin(); it != eit; ++it )
00307 {
00308 const ElementInfo info = it.elementInfo( fillFlags );
00309 info.leafTraverse( functor );
00310 }
00311 }
00312
00313
00314 #if DUNE_ALBERTA_VERSION >= 0x201
00315 template< int dim >
00316 inline bool MeshPointer< dim >::coarsen ( typename FillFlags::Flags fillFlags )
00317 {
00318 const bool coarsened = (ALBERTA coarsen( mesh_, fillFlags ) == meshCoarsened);
00319 if( coarsened )
00320 ALBERTA dof_compress( mesh_ );
00321 return coarsened;
00322 }
00323 #endif // #if DUNE_ALBERTA_VERSION >= 0x201
00324
00325 #if DUNE_ALBERTA_VERSION <= 0x200
00326 template< int dim >
00327 inline bool MeshPointer< dim >::coarsen ( typename FillFlags::Flags fillFlags )
00328 {
00329 assert( fillFlags == FillFlags::nothing );
00330 const bool coarsened = (ALBERTA coarsen( mesh_ ) == meshCoarsened);
00331 if( coarsened )
00332 ALBERTA dof_compress( mesh_ );
00333 return coarsened;
00334 }
00335 #endif // #if DUNE_ALBERTA_VERSION <= 0x200
00336
00337
00338 #if DUNE_ALBERTA_VERSION >= 0x201
00339 template< int dim >
00340 inline bool MeshPointer< dim >::refine ( typename FillFlags::Flags fillFlags )
00341 {
00342 return (ALBERTA refine( mesh_, fillFlags ) == meshRefined);
00343 }
00344 #endif // #if DUNE_ALBERTA_VERSION >= 0x201
00345
00346 #if DUNE_ALBERTA_VERSION <= 0x200
00347 template< int dim >
00348 inline bool MeshPointer< dim >::refine ( typename FillFlags::Flags fillFlags )
00349 {
00350 assert( fillFlags == FillFlags::nothing );
00351 return (ALBERTA refine( mesh_ ) == meshRefined);
00352 }
00353 #endif // #if DUNE_ALBERTA_VERSION <= 0x200
00354
00355
00356
00357
00358
00359
00360 #if DUNE_ALBERTA_VERSION < 0x200
00361 template< int dim >
00362 class MeshPointer< dim >::BoundaryProvider
00363 {
00364 static const int interior = INTERIOR;
00365
00366 #if DIM > 1
00367 static const int numTypes = 256;
00368 static const int firstType = -127;
00369
00370 Boundary boundaries[ numTypes ];
00371 #endif
00372
00373 BoundaryProvider ();
00374
00375
00376 BoundaryProvider ( const BoundaryProvider & );
00377 BoundaryProvider &operator= ( const BoundaryProvider & );
00378
00379 public:
00380 const Boundary *operator[] ( int type ) const;
00381
00382 static const BoundaryProvider &instance ()
00383 {
00384 static BoundaryProvider provider;
00385 return provider;
00386 }
00387
00388 static const Boundary *initBoundary ( Mesh *mesh, int type )
00389 {
00390 return instance()[ type ];
00391 }
00392 };
00393
00394
00395 template< int dim >
00396 inline MeshPointer< dim >::BoundaryProvider::BoundaryProvider ()
00397 {
00398 #if DIM > 1
00399 for( int i = 0; i < numTypes; ++i )
00400 {
00401 boundaries[ i ].param_bound = NULL;
00402 boundaries[ i ].bound = i+firstType;
00403 }
00404 #endif
00405 }
00406
00407
00408 template< int dim >
00409 inline const Boundary *
00410 MeshPointer< dim >::BoundaryProvider::operator[] ( int type ) const
00411 {
00412 int index = type-firstType;
00413 if( (type == interior) || (index < 0) || (index >= numTypes) )
00414 DUNE_THROW( AlbertaError, "Invalid boundary type: " << type << "." );
00415 #if DIM > 1
00416 return &(boundaries[ index ]);
00417 #else
00418 return NULL;
00419 #endif
00420 }
00421 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00422
00423
00424
00425
00426
00427
00428 #if DUNE_ALBERTA_VERSION >= 0x200
00429 template< int dim >
00430 class MeshPointer< dim >::MacroIteratorBase
00431 {
00432 friend class MacroIterator;
00433
00434 public:
00435 typedef Alberta::MeshPointer< dim > MeshPointer;
00436 typedef Alberta::ElementInfo< dim > ElementInfo;
00437
00438 private:
00439 MeshPointer mesh_;
00440 int index_;
00441
00442 explicit MacroIteratorBase ( const MeshPointer &mesh, bool end = false )
00443 : mesh_( mesh ),
00444 index_( end ? numMacroElements() : 0 )
00445 {}
00446
00447 public:
00448 bool done () const
00449 {
00450 return (index_ >= numMacroElements());
00451 }
00452
00453 bool equals ( const MacroIterator &other ) const
00454 {
00455 return (index_ == other.index_);
00456 }
00457
00458 void increment ()
00459 {
00460 assert( !done() );
00461 ++index_;
00462 }
00463
00464 MacroElement ¯oElement () const
00465 {
00466 assert( !done() );
00467 return mesh().mesh_->macro_els[ index_ ];
00468 }
00469
00470 const MeshPointer &mesh () const
00471 {
00472 return mesh_;
00473 }
00474
00475 private:
00476 int numMacroElements () const
00477 {
00478 return mesh().mesh_->n_macro_el;
00479 }
00480 };
00481 #endif // #if DUNE_ALBERTA_VERSION >= 0x200
00482
00483 #if DUNE_ALBERTA_VERSION < 0x200
00484 template< int dim >
00485 class MeshPointer< dim >::MacroIteratorBase
00486 {
00487 friend class MacroIterator;
00488
00489 public:
00490 typedef Alberta::MeshPointer< dim > MeshPointer;
00491 typedef Alberta::ElementInfo< dim > ElementInfo;
00492
00493 typedef typename ElementInfo::FillFlags FillFlags;
00494
00495 private:
00496 MeshPointer mesh_;
00497 MacroElement *element_;
00498
00499 explicit MacroIteratorBase ( const MeshPointer &mesh, bool end = false )
00500 : mesh_( mesh ),
00501 element_( end ? NULL : mesh.mesh_->first_macro_el )
00502 {}
00503
00504 public:
00505 bool done () const
00506 {
00507 return (element_ == NULL);
00508 }
00509
00510 bool equals ( const MacroIterator &other ) const
00511 {
00512 return (element_ == other.element_);
00513 }
00514
00515 void increment ()
00516 {
00517 assert( !done() );
00518 element_ = element_->next;
00519 }
00520
00521 MacroElement ¯oElement () const
00522 {
00523 assert( !done() );
00524 return *element_;
00525 }
00526
00527 const MeshPointer &mesh () const
00528 {
00529 return mesh_;
00530 }
00531 };
00532 #endif // #if DUNE_ALBERTA_VERSION < 0x200
00533
00534
00535
00536
00537
00538
00539 template< int dim >
00540 class MeshPointer< dim >::MacroIterator
00541 : public MeshPointer< dim >::MacroIteratorBase
00542 {
00543 typedef MacroIterator This;
00544 typedef MacroIteratorBase Base;
00545
00546 friend class MeshPointer< dim >;
00547
00548 public:
00549 typedef Alberta::MeshPointer< dim > MeshPointer;
00550 typedef Alberta::ElementInfo< dim > ElementInfo;
00551
00552 private:
00553 explicit MacroIterator ( const MeshPointer &mesh, bool end = false )
00554 : Base( mesh, end )
00555 {}
00556
00557 public:
00558 using Base::done;
00559 using Base::equals;
00560 using Base::increment;
00561 using Base::macroElement;
00562 using Base::mesh;
00563
00564 This &operator++ ()
00565 {
00566 increment();
00567 return *this;
00568 }
00569
00570 ElementInfo operator* () const
00571 {
00572 return elementInfo();
00573 }
00574
00575 bool operator== ( const MacroIterator &other ) const
00576 {
00577 return equals( other );
00578 }
00579
00580 bool operator!= ( const MacroIterator &other ) const
00581 {
00582 return !equals( other );
00583 }
00584
00585 ElementInfo
00586 elementInfo ( typename FillFlags::Flags fillFlags = FillFlags::standard ) const
00587 {
00588 if( done() )
00589 return ElementInfo();
00590 else
00591 return ElementInfo( mesh(), macroElement(), fillFlags );
00592 }
00593 };
00594
00595 }
00596
00597 }
00598
00599 #endif // #if HAVE_ALBERTA
00600
00601 #endif