dune-grid  2.2.0
macrodata.hh
Go to the documentation of this file.
1 #ifndef DUNE_ALBERTA_MACRODATA_HH
2 #define DUNE_ALBERTA_MACRODATA_HH
3 
9 #include <dune/common/fvector.hh>
10 #include <dune/common/fmatrix.hh>
11 
15 
16 #if HAVE_ALBERTA
17 
18 namespace Dune
19 {
20 
21  namespace Alberta
22  {
23 
24  template< int dim >
25  class MacroData
26  {
27  typedef MacroData< dim > This;
28 
29  typedef ALBERTA MACRO_DATA Data;
30 
31  static const int dimension = dim;
32  static const int numVertices = NumSubEntities< dimension, dimension >::value;
33  static const int numEdges = NumSubEntities< dimension, dimension-1 >::value;
34 
35  static const int initialSize = 4096;
36 
37  public:
38  template< int >
39  struct Library;
40 
41  template< int > friend struct InstantiateMacroDataLibrary;
42 
43  public:
44  typedef int ElementId[ numVertices ];
45 
46  static const int supportPeriodicity = (DUNE_ALBERTA_VERSION >= 0x300);
47 
49  : data_( NULL ),
50  vertexCount_( -1 ),
51  elementCount_( -1 )
52  {}
53 
54  operator Data * () const
55  {
56  return data_;
57  }
58 
59  int vertexCount () const
60  {
61  return (vertexCount_ < 0 ? data_->n_total_vertices : vertexCount_);
62  }
63 
64  int elementCount () const
65  {
66  return (elementCount_ < 0 ? data_->n_macro_elements : elementCount_);
67  }
68 
69  ElementId &element ( int i ) const;
70  GlobalVector &vertex ( int i ) const;
71  int &neighbor ( int element, int i ) const;
72  BoundaryId &boundaryId ( int element, int i ) const;
73 
78  void create ();
79 
88  void finalize ();
89 
98  void markLongestEdge ();
99 
108  void setOrientation ( const Real orientation );
109 
120  bool checkNeighbors () const;
121 
123  void release ()
124  {
125  if( data_ != NULL )
126  {
127  ALBERTA free_macro_data( data_ );
128  data_ = NULL;
129  }
130  vertexCount_ = elementCount_ = -1;
131  }
132 
138  int insertElement ( const ElementId &id );
139 
145  int insertVertex ( const GlobalVector &coords )
146  {
147  assert( vertexCount_ >= 0 );
148  if( vertexCount_ >= data_->n_total_vertices )
149  resizeVertices( 2*vertexCount_ );
150  copy( coords, vertex( vertexCount_ ) );
151  return vertexCount_++;
152  }
153 
159  int insertVertex ( const FieldVector< Real, dimWorld > &coords )
160  {
161  assert( vertexCount_ >= 0 );
162  if( vertexCount_ >= data_->n_total_vertices )
163  resizeVertices( 2*vertexCount_ );
164  copy( coords, vertex( vertexCount_ ) );
165  return vertexCount_++;
166  }
167 
168  void insertWallTrafo ( const GlobalMatrix &m, const GlobalVector &t );
169  void insertWallTrafo ( const FieldMatrix< Real, dimWorld, dimWorld > &matrix,
170  const FieldVector< Real, dimWorld > &shift );
171 
172  void checkCycles ();
173 
174  void read ( const std::string &filename, bool binary = false );
175 
176  bool write ( const std::string &filename, bool binary = false ) const
177  {
178  if( binary )
179  return ALBERTA write_macro_data_xdr( data_, filename.c_str() );
180  else
181  return ALBERTA write_macro_data( data_, filename.c_str() );
182  }
183 
184  private:
185  template< class Vector >
186  void copy ( const Vector &x, GlobalVector &y )
187  {
188  for( int i = 0; i < dimWorld; ++i )
189  y[ i ] = x[ i ];
190  }
191 
192  void resizeElements ( const int newSize );
193 
194  void resizeVertices ( const int newSize )
195  {
196  const int oldSize = data_->n_total_vertices;
197  data_->n_total_vertices = newSize;
198  data_->coords = memReAlloc< GlobalVector >( data_->coords, oldSize, newSize );
199  assert( (data_->coords != NULL) || (newSize == 0) );
200  }
201 
202  private:
203  Data *data_;
204  int vertexCount_;
205  int elementCount_;
206  };
207 
208 
209 
210  // MacroData::Library
211  // ------------------
212 
213  template< int dim >
214  template< int >
215  struct MacroData< dim >::Library
216  {
218 
219  static bool checkNeighbors ( const MacroData &macroData );
220  static void markLongestEdge ( MacroData &macroData );
221  static void setOrientation ( MacroData &macroData, const Real orientation );
222 
223  private:
224  static Real edgeLength ( const MacroData &macroData, const ElementId &e, int edge );
225  static int longestEdge ( const MacroData &macroData, const ElementId &e );
226 
227  template< class Type >
228  static void rotate ( Type *array, int i, int shift );
229 
230  static void rotate ( MacroData &macroData, int i, int shift );
231  static void swap ( MacroData &macroData, int el, int v1, int v2 );
232  };
233 
234 
235 
236  // Implementation of MacroData
237  // ---------------------------
238 
239  template< int dim >
240  inline typename MacroData< dim >::ElementId &
242  {
243  assert( (i >= 0) && (i < data_->n_macro_elements) );
244  const int offset = i * numVertices;
245  return *reinterpret_cast< ElementId * >( data_->mel_vertices + offset );
246  }
247 
248 
249  template< int dim >
250  inline GlobalVector &MacroData< dim >::vertex ( int i ) const
251  {
252  assert( (i >= 0) && (i < data_->n_total_vertices) );
253  return data_->coords[ i ];
254  }
255 
256 
257  template< int dim >
258  inline int &MacroData< dim >::neighbor ( int element, int i ) const
259  {
260  assert( (element >= 0) && (element < data_->n_macro_elements) );
261  assert( (i >= 0) && (i < numVertices) );
262  return data_->neigh[ element*numVertices + i ];
263  }
264 
265 
266  template< int dim >
267  inline BoundaryId &MacroData< dim >::boundaryId ( int element, int i ) const
268  {
269  assert( (element >= 0) && (element < data_->n_macro_elements) );
270  assert( (i >= 0) && (i < numVertices) );
271  return data_->boundary[ element*numVertices + i ];
272  }
273 
274 
275 #if DUNE_ALBERTA_VERSION >= 0x300
276  template< int dim >
277  inline void MacroData< dim >::create ()
278  {
279  release();
280  data_ = ALBERTA alloc_macro_data( dim, initialSize, initialSize );
281  data_->boundary = memAlloc< BoundaryId >( initialSize*numVertices );
282  if( dim == 3 )
283  data_->el_type = memAlloc< ElementType >( initialSize );
284  vertexCount_ = elementCount_ = 0;
285  elementCount_ = 0;
286  }
287 #endif // #if DUNE_ALBERTA_VERSION >= 0x300
288 
289 #if DUNE_ALBERTA_VERSION == 0x200
290  template< int dim >
291  inline void MacroData< dim >::create ()
292  {
293  release();
294  data_ = ALBERTA alloc_macro_data( dim, initialSize, initialSize, 0 );
295  data_->boundary = memAlloc< BoundaryId >( initialSize*numVertices );
296  if( dim == 3 )
297  data_->el_type = memAlloc< ElementType >( initialSize );
298  vertexCount_ = elementCount_ = 0;
299  elementCount_ = 0;
300  }
301 #endif // #if DUNE_ALBERTA_VERSION == 0x200
302 
303 
304  template< int dim >
306  {
307  if( (vertexCount_ >= 0) && (elementCount_ >= 0) )
308  {
309  resizeVertices( vertexCount_ );
310  resizeElements( elementCount_ );
311  ALBERTA compute_neigh_fast( data_ );
312 
313  // assign default boundary id (if none is assigned)
314  for( int element = 0; element < elementCount_; ++element )
315  {
316  for( int i = 0; i < numVertices; ++i )
317  {
318  BoundaryId &id = boundaryId( element, i );
319  if( neighbor( element, i ) >= 0 )
320  {
321  assert( id == InteriorBoundary );
322  id = InteriorBoundary;
323  }
324  else
325  id = (id == InteriorBoundary ? DirichletBoundary : id);
326  }
327  }
328 
329  vertexCount_ = elementCount_ = -1;
330  }
331  assert( (vertexCount_ < 0) && (elementCount_ < 0) );
332  }
333 
334 
335  template< int dim >
337  {
339  }
340 
341 
342  template< int dim >
343  inline void MacroData< dim >::setOrientation ( const Real orientation )
344  {
345  Library< dimWorld >::setOrientation( *this, orientation );
346  }
347 
348 
349  template< int dim >
350  inline bool MacroData< dim >::checkNeighbors () const
351  {
352  return Library< dimWorld >::checkNeighbors( *this );
353  }
354 
355 
356  template< int dim >
357  inline int MacroData< dim >::insertElement ( const ElementId &id )
358  {
359  assert( elementCount_ >= 0 );
360  if( elementCount_ >= data_->n_macro_elements )
361  resizeElements( 2*elementCount_ );
362 
363  ElementId &e = element( elementCount_ );
364  for( int i = 0; i < numVertices; ++i )
365  {
366  e[ i ] = id[ i ];
367  boundaryId( elementCount_, i ) = InteriorBoundary;
368  }
369  if( dim == 3 )
370  data_->el_type[ elementCount_ ] = 0;
371 
372  return elementCount_++;
373  }
374 
375 
376 #if DUNE_ALBERTA_VERSION >= 0x300
377  template< int dim >
378  inline void MacroData< dim >
379  ::insertWallTrafo ( const GlobalMatrix &matrix, const GlobalVector &shift )
380  {
381  int &count = data_->n_wall_trafos;
382  AffineTransformation *&array = data_->wall_trafos;
383 
384  // resize wall trafo array
385  array = memReAlloc< AffineTransformation >( array, count, count+1 );
386  assert( data_->wall_trafos != NULL );
387 
388  // copy matrix and shift
389  for( int i = 0; i < dimWorld; ++i )
390  copy( matrix[ i ], array[ count ].M[ i ] );
391  copy( shift, array[ count ].t );
392  ++count;
393  }
394 
395  template< int dim >
396  inline void MacroData< dim >
397  ::insertWallTrafo ( const FieldMatrix< Real, dimWorld, dimWorld > &matrix,
398  const FieldVector< Real, dimWorld > &shift )
399  {
400  int &count = data_->n_wall_trafos;
401  AffineTransformation *&array = data_->wall_trafos;
402 
403  // resize wall trafo array
404  array = memReAlloc< AffineTransformation >( array, count, count+1 );
405  assert( data_->wall_trafos != NULL );
406 
407  // copy matrix and shift
408  for( int i = 0; i < dimWorld; ++i )
409  copy( matrix[ i ], array[ count ].M[ i ] );
410  copy( shift, array[ count ].t );
411  ++count;
412  }
413 #endif // #if DUNE_ALBERTA_VERSION >= 0x300
414 
415 #if DUNE_ALBERTA_VERSION <= 0x200
416  template< int dim >
417  inline void MacroData< dim >
419  {
420  DUNE_THROW( AlbertaError,
421  "Periodic grids are only supported in ALBERTA 3.0 or higher." );
422  }
423 
424  template< int dim >
425  inline void MacroData< dim >
426  ::insertWallTrafo ( const FieldMatrix< Real, dimWorld, dimWorld > &matrix,
427  const FieldVector< Real, dimWorld > &shift )
428  {
429  DUNE_THROW( AlbertaError,
430  "Periodic grids are only supported in ALBERTA 3.0 or higher." );
431  }
432 #endif // #if DUNE_ALBERTA_VERSION <= 0x200
433 
434 
435  template< int dim >
437  {
438  // ensure that the macro data has been finalized
439  finalize();
440  ALBERTA macro_test( data_, NULL );
441  }
442 
443 
444  template< int dim >
445  inline void MacroData< dim >::read ( const std::string &filename, bool binary )
446  {
447  release();
448  if( binary )
449  data_ = ALBERTA read_macro_xdr( filename.c_str() );
450  else
451  data_ = ALBERTA read_macro( filename.c_str() );
452  }
453 
454 
455  template< int dim >
456  inline void MacroData< dim >::resizeElements ( const int newSize )
457  {
458  const int oldSize = data_->n_macro_elements;
459  data_->n_macro_elements = newSize;
460  data_->mel_vertices = memReAlloc( data_->mel_vertices, oldSize*numVertices, newSize*numVertices );
461  data_->boundary = memReAlloc( data_->boundary, oldSize*numVertices, newSize*numVertices );
462  if( dim == 3 )
463  data_->el_type = memReAlloc( data_->el_type, oldSize, newSize );
464  assert( (newSize == 0) || (data_->mel_vertices != NULL) );
465  }
466 
467  }
468 
469 }
470 
471 #endif // #if HAVE_ALBERTA
472 
473 #endif