Dune Core Modules (2.9.0)

dgf.hh
1#ifndef DUNE_ALUGRID_DGF_HH
2#define DUNE_ALUGRID_DGF_HH
3
4#include <type_traits>
5
6#if HAVE_ALUGRID
7#include <dune/alugrid/grid.hh>
8#include <dune/grid/io/file/dgfparser/dgfalu.hh>
9#else
10
11// include grid first to avoid includes from dune-grid/grid/alugrid
12#include <dune/alugrid/grid.hh>
13
14#include <dune/grid/common/intersection.hh>
15#include <dune/grid/io/file/dgfparser/dgfparser.hh>
16#include <dune/grid/io/file/dgfparser/parser.hh>
17#include <dune/grid/io/file/dgfparser/blocks/projection.hh>
18
19
20namespace Dune
21{
22
23 namespace
24 {
25
26 // GlobalVertexIndexBlock
27 // ----------------------
28
29 class GlobalVertexIndexBlock
30 : public dgf::BasicBlock
31 {
32 bool goodline;
33
34 public:
35 GlobalVertexIndexBlock ( std :: istream &in )
36 : dgf::BasicBlock( in, "GlobalVertexIndex" ),
37 goodline( true )
38 {}
39
40 bool next ( int &index )
41 {
42 assert( ok() );
43 if( !getnextline() )
44 return (goodline = false);
45
46 if( !getnextentry( index ) )
47 {
48 DUNE_THROW ( DGFException, "Error in " << *this << ": "
49 << "Wrong global vertex indices " );
50 }
51 return (goodline = true);
52 }
53
54 // some information
55 bool ok ()
56 {
57 return goodline;
58 }
59 };
60
61
62
63 // ALUParallelBlock
64 // ----------------
65
66 class ALUParallelBlock
67 : public dgf::BasicBlock
68 {
69 bool goodline;
70
71 public:
72 ALUParallelBlock ( std :: istream &in )
73 : dgf::BasicBlock( in, "ALUParallel" ),
74 goodline( true )
75 {}
76
77 bool next ( std::string &name )
78 {
79 assert( ok() );
80 if( !getnextline() )
81 return (goodline = false);
82
83 if( !getnextentry( name ) )
84 {
85 DUNE_THROW ( DGFException, "Error in " << *this << ": "
86 << "Wrong global vertex indices " );
87 }
88 return (goodline = true);
89 }
90
91 // some information
92 bool ok ()
93 {
94 return goodline;
95 }
96 };
97
98 } // end empty namespace
99
100
101
102 // DGFGridInfo (specialization for ALUGrid)
103 // ----------------------------------------
104
105 template<int dimg, int dimw, ALUGridElementType eltype, ALUGridRefinementType refinementtype, class Comm >
106 struct DGFGridInfo< Dune::ALUGrid< dimg, dimw, eltype, refinementtype, Comm > >
107 {
108 static int refineStepsForHalf () { return ( refinementtype == conforming ) ? dimg : 1; }
109 static double refineWeight () { return ( refinementtype == conforming ) ? 0.5 : 1.0/(std::pow( 2.0, double(dimg))); }
110 };
115 // DGFGridFactory for AluGrid
116 // --------------------------
117
118 // template< int dim, int dimworld > // for a first version
119 template< class G >
120 struct DGFBaseFactory
121 {
122 typedef G Grid;
123 const static int dimension = Grid::dimension;
124 typedef MPIHelper::MPICommunicator MPICommunicatorType;
125 typedef typename Grid::template Codim<0>::Entity Element;
126 typedef typename Grid::template Codim<dimension>::Entity Vertex;
127 typedef Dune::GridFactory<Grid> GridFactory;
128
129 DGFBaseFactory ()
130 : factory_( ),
131 dgf_( 0, 1 )
132 {}
133
134 explicit DGFBaseFactory ( MPICommunicatorType comm )
135 : factory_(comm),
136 dgf_( rank(comm), size(comm) )
137 {}
138
139 Grid *grid () const
140 {
141 return grid_;
142 }
143
144 template< class Intersection >
145 bool wasInserted ( const Intersection &intersection ) const
146 {
147 return factory_.wasInserted( intersection );
148 }
149
150 template< class GG, class II >
151 int boundaryId ( const Intersection< GG, II > & intersection ) const
152 {
153 typedef Dune::Intersection< GG, II > Intersection;
154 const typename Intersection::Entity & entity = intersection.inside();
155
156 const int face = intersection.indexInInside();
157
158 const auto& refElem =
160 int corners = refElem.size( face, 1, dimension );
161 std :: vector< unsigned int > bound( corners );
162 for( int i=0; i < corners; ++i )
163 {
164 const int k = refElem.subEntity( face, 1, i, dimension );
165 bound[ i ] = factory_.insertionIndex( entity.template subEntity< dimension >( k ) );
166 }
167
168 DuneGridFormatParser::facemap_t::key_type key( bound, false );
169 const DuneGridFormatParser::facemap_t::const_iterator pos = dgf_.facemap.find( key );
170 if( pos != dgf_.facemap.end() )
171 return dgf_.facemap.find( key )->second.first;
172 else
173 return (intersection.boundary() ? 1 : 0);
174 }
175
176 template< class GG, class II >
177 const typename DGFBoundaryParameter::type &
178 boundaryParameter ( const Intersection< GG, II > & intersection ) const
179 {
180 typedef Dune::Intersection< GG, II > Intersection;
181 const typename Intersection::Entity & entity = intersection.inside();
182
183 const int face = intersection.indexInInside();
184
185 const auto& refElem =
187 int corners = refElem.size( face, 1, dimension );
188 std :: vector< unsigned int > bound( corners );
189 for( int i=0; i < corners; ++i )
190 {
191 const int k = refElem.subEntity( face, 1, i, dimension );
192 bound[ i ] = factory_.insertionIndex( entity.template subEntity< dimension >( k ) );
193 }
194
195 DuneGridFormatParser::facemap_t::key_type key( bound, false );
196 const DuneGridFormatParser::facemap_t::const_iterator pos = dgf_.facemap.find( key );
197 if( pos != dgf_.facemap.end() )
198 return dgf_.facemap.find( key )->second.second;
199 else
201 }
202
203 template< int codim >
204 int numParameters () const
205 {
206 if( codim == 0 )
207 return dgf_.nofelparams;
208 else if( codim == dimension )
209 return dgf_.nofvtxparams;
210 else
211 return 0;
212 }
213
214 // return true if boundary parameters found
215 bool haveBoundaryParameters () const
216 {
217 return dgf_.haveBndParameters;
218 }
219
220 std::vector< double > &parameter ( const Element &element )
221 {
222 if( numParameters< 0 >() <= 0 )
223 {
224 DUNE_THROW( InvalidStateException,
225 "Calling DGFGridFactory::parameter is only allowed if there are parameters." );
226 }
227 return dgf_.elParams[ factory_.insertionIndex( element ) ];
228 }
229
230 std::vector< double > &parameter ( const Vertex &vertex )
231 {
232 if( numParameters< dimension >() <= 0 )
233 {
234 DUNE_THROW( InvalidStateException,
235 "Calling DGFGridFactory::parameter is only allowed if there are parameters." );
236 }
237 return dgf_.vtxParams[ factory_.insertionIndex( vertex ) ];
238 }
239
240 protected:
241 bool generateALUGrid( const ALUGridElementType eltype,
242 const ALUGridRefinementType refinementtype,
243 std::istream &file,
244 MPICommunicatorType communicator,
245 const std::string &filename );
246
247
248 static Grid* callDirectly( const std::string& gridname,
249 const int rank,
250 const char *filename,
251 MPICommunicatorType communicator )
252 {
253 typedef typename Grid::MPICommunicatorType GridCommunicatorType;
254 static const bool isSameComm = std::is_same< GridCommunicatorType, MPICommunicatorType >::value;
255 return callDirectlyImpl( gridname, rank, filename, communicator, std::integral_constant< bool, isSameComm >() );
256 }
257
258 static Grid* callDirectlyImpl( const std::string& gridname,
259 const int rank,
260 const char *filename,
261 MPICommunicatorType communicator,
262 std::false_type )
263 {
264 // for rank 0 we also check the normal file name
265 if( rank == 0 )
266 {
267 if( fileExists( filename ) )
268 return new Grid( filename );
269
270 // only throw this exception on rank 0 because
271 // for the other ranks we can still create empty grids
272 DUNE_THROW( GridError, "Unable to create " << gridname << " from '"
273 << filename << "'." );
274 }
275 // return empty grid on all other processes
276 return new Grid();
277 }
278
279 static Grid* callDirectlyImpl( const std::string& gridname,
280 const int rank,
281 const char *filename,
282 MPICommunicatorType communicator,
283 std::true_type )
284 {
285 if constexpr ( !std::is_same< MPICommunicatorType, No_Comm >::value )
286 {
287 // in parallel runs add rank to filename
288 std :: stringstream tmps;
289 tmps << filename << "." << rank;
290 const std :: string &tmp = tmps.str();
291
292 // if file exits then use it
293 if( fileExists( tmp.c_str() ) )
294 return new Grid( tmp.c_str(), communicator );
295 }
296
297 // for rank 0 we also check the normal file name
298 if( rank == 0 )
299 {
300 if( fileExists( filename ) )
301 return new Grid( filename , communicator );
302
303 // only throw this exception on rank 0 because
304 // for the other ranks we can still create empty grids
305 DUNE_THROW( GridError, "Unable to create " << gridname << " from '"
306 << filename << "'." );
307 }
308 // don't create messages in every proc, this does not work for many cores.
309 //else
310 //{
311 // dwarn << "WARNING: P[" << rank << "]: Creating empty grid!" << std::endl;
312 //}
313
314 // return empty grid on all other processes
315 return new Grid( communicator );
316 }
317 static bool fileExists ( const char *fileName )
318 {
319 std :: ifstream testfile( fileName );
320 if( !testfile )
321 return false;
322 testfile.close();
323 return true;
324 }
325 static int rank( MPICommunicatorType mpiComm )
326 {
327 int rank = 0;
328#if HAVE_MPI
329 MPI_Comm_rank( mpiComm, &rank );
330#endif
331 return rank;
332 }
333 static int size( MPICommunicatorType mpiComm )
334 {
335 int size = 1;
336#if HAVE_MPI
337 MPI_Comm_size( mpiComm, &size );
338#endif
339 return size;
340 }
341 Grid *grid_;
342 GridFactory factory_;
343 DuneGridFormatParser dgf_;
344 };
345
346 template <int dim, int dimw, ALUGridElementType eltype, ALUGridRefinementType refinementtype, class Comm >
347 struct DGFGridFactory< ALUGrid< dim, dimw, eltype, refinementtype, Comm > > :
348 public DGFBaseFactory< ALUGrid< dim, dimw, eltype, refinementtype, Comm > >
349 {
350 typedef ALUGrid< dim, dimw, eltype, refinementtype, Comm > DGFGridType;
351 typedef DGFBaseFactory< DGFGridType > BaseType;
352 typedef typename BaseType :: MPICommunicatorType MPICommunicatorType;
353 protected:
354 using BaseType :: grid_;
355 using BaseType :: callDirectly;
356 public:
357 explicit DGFGridFactory ( std::istream &input,
358 MPICommunicatorType mpiComm )
359 : DGFGridFactory( input, Comm(mpiComm) )
360 {}
361
362 explicit DGFGridFactory ( const std::string &filename,
363 MPICommunicatorType mpiComm )
364 : DGFGridFactory( filename, Comm(mpiComm) )
365 {}
366
367 DGFGridFactory ( std::istream &input,
368 Comm comm = Comm() ) // casts from and to MPI_Comm
369 : BaseType( MPICommunicatorType(comm) )
370 {
371 input.clear();
372 input.seekg( 0 );
373 if( !input )
374 DUNE_THROW( DGFException, "Error resetting input stream." );
375 generate( input, comm );
376 }
377
378 explicit DGFGridFactory ( const std::string &filename,
379 Comm comm = Comm() ) // casts from and to MPI_Comm
380 : BaseType( MPICommunicatorType(comm) )
381 {
382 std::ifstream input( filename.c_str() );
383 bool fileFound = input.is_open() ;
384 if( fileFound )
385 fileFound = generate( input, comm, filename );
386
387 if( ! fileFound )
388 {
389 std::stringstream gridname;
390 gridname << "ALUGrid< " << dim << ", " << dimw << ", eltype, ref, comm >";
391 grid_ = callDirectly( gridname.str(), this->rank( comm ), filename.c_str(), comm );
392 }
393 }
394
395 protected:
396 bool generate( std::istream &file, MPICommunicatorType comm, const std::string &filename = "" );
397 };
398
399
400 namespace dgf
401 {
402
403 struct ALU2dGridParameterBlock
404 : public GridParameterBlock
405 {
406 ALU2dGridParameterBlock( std::istream &in, const bool verbose )
407 : GridParameterBlock( in ),
408 tolerance_( 1e-8 )
409 {
410 if( findtoken( "tolerance" ) )
411 {
412 double x;
413 if( getnextentry(x) )
414 tolerance_ = x;
415 else
416 {
417 if( verbose )
418 {
419 dwarn << "GridParameterBlock: found keyword `tolerance' but no value, "
420 << "defaulting to `" << tolerance_ <<"'!" << std::endl;
421 }
422 }
423 if( tolerance_ <= 0 )
424 DUNE_THROW( DGFException, "Nonpositive tolerance specified!" );
425 }
426 else
427 {
428 if( verbose )
429 {
430 dwarn << "GridParameterBlock: Parameter 'tolerance' not specified, "
431 << "defaulting to `" << tolerance_ <<"'!" << std::endl;
432 }
433 }
434 }
435
436 double tolerance () const { return tolerance_; }
437
438 protected:
439 double tolerance_;
440 };
441
442 } //end namespace dgf
443
444
445 template < class G >
446 inline bool DGFBaseFactory< G > ::
447 generateALUGrid( const ALUGridElementType eltype,
448 const ALUGridRefinementType refinementtype,
449 std::istream &file, MPICommunicatorType communicator,
450 const std::string &filename )
451 {
452 typedef G DGFGridType ;
453
454 const int dimworld = DGFGridType :: dimensionworld ;
455 const int dimgrid = DGFGridType :: dimension;
456 dgf_.element = ( eltype == simplex) ?
457 DuneGridFormatParser::Simplex :
458 DuneGridFormatParser::Cube ;
459 dgf_.dimgrid = dimgrid;
460 dgf_.dimw = dimworld;
461
462 const bool isDGF = dgf_.isDuneGridFormat( file );
463 file.seekg( 0 );
464 if( !isDGF )
465 return false;
466
467 int rank = 0;
468#if ALU3DGRID_PARALLEL
469 MPI_Comm_rank( communicator, &rank );
470#endif
471
472 dgf::GridParameterBlock parameter( file );
473
474 typedef FieldVector< typename DGFGridType :: ctype, dimworld > CoordinateType ;
475
476 ALUParallelBlock aluParallelBlock( file );
477 const bool readFromParallelDGF = aluParallelBlock.isactive();
478 bool parallelFileExists = false;
479
480 std::string newfilename;
481 if (readFromParallelDGF)
482 {
483 bool ok = true;
484 for (int p=0;p<=rank && ok;++p)
485 ok = aluParallelBlock.next(newfilename);
486 if (ok)
487 {
488 parallelFileExists = true;
489 std::ifstream newfile(newfilename.c_str());
490 if ( !newfile )
491 {
492 std::cout << "prozess " << rank << " failed to open file " << newfilename << " ... abort" << std::endl;
493 DUNE_THROW( InvalidStateException, "parallel DGF file could not opend" );
494 }
495 assert( newfile );
496 return generateALUGrid(eltype, refinementtype, newfile, communicator, filename);
497 }
498 }
499
500 const GeometryType elementType = (eltype == simplex) ?
502 const GeometryType faceType = (eltype == simplex) ?
503 GeometryTypes::simplex(dimgrid-1) : GeometryTypes::cube(dimgrid-1);
504
505 GlobalVertexIndexBlock vertexIndex( file );
506 const bool globalVertexIndexFound = vertexIndex.isactive();
507 if( rank == 0 || globalVertexIndexFound )
508 {
509 if( !dgf_.readDuneGrid( file, dimgrid, dimworld ) )
510 DUNE_THROW( InvalidStateException, "DGF file not recognized on second call." );
511
512 if( eltype == simplex )
513 {
514 if(dimgrid == 3)
515 dgf_.setOrientation( 2, 3 );
516 else
517 dgf_.setRefinement( 0, 1);
518 }
519
520 if( parallelFileExists && !globalVertexIndexFound )
521 DUNE_THROW( DGFException, "Parallel DGF file requires GLOBALVERTEXINDEX block." );
522
523 for( int n = 0; n < dgf_.nofvtx; ++n )
524 {
525 CoordinateType pos;
526 for( int i = 0; i < dimworld; ++i )
527 pos[ i ] = dgf_.vtx[ n ][ i ];
528 if ( !globalVertexIndexFound )
529 factory_.insertVertex( pos );
530 else
531 {
532 int globalIndex;
533 bool ok = vertexIndex.next(globalIndex);
534 if (!ok)
535 DUNE_THROW( DGFException, "Not enough values in GlobalVertexIndex block" );
536 factory_.insertVertex( pos, globalIndex );
537 }
538 }
539
540 const int nFaces = (eltype == simplex) ? dimgrid+1 : 2*dimgrid;
541 for( int n = 0; n < dgf_.nofelements; ++n )
542 {
543 factory_.insertElement( elementType, dgf_.elements[ n ] );
544 for( int face = 0; face <nFaces; ++face )
545 {
546 typedef DuneGridFormatParser::facemap_t::key_type Key;
547 typedef DuneGridFormatParser::facemap_t::iterator Iterator;
548
549 const Key key = ElementFaceUtil::generateFace( dimgrid, dgf_.elements[ n ], face );
550 const Iterator it = dgf_.facemap.find( key );
551 if( it != dgf_.facemap.end() )
552 factory_.insertBoundary( n, face, it->second.first );
553 }
554 }
555
556 } // end rank == 0 || globalVertexIndexBlock
557
558 dgf::ProjectionBlock projectionBlock( file, dimworld );
559 const DuneBoundaryProjection< dimworld > *projection
560 = projectionBlock.defaultProjection< dimworld >();
561
562 //There is currently only the possibility to insert one
563 //surface OR a global BOUNDARY projection
564 //This is done via a second argument bool
565 //that defaults to dimgrid != dimworld
566 if( projection )
567 factory_.insertBoundaryProjection( *projection );
568
569 if( rank == 0 || globalVertexIndexFound )
570 {
571 const size_t numBoundaryProjections = projectionBlock.numBoundaryProjections();
572 for( size_t i = 0; i < numBoundaryProjections; ++i )
573 {
574 const std::vector< unsigned int > &vertices = projectionBlock.boundaryFace( i );
575 const DuneBoundaryProjection< dimworld > *projection
576 = projectionBlock.boundaryProjection< dimworld >( i );
577 factory_.insertBoundaryProjection( faceType, vertices, projection );
578 }
579
580 typedef dgf::PeriodicFaceTransformationBlock::AffineTransformation Transformation;
581 dgf::PeriodicFaceTransformationBlock trafoBlock( file, dimworld );
582 const int size = trafoBlock.numTransformations();
583 for( int k = 0; k < size; ++k )
584 {
585 const Transformation &trafo = trafoBlock.transformation( k );
586
587 typename GridFactory::WorldMatrix matrix;
588 for( int i = 0; i < dimworld; ++i )
589 for( int j = 0; j < dimworld; ++j )
590 matrix[ i ][ j ] = trafo.matrix( i, j );
591
592 typename GridFactory::WorldVector shift;
593 for( int i = 0; i < dimworld; ++i )
594 shift[ i ] = trafo.shift[ i ];
595
596 factory_.insertFaceTransformation( matrix, shift );
597 }
598 } // end rank == 0 || globalVertexIndexBlock
599
600 int addMissingBoundariesLocal = (dgf_.nofelements > 0) && dgf_.facemap.empty();
601 int addMissingBoundariesGlobal = addMissingBoundariesLocal;
602#if ALU3DGRID_PARALLEL
603 MPI_Allreduce( &addMissingBoundariesLocal, &addMissingBoundariesGlobal, 1, MPI_INT, MPI_MAX, communicator );
604#endif
605
606 // pass longest edge marking (default is off)
607 if( ( refinementtype == conforming ) && parameter.markLongestEdge() )
608 factory_.setLongestEdgeFlag();
609
610 if( !parameter.dumpFileName().empty() )
611 grid_ = std::unique_ptr<Grid>(factory_.createGrid( addMissingBoundariesGlobal, false, parameter.dumpFileName() )).release() ;
612 else
613 grid_ = std::unique_ptr<Grid>(factory_.createGrid( addMissingBoundariesGlobal, true, filename )).release();
614 return true;
615 }
616
617 template <int dim, int dimw, ALUGridElementType eltype, ALUGridRefinementType refinementtype, class Comm>
618 inline bool DGFGridFactory< ALUGrid< dim, dimw, eltype, refinementtype, Comm > >
619 ::generate( std::istream &file, MPICommunicatorType communicator, const std::string &filename )
620 {
621 return BaseType :: generateALUGrid( eltype, refinementtype, file, communicator, filename );
622 }
623
624
625
626} // namespace Dune
627
628#endif // else if HAVE_ALUGRID
629
630#endif // #ifndef DUNE_ALUGRID_DGF_HH
static constexpr int dimension
The dimension of the grid.
Definition: grid.hh:387
Intersection of a mesh entity of codimension 0 ("element") with a "neighboring" element or with the d...
Definition: intersection.hh:164
GridImp::template Codim< 0 >::Entity Entity
Type of entity that this Intersection belongs to.
Definition: intersection.hh:192
MPI_Comm MPICommunicator
The type of the mpi communicator.
Definition: mpihelper.hh:190
GridParameterBlock(std::istream &in)
constructor: read commmon parameters
GeometryType
Type representing VTK's entity geometry types.
Definition: common.hh:132
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr GeometryType cube(unsigned int dim)
Returns a GeometryType representing a hypercube of dimension dim.
Definition: type.hh:472
constexpr GeometryType simplex(unsigned int dim)
Returns a GeometryType representing a simplex of dimension dim.
Definition: type.hh:463
constexpr GeometryType vertex
GeometryType representing a vertex.
Definition: type.hh:506
DWarnType dwarn(std::cerr)
Stream for warnings indicating problems.
Definition: stdstreams.hh:161
Dune namespace.
Definition: alignedallocator.hh:13
ALUGridElementType
basic element types for ALUGrid
Definition: declaration.hh:17
@ simplex
use only simplex elements (i.e., triangles or tetrahedra)
Definition: declaration.hh:18
ALUGridRefinementType
available refinement types for ALUGrid
Definition: declaration.hh:24
@ conforming
use only conforming bisection refinement
Definition: declaration.hh:25
static const type & defaultValue()
default constructor
Definition: parser.hh:28
std::string type
type of additional boundary parameters
Definition: parser.hh:25
static double refineWeight()
static int refineStepsForHalf()
number of globalRefine steps needed to refuce h by 0.5
static const ReferenceElement & general(const GeometryType &type)
get general reference elements
Definition: referenceelements.hh:198
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)