4#ifndef DUNE_GMSHREADER_HH
5#define DUNE_GMSHREADER_HH
19#include <dune/common/to_unique_ptr.hh>
48 template<
int dimension,
int dimWorld = dimension >
49 class GmshReaderQuadraticBoundarySegment
53 static void registerFactory() {}
68 template<
int dimWorld >
69 struct GmshReaderQuadraticBoundarySegment< 2, dimWorld >
72 typedef GmshReaderQuadraticBoundarySegment< 2, dimWorld > ThisType;
76 GmshReaderQuadraticBoundarySegment (
const GlobalVector &p0_,
const GlobalVector &p1_,
const GlobalVector &p2_)
77 : p0(p0_), p1(p1_), p2(p2_)
82 GmshReaderQuadraticBoundarySegment( ObjectStreamType& in )
85 const int bytes =
sizeof(double)*dimWorld;
86 in.read( (
char *) &p0[ 0 ], bytes );
87 in.read( (
char *) &p1[ 0 ], bytes );
88 in.read( (
char *) &p2[ 0 ], bytes );
92 static void registerFactory()
104 y.axpy((local[0]-alpha)*(local[0]-1.0)/alpha,p0);
105 y.axpy(local[0]*(local[0]-1.0)/(alpha*(alpha-1.0)),p1);
106 y.axpy(local[0]*(local[0]-alpha)/(1.0-alpha),p2);
110 void backup( ObjectStreamType& out )
const
113 out.write( (
const char *) &key(),
sizeof(
int ) );
115 const int bytes =
sizeof(double)*dimWorld;
116 out.write( (
const char*) &p0[ 0 ], bytes );
117 out.write( (
const char*) &p1[ 0 ], bytes );
118 out.write( (
const char*) &p2[ 0 ], bytes );
124 GlobalVector d1 = p1;
126 GlobalVector d2 = p2;
129 alpha=d1.two_norm()/(d1.two_norm()+d2.two_norm());
130 if (alpha<1E-6 || alpha>1-1E-6)
140 GlobalVector p0,p1,p2;
169 class GmshReaderQuadraticBoundarySegment< 3, 3 >
172 typedef GmshReaderQuadraticBoundarySegment< 3, 3 > ThisType;
178 : p0(p0_), p1(p1_), p2(p2_), p3(p3_), p4(p4_), p5(p5_)
183 GmshReaderQuadraticBoundarySegment( ObjectStreamType& in )
185 const int bytes =
sizeof(double)*3;
186 in.read( (
char *) &p0[ 0 ], bytes );
187 in.read( (
char *) &p1[ 0 ], bytes );
188 in.read( (
char *) &p2[ 0 ], bytes );
189 in.read( (
char *) &p3[ 0 ], bytes );
190 in.read( (
char *) &p4[ 0 ], bytes );
191 in.read( (
char *) &p5[ 0 ], bytes );
195 static void registerFactory()
207 y.
axpy(phi0(local),p0);
208 y.
axpy(phi1(local),p1);
209 y.
axpy(phi2(local),p2);
210 y.
axpy(phi3(local),p3);
211 y.
axpy(phi4(local),p4);
212 y.
axpy(phi5(local),p5);
216 void backup( ObjectStreamType& out )
const
219 out.write( (
const char*) &key(),
sizeof(
int ) );
221 const int bytes =
sizeof(double)*3;
222 out.write( (
const char*) &p0[ 0 ], bytes );
223 out.write( (
const char*) &p1[ 0 ], bytes );
224 out.write( (
const char*) &p2[ 0 ], bytes );
225 out.write( (
const char*) &p3[ 0 ], bytes );
226 out.write( (
const char*) &p4[ 0 ], bytes );
227 out.write( (
const char*) &p5[ 0 ], bytes );
239 if (alpha<1E-6 || alpha>1-1E-6)
245 if (beta<1E-6 || beta>1-1E-6)
251 if (gamma<1E-6 || gamma>1-1E-6)
266 return (alpha*beta-beta*local[0]-alpha*local[1])*(1-local[0]-local[1])/(alpha*beta);
270 return local[0]*(1-local[0]-local[1])/(alpha*(1-alpha));
274 return local[0]*(gamma*local[0]-(sqrt2-gamma-sqrt2*alpha)*local[1]-alpha*gamma)/(gamma*(1-alpha));
278 return local[1]*(1-local[0]-local[1])/(beta*(1-beta));
282 return local[0]*local[1]/((1-gamma/sqrt2)*gamma/sqrt2);
286 return local[1]*(beta*(1-gamma/sqrt2)-local[0]*(beta-gamma/sqrt2)-local[1]*(1-gamma/sqrt2))/((1-gamma/sqrt2)*(beta-1));
290 double alpha,beta,gamma,sqrt2;
296 template<
typename Gr
idType>
303 bool insert_boundary_segments;
304 unsigned int number_of_real_vertices;
305 int boundary_element_count;
309 std::string fileName;
311 std::vector<int> boundary_id_to_physical_entity;
312 std::vector<int> element_index_to_physical_entity;
315 static const int dim = GridType::dimension;
316 static const int dimWorld = GridType::dimensionworld;
317 static_assert( (dimWorld <= 3),
"GmshReader requires dimWorld <= 3." );
326 void readfile(FILE * file,
int cnt,
const char * format,
327 void* t1,
void* t2 = 0,
void* t3 = 0,
void* t4 = 0,
328 void* t5 = 0,
void* t6 = 0,
void* t7 = 0,
void* t8 = 0,
329 void* t9 = 0,
void* t10 = 0)
331 off_t pos = ftello(file);
332 int c = fscanf(file, format, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
336 <<
": Expected '" << format <<
"', only read " << c <<
" entries instead of " << cnt <<
".");
340 void skipline(FILE * file)
344 c = std::fgetc(file);
345 }
while(c !=
'\n' && c != EOF);
351 factory(_factory), verbose(v), insert_boundary_segments(i) {}
353 std::vector<int> & boundaryIdMap()
355 return boundary_id_to_physical_entity;
358 std::vector<int> & elementIndexMap()
360 return element_index_to_physical_entity;
363 void read (
const std::string& f)
365 if (verbose) std::cout <<
"Reading " << dim <<
"d Gmsh grid..." << std::endl;
369 FILE* file = fopen(fileName.c_str(),
"rb");
378 number_of_real_vertices = 0;
379 boundary_element_count = 0;
383 double version_number;
384 int file_type, data_size;
386 readfile(file,1,
"%s\n",buf);
387 if (strcmp(buf,
"$MeshFormat")!=0)
389 readfile(file,3,
"%lg %d %d\n",&version_number,&file_type,&data_size);
390 if( (version_number < 2.0) || (version_number > 2.2) )
392 if (verbose) std::cout <<
"version " << version_number <<
" Gmsh file detected" << std::endl;
393 readfile(file,1,
"%s\n",buf);
394 if (strcmp(buf,
"$EndMeshFormat")!=0)
400 readfile(file,1,
"%s\n",buf);
401 if (strcmp(buf,
"$Nodes")!=0)
403 readfile(file,1,
"%d\n",&number_of_nodes);
404 if (verbose) std::cout <<
"file contains " << number_of_nodes <<
" nodes" << std::endl;
408 std::vector< GlobalVector > nodes( number_of_nodes+1 );
412 for(
int i = 1; i <= number_of_nodes; ++i )
414 readfile(file,4,
"%d %lg %lg %lg\n", &
id, &x[ 0 ], &x[ 1 ], &x[ 2 ] );
416 if (
id > number_of_nodes) {
418 "Only dense sequences of node indices are currently supported (node index "
419 <<
id <<
" is invalid).");
423 for(
int j = 0; j < dimWorld; ++j )
424 nodes[
id ][ j ] = x[ j ];
426 readfile(file,1,
"%s\n",buf);
427 if (strcmp(buf,
"$EndNodes")!=0)
432 readfile(file,1,
"%s\n",buf);
433 if (strcmp(buf,
"$Elements")!=0)
435 int number_of_elements;
436 readfile(file,1,
"%d\n",&number_of_elements);
437 if (verbose) std::cout <<
"file contains " << number_of_elements <<
" elements" << std::endl;
444 off_t section_element_offset = ftello(file);
445 std::map<int,unsigned int> renumber;
446 for (
int i=1; i<=number_of_elements; i++)
448 int id, elm_type, number_of_tags;
449 readfile(file,3,
"%d %d %d ",&
id,&elm_type,&number_of_tags);
450 for (
int k=1; k<=number_of_tags; k++)
453 readfile(file,1,
"%d ",&blub);
464 if (verbose) std::cout <<
"number of real vertices = " << number_of_real_vertices << std::endl;
465 if (verbose) std::cout <<
"number of boundary elements = " << boundary_element_count << std::endl;
466 if (verbose) std::cout <<
"number of elements = " << element_count << std::endl;
467 readfile(file,1,
"%s\n",buf);
468 if (strcmp(buf,
"$EndElements")!=0)
470 boundary_id_to_physical_entity.resize(boundary_element_count);
471 element_index_to_physical_entity.resize(element_count);
477 fseeko(file, section_element_offset, SEEK_SET);
478 boundary_element_count = 0;
480 for (
int i=1; i<=number_of_elements; i++)
482 int id, elm_type, number_of_tags;
483 readfile(file,3,
"%d %d %d ",&
id,&elm_type,&number_of_tags);
484 int physical_entity = -1;
486 for (
int k=1; k<=number_of_tags; k++)
489 readfile(file,1,
"%d ",&blub);
490 if (k==1) physical_entity = blub;
494 readfile(file,1,
"%s\n",buf);
495 if (strcmp(buf,
"$EndElements")!=0)
507 std::map<int,unsigned int> & renumber,
508 const std::vector< GlobalVector > & nodes)
511 const int nDofs[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 3, 6, -1, 10, -1, -1, -1, 1};
512 const int nVertices[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 2, 3, -1, 4, -1, -1, -1, 1};
513 const int elementDim[16] = {-1, 1, 2, 2, 3, 3, 3, 3, 1, 2, -1, 3, -1, -1, -1, 0};
516 if ( not (elm_type > 0 && elm_type <= 15
517 && (elementDim[elm_type] == dim || elementDim[elm_type] == (dim-1) ) ) )
525 for (
int i=1; i<nDofs[elm_type]; i++)
530 std::vector<int> elementDofs(10);
533 &(elementDofs[0]),&(elementDofs[1]),&(elementDofs[2]),
534 &(elementDofs[3]),&(elementDofs[4]),&(elementDofs[5]),
535 &(elementDofs[6]),&(elementDofs[7]),&(elementDofs[8]),
539 for (
int i=0; i<nVertices[elm_type]; i++)
540 if (renumber.find(elementDofs[i])==renumber.end())
542 renumber[elementDofs[i]] = number_of_real_vertices++;
547 if (elementDim[elm_type] == dim)
550 boundary_element_count++;
557 template <
class E,
class V,
class V2>
558 void boundarysegment_insert(
560 const E& elementDofs,
568 template <
class E,
class V>
569 void boundarysegment_insert(
570 const std::vector<FieldVector<double, 3> >& nodes,
571 const E& elementDofs,
575 std::array<FieldVector<double,dimWorld>, 6> v;
576 for (
int i=0; i<6; i++)
577 for (
int j=0; j<dimWorld; j++)
578 v[i][j] = nodes[elementDofs[i]][j];
580 BoundarySegment<dim,dimWorld>* newBoundarySegment
581 = (BoundarySegment<dim,dimWorld>*)
new GmshReaderQuadraticBoundarySegment< 3, 3 >( v[0], v[1], v[2],
585 std::shared_ptr<BoundarySegment<dim,dimWorld> >(newBoundarySegment) );
595 std::map<int,unsigned int> & renumber,
596 const std::vector< GlobalVector > & nodes,
597 const int physical_entity)
600 const int nDofs[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 3, 6, -1, 10, -1, -1, -1, 1};
601 const int nVertices[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 2, 3, -1, 4, -1, -1, -1, 1};
602 const int elementDim[16] = {-1, 1, 2, 2, 3, 3, 3, 3, 1, 2, -1, 3, -1, -1, -1, 0};
605 if ( not (elm_type > 0 && elm_type <= 15
606 && (elementDim[elm_type] == dim || elementDim[elm_type] == (dim-1) ) ) )
614 for (
int i=1; i<nDofs[elm_type]; i++)
619 std::vector<int> elementDofs(10);
622 &(elementDofs[0]),&(elementDofs[1]),&(elementDofs[2]),
623 &(elementDofs[3]),&(elementDofs[4]),&(elementDofs[5]),
624 &(elementDofs[6]),&(elementDofs[7]),&(elementDofs[8]),
631 std::swap(elementDofs[2],elementDofs[3]);
634 std::swap(elementDofs[2],elementDofs[3]);
635 std::swap(elementDofs[6],elementDofs[7]);
638 std::swap(elementDofs[2],elementDofs[3]);
644 std::vector<unsigned int> vertices(nVertices[elm_type]);
646 for (
int i=0; i<nVertices[elm_type]; i++)
647 vertices[i] = renumber[elementDofs[i]];
650 if (elementDim[elm_type] == dim) {
685 if (insert_boundary_segments) {
706 std::array<FieldVector<double,dimWorld>, 3> v;
707 for (
int i=0; i<dimWorld; i++) {
708 v[0][i] = nodes[elementDofs[0]][i];
709 v[1][i] = nodes[elementDofs[2]][i];
710 v[2][i] = nodes[elementDofs[1]][i];
719 boundarysegment_insert(nodes, elementDofs, vertices);
729 if (elementDim[elm_type] == dim) {
730 element_index_to_physical_entity[element_count] = physical_entity;
733 boundary_id_to_physical_entity[boundary_element_count] = physical_entity;
734 boundary_element_count++;
765 template<
typename Gr
idType>
772 GmshReaderQuadraticBoundarySegment< Grid::dimension, Grid::dimensionworld >::registerFactory();
780 typedef GridType Grid;
794 registerFactory( factory );
800 parser.read(fileName);
813 std::vector<int>& boundarySegmentToPhysicalEntity,
814 std::vector<int>& elementToPhysicalEntity,
815 bool verbose =
true,
bool insertBoundarySegments=
true)
821 registerFactory( factory );
827 parser.read(fileName);
829 boundarySegmentToPhysicalEntity.swap(parser.boundaryIdMap());
830 elementToPhysicalEntity.swap(parser.elementIndexMap());
838 bool verbose =
true,
bool insertBoundarySegments=
true)
841 registerFactory( factory );
847 parser.read(fileName);
853 const std::string& fileName,
854 std::vector<int>& boundarySegmentToPhysicalEntity,
855 std::vector<int>& elementToPhysicalEntity,
856 bool verbose =
true,
bool insertBoundarySegments=
true)
859 registerFactory( factory );
865 parser.read(fileName);
867 boundarySegmentToPhysicalEntity.swap(parser.boundaryIdMap());
868 elementToPhysicalEntity.swap(parser.elementIndexMap());
Base class for grid boundary segments of arbitrary geometry.
int rank() const
Return rank, is between 0 and size()-1.
Definition: communication.hh:95
int barrier() const
Wait until all processes have arrived at this point in the program.
Definition: communication.hh:251
FieldTraits< value_type >::real_type two_norm() const
two norm sqrt(sum over squared values of entries)
Definition: densevector.hh:642
derived_type & axpy(const field_type &a, const DenseVector< Other > &x)
vector space axpy operation ( *this += a x )
Definition: densevector.hh:576
vector space out of a tensor product of fields.
Definition: fvector.hh:96
dimension independent parts for GmshReaderParser
Definition: gmshreader.hh:298
void pass1HandleElement(FILE *file, const int elm_type, std::map< int, unsigned int > &renumber, const std::vector< GlobalVector > &nodes)
Process one element during the first pass through the list of all elements.
Definition: gmshreader.hh:506
virtual void pass2HandleElement(FILE *file, const int elm_type, std::map< int, unsigned int > &renumber, const std::vector< GlobalVector > &nodes, const int physical_entity)
Process one element during the second pass through the list of all elements.
Definition: gmshreader.hh:594
Read Gmsh mesh file.
Definition: gmshreader.hh:767
static ToUniquePtr< Grid > read(const std::string &fileName, bool verbose=true, bool insertBoundarySegments=true)
Definition: gmshreader.hh:788
static void read(Dune::GridFactory< Grid > &factory, const std::string &fileName, bool verbose=true, bool insertBoundarySegments=true)
Definition: gmshreader.hh:837
static ToUniquePtr< Grid > read(const std::string &fileName, std::vector< int > &boundarySegmentToPhysicalEntity, std::vector< int > &elementToPhysicalEntity, bool verbose=true, bool insertBoundarySegments=true)
Definition: gmshreader.hh:812
static void read(Dune::GridFactory< Grid > &factory, const std::string &fileName, std::vector< int > &boundarySegmentToPhysicalEntity, std::vector< int > &elementToPhysicalEntity, bool verbose=true, bool insertBoundarySegments=true)
Definition: gmshreader.hh:852
Communication comm() const
Return the Communication used by the grid factory.
Definition: gridfactory.hh:252
Provide a generic factory class for unstructured grids.
Definition: gridfactory.hh:269
virtual void insertElement(const GeometryType &type, const std::vector< unsigned int > &vertices)
Insert an element into the coarse grid.
Definition: gridfactory.hh:301
virtual ToUniquePtr< GridType > createGrid()
Finalize grid creation and hand over the grid.
Definition: gridfactory.hh:327
virtual void insertVertex(const FieldVector< ctype, dimworld > &pos)
Insert a vertex into the coarse grid.
Definition: gridfactory.hh:290
virtual void insertBoundarySegment(const std::vector< unsigned int > &vertices)
insert a boundary segment
Definition: gridfactory.hh:319
Default exception class for I/O errors.
Definition: exceptions.hh:229
An owning pointer wrapper that can be assigned to (smart) pointers. Cannot be copied....
Definition: to_unique_ptr.hh:37
Provide a generic factory class for unstructured grids.
A few common exception classes.
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:216
constexpr GeometryType line
GeometryType representing a line.
Definition: type.hh:803
constexpr GeometryType prism
GeometryType representing a 3D prism.
Definition: type.hh:833
constexpr GeometryType triangle
GeometryType representing a triangle.
Definition: type.hh:809
constexpr GeometryType quadrilateral
GeometryType representing a quadrilateral (a square).
Definition: type.hh:815
constexpr GeometryType hexahedron
GeometryType representing a hexahedron.
Definition: type.hh:839
constexpr GeometryType pyramid
GeometryType representing a 3D pyramid.
Definition: type.hh:827
constexpr GeometryType tetrahedron
GeometryType representing a tetrahedron.
Definition: type.hh:821
static std::string formatString(const std::string &s, const T &... args)
Format values according to printf format string.
Definition: stringutility.hh:71
Dune namespace.
Definition: alignedallocator.hh:14
Base class for classes implementing geometries of boundary segments.
Definition: boundarysegment.hh:92
Options for read operation.
Definition: gmshreader.hh:36
GeometryOrder
Definition: gmshreader.hh:37
@ firstOrder
edges are straight lines.
Definition: gmshreader.hh:39
@ secondOrder
quadratic boundary approximation.
Definition: gmshreader.hh:41
A unique label for each type of element that can occur in a grid.