Dune Core Modules (2.9.0)

structuredgridfactory.hh
1#ifndef DUNE_ALUGRID_STRUCTUREDGRIDFACTORY_HH
2#define DUNE_ALUGRID_STRUCTUREDGRIDFACTORY_HH
3
4#include <array>
5#include <memory>
6#include <vector>
7
9
15
17#include <dune/grid/common/exceptions.hh>
18
19#include <dune/alugrid/common/alugrid_assert.hh>
20#include <dune/alugrid/common/declaration.hh>
21
22#include <dune/alugrid/common/hsfc.hh>
23
24// include DGF parser implementation for YaspGrid
25#include <dune/grid/io/file/dgfparser/dgfyasp.hh>
26
27namespace Dune
28{
29
30 // External Forward Declarations
31 // -----------------------------
32
33 template< class Grid >
34 class StructuredGridFactory;
35
36
37
38 // StructuredGridFactory for ALUGrid
39 // ---------------------------------
40
41 template< int dim, int dimworld, ALUGridElementType eltype, ALUGridRefinementType refineType, class Comm >
42 class StructuredGridFactory< ALUGrid< dim, dimworld, eltype, refineType, Comm > >
43 {
44 public:
45 typedef ALUGrid< dim, dimworld, eltype, refineType, Comm > Grid;
46#if DUNE_VERSION_NEWER(DUNE_GRID, 2, 6)
47 typedef std::unique_ptr< Grid > SharedPtrType;
48#else // #if DUNE_VERSION_NEWER(DUNE_GRID, 2, 6)
49 // mygrid_ptr in GridPtr is a derived from std::shared_ptr and implements a method release
50 typedef typename Dune::GridPtr< Grid > :: mygrid_ptr SharedPtrType;
51#endif // #else // #if DUNE_VERSION_NEWER(DUNE_GRID, 2, 6)
52
53 protected:
54 typedef StructuredGridFactory< Grid > This;
55
56 private:
57 // SimplePartitioner
58 // -----------------
59 template< class GV, PartitionIteratorType pitype, class IS = typename GV::IndexSet >
60 class SimplePartitioner
61 {
62 typedef SimplePartitioner< GV, pitype, IS > This;
63
64 public:
65 typedef GV GridView;
66 typedef typename GridView::Grid Grid;
67
68 typedef IS IndexSet;
69
70 protected:
71 typedef typename IndexSet::IndexType IndexType;
72
73 static const int dimension = Grid::dimension;
74
75 typedef typename Grid::template Codim< 0 >::Entity Element;
76
77 typedef typename Element::Geometry::GlobalCoordinate VertexType;
78
79 // type of communicator
80 typedef Dune :: Communication< typename MPIHelper :: MPICommunicator > Communication ;
81
82#ifdef USE_ALUGRID_SFC_ORDERING
83 typedef SpaceFillingCurveOrdering< VertexType > SpaceFillingCurveOrderingType;
84#endif
85
86 public:
87 SimplePartitioner ( const GridView &gridView, const Communication& comm,
88 const VertexType& lowerLeft, const VertexType& upperRight )
89 : comm_( comm ),
90 gridView_( gridView ),
91 indexSet_( gridView_.indexSet() ),
92 pSize_( comm_.size() ),
93 elementCuts_( pSize_, -1 ),
94#ifdef USE_ALUGRID_SFC_ORDERING
95 sfc_( SpaceFillingCurveOrderingType::ZCurve, lowerLeft, upperRight, comm_ ),
96#endif
97 maxIndex_( -1.0 )
98 {
99#ifdef USE_ALUGRID_SFC_ORDERING
100 const auto end = gridView_.template end< 0 > ();
101 for( auto it = gridView_.template begin< 0 > (); it != end; ++it )
102 {
103 VertexType center = (*it).geometry().center();
104 // get hilbert index in [0,1]
105 const double hidx = sfc_.index( center );
106 maxIndex_ = std::max( maxIndex_, hidx );
107 }
108
109 // adjust with number of elements
110 maxIndex_ /= indexSet_.size( 0 );
111#endif
112
113 // compute decomposition of sfc
114 calculateElementCuts();
115 }
116
117 public:
118 template< class Entity >
119 double index( const Entity &entity ) const
120 {
121 alugrid_assert ( Entity::codimension == 0 );
122#ifdef USE_ALUGRID_SFC_ORDERING
123 // get center of entity's geometry
124 VertexType center = entity.geometry().center();
125 // get hilbert index in [0,1]
126 return sfc_.index( center );
127#else
128 return double(indexSet_.index( entity ));
129#endif
130 }
131
132 template< class Entity >
133 int rank( const Entity &entity ) const
134 {
135 alugrid_assert ( Entity::codimension == 0 );
136#ifdef USE_ALUGRID_SFC_ORDERING
137 // get center of entity's geometry
138 VertexType center = entity.geometry().center();
139 // get hilbert index in [0,1]
140 const double hidx = sfc_.index( center );
141 // transform to element index
142 const long int index = (hidx / maxIndex_);
143 //std::cout << "sfc index = " << hidx << " " << index << std::endl;
144#else
145 const long int index = indexSet_.index( entity );
146#endif
147 return rank( index );
148 }
149
150 protected:
151 int rank( long int index ) const
152 {
153 if( index < elementCuts_[ 0 ] ) return 0;
154 for( int p=1; p<pSize_; ++p )
155 {
156 if( index >= elementCuts_[ p-1 ] && index < elementCuts_[ p ] )
157 return p;
158 }
159 return pSize_-1;
160 }
161
162 void calculateElementCuts()
163 {
164 const size_t nElements = indexSet_.size( 0 );
165
166 // get number of MPI processes
167 const int nRanks = pSize_;
168
169 // get minimal number of entities per process
170 const size_t minPerProc = (double(nElements) / double( nRanks ));
171 size_t maxPerProc = minPerProc ;
172 if( nElements % nRanks != 0 )
173 ++ maxPerProc ;
174
175 // calculate percentage of elements with larger number
176 // of elements per process
177 double percentage = (double(nElements) / double( nRanks ));
178 percentage -= minPerProc ;
179 percentage *= nRanks ;
180
181 int rank = 0;
182 size_t elementCount = maxPerProc ;
183 [[maybe_unused]] size_t elementNumber = 0;
184 size_t localElementNumber = 0;
185 const int lastRank = nRanks - 1;
186
187 const size_t size = indexSet_.size( 0 );
188 for( size_t i=0; i<size; ++i )
189 {
190 if( localElementNumber >= elementCount )
191 {
192 elementCuts_[ rank ] = i ;
193
194 // increase rank
195 if( rank < lastRank ) ++ rank;
196
197 // reset local number
198 localElementNumber = 0;
199
200 // switch to smaller number if red line is crossed
201 if( elementCount == maxPerProc && rank >= percentage )
202 elementCount = minPerProc ;
203 }
204
205 // increase counters
206 ++elementNumber;
207 ++localElementNumber;
208 }
209
210 // set cut for last process
211 elementCuts_[ lastRank ] = size ;
212
213 //for( int p=0; p<pSize_; ++p )
214 // std::cout << "P[ " << p << " ] = " << elementCuts_[ p ] << std::endl;
215 }
216
217 const Communication& comm_;
218
219 const GridView& gridView_;
220 const IndexSet &indexSet_;
221
222 const int pSize_;
223 std::vector< long int > elementCuts_ ;
224
225#ifdef USE_ALUGRID_SFC_ORDERING
226 // get element to hilbert (or Z) index mapping
227 SpaceFillingCurveOrdering< VertexType > sfc_;
228#endif
229 double maxIndex_ ;
230 };
231
232 public:
233 typedef typename Grid::ctype ctype;
234 typedef typename MPIHelper :: MPICommunicator MPICommunicatorType ;
235
236 // type of communicator
237 typedef Dune :: Communication< MPICommunicatorType >
238 Communication ;
239
240 static SharedPtrType
241 createCubeGrid( const std::string& filename,
242 MPICommunicatorType mpiComm = MPIHelper :: getCommunicator() )
243 {
244 std::ifstream file( filename.c_str() );
245 if( ! file )
246 {
247 DUNE_THROW(InvalidStateException,"file not found " << filename );
248 }
249 return createCubeGrid( file, filename, mpiComm );
250 }
251
252 static SharedPtrType
253 createCubeGrid( std::istream& input,
254 const std::string& name,
255 MPICommunicatorType mpiComm = MPIHelper :: getCommunicator() )
256 {
257 Communication comm( MPIHelper :: getCommunicator() );
258 static_assert( dim == dimworld, "YaspGrid is used for creation of the structured grid which only supports dim == dimworld");
259
260 // if periodic transformations are active we cannot use the YaspGrid
261 // approach to insert the grid cells, otherwise the periodic elements
262 // are not inserted
263 dgf::PeriodicFaceTransformationBlock trafoBlock( input, dimworld );
264 if( trafoBlock.isactive() )
265 {
266 Dune::GridPtr< Grid > grid( input, mpiComm );
267 return SharedPtrType( grid.release() );
268 }
269
270 Dune::dgf::IntervalBlock intervalBlock( input );
271 if( !intervalBlock.isactive() )
272 {
273 std::cerr << "No interval block found, using default DGF method to create ALUGrid!" << std::endl;
274 return SharedPtrType( GridPtr< Grid > (input, mpiComm ).release());
275 }
276
277 if( intervalBlock.numIntervals() != 1 )
278 {
279 std::cerr << "ALUGrid creation from YaspGrid can only handle 1 interval block, using default DGF method to create ALUGrid!" << std::endl;
280 return SharedPtrType( GridPtr< Grid > (input, mpiComm ).release());
281 }
282
283 if( intervalBlock.dimw() != dim )
284 {
285 std::cerr << "ALUGrid creation from YaspGrid only works for dim == dimworld, using default DGF method to create ALUGrid!" << std::endl;
286 return SharedPtrType( GridPtr< Grid > (input, mpiComm ).release());
287 }
288
289 const dgf::IntervalBlock::Interval &interval = intervalBlock.get( 0 );
290
291 // only work for the new ALUGrid version
292 // if creation of SGrid fails the DGF file does not contain a proper
293 // IntervalBlock, and thus we cannot create the grid parallel,
294 // we will use the standard technique
295 std::array<int, dim> dims;
296 FieldVector<ctype, dimworld> lowerLeft;
297 FieldVector<ctype, dimworld> upperRight;
298 for( int i=0; i<dim; ++i )
299 {
300 dims[ i ] = interval.n[ i ] ;
301 lowerLeft[ i ] = interval.p[ 0 ][ i ];
302 upperRight[ i ] = interval.p[ 1 ][ i ];
303 }
304
305 // broadcast array values
306 comm.broadcast( &dims[ 0 ], dim, 0 );
307 comm.broadcast( &lowerLeft [ 0 ], dim, 0 );
308 comm.broadcast( &upperRight[ 0 ], dim, 0 );
309
310 std::string nameYasp( name );
311 nameYasp += " via YaspGrid";
312 typedef StructuredGridFactory< Grid > SGF;
313 return SGF :: createCubeGridImpl( lowerLeft, upperRight, dims, comm, nameYasp );
314 }
315
316 static SharedPtrType
317 createSimplexGrid ( const FieldVector<ctype,dimworld>& lowerLeft,
318 const FieldVector<ctype,dimworld>& upperRight,
319 const std::array<unsigned int, dim>& elements,
320 MPICommunicatorType mpiComm = MPIHelper :: getCommunicator() )
321 {
322 // create DGF interval block and use DGF parser to create simplex grid
323 std::stringstream dgfstream;
324 dgfstream << "DGF" << std::endl;
325 dgfstream << "Interval" << std::endl;
326 dgfstream << lowerLeft << std::endl;
327 dgfstream << upperRight << std::endl;
328 for( int i=0; i<dim; ++ i)
329 dgfstream << elements[ i ] << " ";
330 dgfstream << std::endl;
331 dgfstream << "#" << std::endl;
332 dgfstream << "Cube" << std::endl;
333 dgfstream << "#" << std::endl;
334 dgfstream << "Simplex" << std::endl;
335 dgfstream << "#" << std::endl;
336
337 std::cout << dgfstream.str() << std::endl;
338
339 Dune::GridPtr< Grid > grid( dgfstream, mpiComm );
340 return SharedPtrType( grid.release() );
341 }
342
343 static SharedPtrType
344 createCubeGrid ( const FieldVector<ctype,dimworld>& lowerLeft,
345 const FieldVector<ctype,dimworld>& upperRight,
346 const std::array<unsigned int, dim>& elements,
347 MPICommunicatorType mpiComm = MPIHelper :: getCommunicator() )
348 {
349 Communication comm( mpiComm );
350 std::string name( "Cartesian ALUGrid via YaspGrid" );
351 return createCubeGridImpl( lowerLeft, upperRight, elements, comm, name );
352 }
353
354 protected:
355 template <int codim, class Entity>
356 int subEntities ( const Entity& entity ) const
357 {
358 return entity.subEntities( codim );
359 }
360
361 template < class int_t >
362 static SharedPtrType
363 createCubeGridImpl ( const FieldVector<ctype,dimworld>& lowerLeft,
364 const FieldVector<ctype,dimworld>& upperRight,
365 const std::array< int_t, dim>& elements,
366 const Communication& comm,
367 const std::string& name )
368 {
369 const int myrank = comm.rank();
370
371 typedef YaspGrid< dimworld, EquidistantOffsetCoordinates<double,dimworld> > CartesianGridType ;
372 std::array< int, dim > dims;
373 for( int i=0; i<dim; ++i ) dims[ i ] = elements[ i ];
374
375 Communication commSelf( MPIHelper :: getLocalCommunicator() );
376 // create YaspGrid to partition and insert elements that belong to process directly
377 CartesianGridType sgrid( lowerLeft, upperRight, dims, std::bitset<dim>(0ULL), 1, commSelf );
378
379 typedef typename CartesianGridType :: LeafGridView GridView ;
380 typedef typename GridView :: IndexSet IndexSet ;
381 typedef typename IndexSet :: IndexType IndexType ;
382 typedef typename GridView :: template Codim< 0 > :: Iterator ElementIterator ;
383 typedef typename ElementIterator::Entity Entity ;
384 typedef typename GridView :: IntersectionIterator IntersectionIterator ;
385 typedef typename IntersectionIterator :: Intersection Intersection ;
386
387 GridView gridView = sgrid.leafGridView();
388 const IndexSet &indexSet = gridView.indexSet();
389
390 // get decompostition of the marco grid
391 SimplePartitioner< GridView, InteriorBorder_Partition > partitioner( gridView, comm, lowerLeft, upperRight );
392
393 // create ALUGrid GridFactory
394 GridFactory< Grid > factory;
395
396 // map global vertex ids to local ones
397 std::map< IndexType, unsigned int > vtxMap;
398 std::map< double, const Entity > sortedElementList;
399
400 const int numVertices = (1 << dim);
401 std::vector< unsigned int > vertices( numVertices );
402
403 const ElementIterator end = gridView.template end< 0 >();
404 for( ElementIterator it = gridView.template begin< 0 >(); it != end; ++it )
405 {
406 const Entity &entity = *it;
407
408 // if the element does not belong to our partition, continue
409 if( partitioner.rank( entity ) != myrank )
410 continue;
411
412 const double elIndex = partitioner.index( entity );
413 assert( sortedElementList.find( elIndex ) == sortedElementList.end() );
414 sortedElementList.insert( std::make_pair( elIndex, entity ) );
415 }
416
417 int nextElementIndex = 0;
418 const auto endSorted = sortedElementList.end();
419 for( auto it = sortedElementList.begin(); it != endSorted; ++it )
420 {
421 const Entity &entity = (*it).second;
422
423 // insert vertices and element
424 const typename Entity::Geometry geo = entity.geometry();
425 alugrid_assert( numVertices == geo.corners() );
426 for( int i = 0; i < numVertices; ++i )
427 {
428 const IndexType vtxId = indexSet.subIndex( entity, i, dim );
429 //auto result = vtxMap.insert( std::make_pair( vtxId, vtxMap.size() ) );
430 std::pair< typename std::map< IndexType, unsigned int >::iterator, bool > result
431 = vtxMap.insert( std::make_pair( vtxId, vtxMap.size() ) );
432 if( result.second )
433 factory.insertVertex( geo.corner( i ), vtxId );
434 vertices[ i ] = result.first->second;
435 }
436
437 factory.insertElement( entity.type(), vertices );
438 const int elementIndex = nextElementIndex++;
439
440 //const auto iend = gridView.iend( entity );
441 //for( auto iit = gridView.ibegin( entity ); iit != iend; ++iit )
442 const IntersectionIterator iend = gridView.iend( entity );
443 for( IntersectionIterator iit = gridView.ibegin( entity ); iit != iend; ++iit )
444 {
445 const Intersection &isec = *iit;
446 const int faceNumber = isec.indexInInside();
447 // insert boundary face in case of domain boundary
448 if( isec.boundary() )
449 factory.insertBoundary( elementIndex, faceNumber );
450 // insert process boundary if the neighboring element has a different rank
451 if( isec.neighbor() && (partitioner.rank( isec.outside() ) != myrank) )
452 factory.insertProcessBorder( elementIndex, faceNumber );
453 }
454 }
455
456 // for structured grids, do not mark longest edge
457 // not necessary
458 factory.setLongestEdgeFlag(false);
459
460 // create shared grid pointer
461 return SharedPtrType( factory.createGrid( true, true, name ) );
462 }
463 };
464
465} // namespace Dune
466
467#endif // #ifndef DUNE_ALUGRID_STRUCTUREDGRIDFACTORY_HH
GridImp::template Codim< cd >::Geometry Geometry
The corresponding geometry type.
Definition: entity.hh:100
static constexpr int codimension
Know your own codimension.
Definition: entity.hh:106
virtual void insertElement(const GeometryType &type, const std::vector< unsigned int > &vertices)
Insert an element into the coarse grid.
Definition: gridfactory.hh:346
virtual void insertVertex(const FieldVector< ctype, dimworld > &pos)
Insert a vertex into the coarse grid.
Definition: gridfactory.hh:335
virtual std::unique_ptr< GridType > createGrid()
Finalize grid creation and hand over the grid.
Definition: gridfactory.hh:372
static constexpr int dimension
The dimension of the grid.
Definition: grid.hh:387
ct ctype
Define type used for coordinates in grid module.
Definition: grid.hh:532
IndexTypeImp IndexType
The type used for the indices.
Definition: indexidset.hh:92
Dune::Intersection< GridImp, IntersectionImp > Intersection
Type of Intersection this IntersectionIterator points to.
Definition: intersectioniterator.hh:111
MPI_Comm MPICommunicator
The type of the mpi communicator.
Definition: mpihelper.hh:190
static MPICommunicator getCommunicator()
get the default communicator
Definition: mpihelper.hh:198
static MPICommunicator getLocalCommunicator()
get a local communicator
Definition: mpihelper.hh:209
static void createSimplexGrid(GridFactory< GridType > &factory, const FieldVector< ctype, dimworld > &lowerLeft, const FieldVector< ctype, dimworld > &upperRight, const std::array< unsigned int, dim > &elements)
insert structured simplex grid into grid factory
Definition: structuredgridfactory.hh:181
static void createCubeGrid(GridFactory< GridType > &factory, const FieldVector< ctype, dimworld > &lowerLeft, const FieldVector< ctype, dimworld > &upperRight, const std::array< unsigned int, dim > &elements)
insert structured cube grid into grid factory
Definition: structuredgridfactory.hh:91
A free function to provide the demangled class name of a given object or type as a string.
A few common exception classes.
Provide a generic factory class for unstructured grids.
Implements a vector constructed from a given type representing a field and a compile-time given size.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
Traits::Grid Grid
type of the grid
Definition: gridview.hh:83
Traits::IntersectionIterator IntersectionIterator
type of the intersection iterator
Definition: gridview.hh:92
Traits::IndexSet IndexSet
type of the index set
Definition: gridview.hh:86
Dune namespace.
Definition: alignedallocator.hh:13
This file implements several utilities related to std::shared_ptr.
Class for constructing grids from DGF files.
Definition: gridptr.hh:66
Various macros to work with Dune module version numbers.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)