dune-grid  2.11
gmsh2parser.hh
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4 // vi: set et ts=4 sw=2 sts=2:
5 
6 #ifndef DUNE_GRID_IO_FILE_GMSH_GMSH2PARSER_HH
7 #define DUNE_GRID_IO_FILE_GMSH_GMSH2PARSER_HH
8 
9 #include <cstdarg>
10 #include <fstream>
11 #include <iostream>
12 #include <map>
13 #include <memory>
14 #include <string>
15 #include <vector>
16 #include <utility>
17 
18 #include <dune/common/exceptions.hh>
19 #include <dune/common/fvector.hh>
20 
21 #include <dune/geometry/type.hh>
22 
25 
26 namespace Dune::Impl::Gmsh
27 {
28  // arbitrary dimension, implementation is in specialization
29  template< int dimension, int dimWorld = dimension >
30  class GmshReaderQuadraticBoundarySegment
31  {
32  public:
33  // empty function since this class does not implement anything
34  static void registerFactory() {}
35  };
36 
37  // quadratic boundary segments in 1d
38  /*
39  Note the points
40 
41  (0) (alpha) (1)
42 
43  are mapped to the points in global coordinates
44 
45  p0 p2 p1
46 
47  alpha is determined automatically from the given points.
48  */
49  template< int dimWorld >
50  struct GmshReaderQuadraticBoundarySegment< 2, dimWorld >
51  : public Dune::BoundarySegment< 2, dimWorld >
52  {
53  typedef GmshReaderQuadraticBoundarySegment< 2, dimWorld > ThisType;
54  typedef typename Dune::BoundarySegment< 2, dimWorld > :: ObjectStreamType ObjectStreamType;
55  typedef Dune::FieldVector< double, dimWorld > GlobalVector;
56 
57  GmshReaderQuadraticBoundarySegment ( const GlobalVector &p0_, const GlobalVector &p1_, const GlobalVector &p2_)
58  : p0(p0_), p1(p1_), p2(p2_)
59  {
60  init();
61  }
62 
63  GmshReaderQuadraticBoundarySegment( ObjectStreamType& in )
64  {
65  // key is read before by the factory
66  const int bytes = sizeof(double)*dimWorld;
67  in.read( (char *) &p0[ 0 ], bytes );
68  in.read( (char *) &p1[ 0 ], bytes );
69  in.read( (char *) &p2[ 0 ], bytes );
70  init();
71  }
72 
73  static void registerFactory()
74  {
75  if( key() < 0 )
76  {
77  key() = Dune::BoundarySegment< 2, dimWorld >::template registerFactory< ThisType >();
78  }
79  }
80 
81  virtual GlobalVector operator() ( const Dune::FieldVector<double,1> &local ) const
82  {
83  GlobalVector y;
84  y = 0.0;
85  y.axpy((local[0]-alpha)*(local[0]-1.0)/alpha,p0);
86  y.axpy(local[0]*(local[0]-1.0)/(alpha*(alpha-1.0)),p1);
87  y.axpy(local[0]*(local[0]-alpha)/(1.0-alpha),p2);
88  return y;
89  }
90 
91  void backup( ObjectStreamType& out ) const
92  {
93  // backup key to identify object
94  out.write( (const char *) &key(), sizeof( int ) );
95  // backup data
96  const int bytes = sizeof(double)*dimWorld;
97  out.write( (const char*) &p0[ 0 ], bytes );
98  out.write( (const char*) &p1[ 0 ], bytes );
99  out.write( (const char*) &p2[ 0 ], bytes );
100  }
101 
102  protected:
103  void init()
104  {
105  GlobalVector d1 = p1;
106  d1 -= p0;
107  GlobalVector d2 = p2;
108  d2 -= p1;
109 
110  alpha=d1.two_norm()/(d1.two_norm()+d2.two_norm());
111  if (alpha<1E-6 || alpha>1-1E-6)
112  DUNE_THROW(Dune::IOError, "ration in quadratic boundary segment bad");
113  }
114 
115  static int& key() {
116  static int k = -1;
117  return k;
118  }
119 
120  private:
121  GlobalVector p0,p1,p2;
122  double alpha;
123  };
124 
125 
126  // quadratic boundary segments in 2d
127  /* numbering of points corresponding to gmsh:
128 
129  2
130 
131  5 4
132 
133  0 3 1
134 
135  Note: The vertices 3, 4, 5 are not necessarily at the edge midpoints but can
136  be placed with parameters alpha, beta , gamma at the following positions
137  in local coordinates:
138 
139 
140  2 = (0,1)
141 
142  5 = (0,beta) 4 = (1-gamma/sqrt(2),gamma/sqrt(2))
143 
144  0 = (0,0) 3 = (alpha,0) 1 = (1,0)
145 
146  The parameters alpha, beta, gamma are determined from the given vertices in
147  global coordinates.
148  */
149  template<>
150  class GmshReaderQuadraticBoundarySegment< 3, 3 >
151  : public Dune::BoundarySegment< 3 >
152  {
153  typedef GmshReaderQuadraticBoundarySegment< 3, 3 > ThisType;
154  typedef typename Dune::BoundarySegment< 3 > :: ObjectStreamType ObjectStreamType;
155  public:
156  GmshReaderQuadraticBoundarySegment (Dune::FieldVector<double,3> p0_, Dune::FieldVector<double,3> p1_,
157  Dune::FieldVector<double,3> p2_, Dune::FieldVector<double,3> p3_,
158  Dune::FieldVector<double,3> p4_, Dune::FieldVector<double,3> p5_)
159  : p0(p0_), p1(p1_), p2(p2_), p3(p3_), p4(p4_), p5(p5_)
160  {
161  init();
162  }
163 
164  GmshReaderQuadraticBoundarySegment( ObjectStreamType& in )
165  {
166  const int bytes = sizeof(double)*3;
167  in.read( (char *) &p0[ 0 ], bytes );
168  in.read( (char *) &p1[ 0 ], bytes );
169  in.read( (char *) &p2[ 0 ], bytes );
170  in.read( (char *) &p3[ 0 ], bytes );
171  in.read( (char *) &p4[ 0 ], bytes );
172  in.read( (char *) &p5[ 0 ], bytes );
173  init();
174  }
175 
176  static void registerFactory()
177  {
178  if( key() < 0 )
179  {
180  key() = Dune::BoundarySegment< 3 >::template registerFactory< ThisType >();
181  }
182  }
183 
184  virtual Dune::FieldVector<double,3> operator() (const Dune::FieldVector<double,2>& local) const
185  {
186  Dune::FieldVector<double,3> y;
187  y = 0.0;
188  y.axpy(phi0(local),p0);
189  y.axpy(phi1(local),p1);
190  y.axpy(phi2(local),p2);
191  y.axpy(phi3(local),p3);
192  y.axpy(phi4(local),p4);
193  y.axpy(phi5(local),p5);
194  return y;
195  }
196 
197  void backup( ObjectStreamType& out ) const
198  {
199  // backup key to identify object in factory
200  out.write( (const char*) &key(), sizeof( int ) );
201  // backup data
202  const int bytes = sizeof(double)*3;
203  out.write( (const char*) &p0[ 0 ], bytes );
204  out.write( (const char*) &p1[ 0 ], bytes );
205  out.write( (const char*) &p2[ 0 ], bytes );
206  out.write( (const char*) &p3[ 0 ], bytes );
207  out.write( (const char*) &p4[ 0 ], bytes );
208  out.write( (const char*) &p5[ 0 ], bytes );
209  }
210 
211  protected:
212  void init()
213  {
214  using std::sqrt;
215  sqrt2 = sqrt(2.0);
216  Dune::FieldVector<double,3> d1,d2;
217 
218  d1 = p3; d1 -= p0;
219  d2 = p1; d2 -= p3;
220  alpha=d1.two_norm()/(d1.two_norm()+d2.two_norm());
221  if (alpha<1E-6 || alpha>1-1E-6)
222  DUNE_THROW(Dune::IOError, "alpha in quadratic boundary segment bad");
223 
224  d1 = p5; d1 -= p0;
225  d2 = p2; d2 -= p5;
226  beta=d1.two_norm()/(d1.two_norm()+d2.two_norm());
227  if (beta<1E-6 || beta>1-1E-6)
228  DUNE_THROW(Dune::IOError, "beta in quadratic boundary segment bad");
229 
230  d1 = p4; d1 -= p1;
231  d2 = p2; d2 -= p4;
232  gamma=sqrt2*(d1.two_norm()/(d1.two_norm()+d2.two_norm()));
233  if (gamma<1E-6 || gamma>1-1E-6)
234  DUNE_THROW(Dune::IOError, "gamma in quadratic boundary segment bad");
235  }
236 
237  static int& key() {
238  static int k = -1;
239  return k;
240  }
241 
242  private:
243  // The six Lagrange basis function on the reference element
244  // for the points given above
245 
246  double phi0 (const Dune::FieldVector<double,2>& local) const
247  {
248  return (alpha*beta-beta*local[0]-alpha*local[1])*(1-local[0]-local[1])/(alpha*beta);
249  }
250  double phi3 (const Dune::FieldVector<double,2>& local) const
251  {
252  return local[0]*(1-local[0]-local[1])/(alpha*(1-alpha));
253  }
254  double phi1 (const Dune::FieldVector<double,2>& local) const
255  {
256  return local[0]*(gamma*local[0]-(sqrt2-gamma-sqrt2*alpha)*local[1]-alpha*gamma)/(gamma*(1-alpha));
257  }
258  double phi5 (const Dune::FieldVector<double,2>& local) const
259  {
260  return local[1]*(1-local[0]-local[1])/(beta*(1-beta));
261  }
262  double phi4 (const Dune::FieldVector<double,2>& local) const
263  {
264  return local[0]*local[1]/((1-gamma/sqrt2)*gamma/sqrt2);
265  }
266  double phi2 (const Dune::FieldVector<double,2>& local) const
267  {
268  return local[1]*(beta*(1-gamma/sqrt2)-local[0]*(beta-gamma/sqrt2)-local[1]*(1-gamma/sqrt2))/((1-gamma/sqrt2)*(beta-1));
269  }
270 
271  Dune::FieldVector<double,3> p0,p1,p2,p3,p4,p5;
272  double alpha,beta,gamma,sqrt2;
273  };
274 
275 
278  template<typename GridType>
279  class Gmsh2Parser
280  {
281  protected:
282  // private data
284  bool verbose;
285  bool insert_boundary_segments;
286  unsigned int number_of_real_vertices;
287  int boundary_element_count;
288  int element_count;
289  // read buffer
290  char buf[512];
291  std::string fileName;
292  // exported data
293  std::vector<int> boundary_id_to_physical_entity;
294  std::vector<int> element_index_to_physical_entity;
295  std::vector<std::string> physical_entity_names;
296 
297  // static data
298  static const int dim = GridType::dimension;
299  static const int dimWorld = GridType::dimensionworld;
300  static_assert( (dimWorld <= 3), "GmshReader requires dimWorld <= 3." );
301 
302  // typedefs
303  typedef FieldVector< double, dimWorld > GlobalVector;
304 
305  // don't use something like
306  // readfile(file, 1, "%s\n", buf);
307  // to skip the rest of of the line -- that will only skip the next
308  // whitespace-separated word! Use skipline() instead.
309  void readfile(FILE * file, int cnt, const char * format, ...)
310 #ifdef __GNUC__
311  __attribute__((format(scanf, 4, 5)))
312 #endif
313  {
314  std::va_list ap;
315  va_start(ap, format);
316  auto pos = std::ftell(file);
317  int c = std::vfscanf(file, format, ap);
318  va_end(ap);
319  if (c != cnt)
320  DUNE_THROW(Dune::IOError, "Error parsing " << fileName << " "
321  "file pos " << pos
322  << ": Expected '" << format << "', only read " << c << " entries instead of " << cnt << ".");
323  }
324 
325  // skip over the rest of the line, including the terminating newline
326  void skipline(FILE * file)
327  {
328  int c;
329  do {
330  c = std::fgetc(file);
331  } while(c != '\n' && c != EOF);
332  }
333 
334  public:
335 
336  Gmsh2Parser(Dune::GridFactory<GridType>& _factory, bool v, bool i) :
337  factory(_factory), verbose(v), insert_boundary_segments(i) {}
338 
339  std::vector<int> & boundaryIdMap()
340  {
341  return boundary_id_to_physical_entity;
342  }
343 
345  std::vector<int> & elementIndexMap()
346  {
347  return element_index_to_physical_entity;
348  }
349 
351  std::vector<std::string> & physicalEntityNames()
352  {
353  return physical_entity_names;
354  }
355 
356  void read (const std::string& f)
357  {
358  if (verbose) std::cout << "Reading " << dim << "d Gmsh grid..." << std::endl;
359 
360  // open file name, we use C I/O
361  fileName = f;
362  FILE* file = fopen(fileName.c_str(),"rb");
363  if (file==0)
364  DUNE_THROW(Dune::IOError, "Could not open " << fileName);
365 
366  //=========================================
367  // Header: Read vertices into vector
368  // Check vertices that are needed
369  //=========================================
370 
371  number_of_real_vertices = 0;
372  boundary_element_count = 0;
373  element_count = 0;
374 
375  // process header
376  double version_number;
377  int file_type, data_size;
378 
379  readfile(file,1,"%s\n",buf);
380  if (strcmp(buf,"$MeshFormat")!=0)
381  DUNE_THROW(Dune::IOError, "expected $MeshFormat in first line");
382  readfile(file,3,"%lg %d %d\n",&version_number,&file_type,&data_size);
383  // 2.2 is not representable as float and leads to problems on i386
384  // Hence we use >= 2.00001.
385  if( (version_number < 2.0) || (version_number >= 2.20001) ) // 2.2 is not representable as float and leads to problems on i386
386  DUNE_THROW(Dune::IOError, "can only read Gmsh version 2 files");
387  if (verbose) std::cout << "version " << version_number << " Gmsh file detected" << std::endl;
388  readfile(file,1,"%s\n",buf);
389  if (strcmp(buf,"$EndMeshFormat")!=0)
390  DUNE_THROW(Dune::IOError, "expected $EndMeshFormat");
391 
392  // physical name section
393  physical_entity_names.clear();
394  readfile(file,1,"%s\n",buf);
395  if (strcmp(buf,"$PhysicalNames")==0) {
396  int number_of_names;
397  readfile(file,1,"%d\n",&number_of_names);
398  if (verbose) std::cout << "file contains " << number_of_names << " physical entities" << std::endl;
399  physical_entity_names.resize(number_of_names);
400  std::string buf_name;
401  for( int i = 0; i < number_of_names; ++i ) {
402  int edim, id;
403  readfile(file,3, "%d %d %s\n", &edim, &id, buf);
404  buf_name.assign(buf);
405  auto begin = buf_name.find_first_of('\"') + 1;
406  auto end = buf_name.find_last_of('\"') - begin;
407  physical_entity_names[id-1].assign(buf_name.substr(begin, end));
408  }
409  readfile(file,1,"%s\n",buf);
410  if (strcmp(buf,"$EndPhysicalNames")!=0)
411  DUNE_THROW(Dune::IOError, "expected $EndPhysicalNames");
412  readfile(file,1,"%s\n",buf);
413  }
414 
415  // node section
416  int number_of_nodes;
417 
418  if (strcmp(buf,"$Nodes")!=0)
419  DUNE_THROW(Dune::IOError, "expected $Nodes");
420  readfile(file,1,"%d\n",&number_of_nodes);
421  if (verbose) std::cout << "file contains " << number_of_nodes << " nodes" << std::endl;
422 
423  // read nodes
424  // The '+1' is due to the fact that gmsh numbers node starting from 1 rather than from 0
425  std::vector< GlobalVector > nodes( number_of_nodes+1 );
426  {
427  int id;
428  double x[ 3 ];
429  for( int i = 1; i <= number_of_nodes; ++i )
430  {
431  readfile(file,4, "%d %lg %lg %lg\n", &id, &x[ 0 ], &x[ 1 ], &x[ 2 ] );
432 
433  if (id > number_of_nodes) {
434  DUNE_THROW(Dune::IOError,
435  "Only dense sequences of node indices are currently supported (node index "
436  << id << " is invalid).");
437  }
438 
439  // just store node position
440  for( int j = 0; j < dimWorld; ++j )
441  nodes[ id ][ j ] = x[ j ];
442  }
443  readfile(file,1,"%s\n",buf);
444  if (strcmp(buf,"$EndNodes")!=0)
445  DUNE_THROW(Dune::IOError, "expected $EndNodes");
446  }
447 
448  // element section
449  readfile(file,1,"%s\n",buf);
450  if (strcmp(buf,"$Elements")!=0)
451  DUNE_THROW(Dune::IOError, "expected $Elements");
452  int number_of_elements;
453  readfile(file,1,"%d\n",&number_of_elements);
454  if (verbose) std::cout << "file contains " << number_of_elements << " elements" << std::endl;
455 
456  //=========================================
457  // Pass 1: Select and insert those vertices in the file that
458  // actually occur as corners of an element.
459  //=========================================
460 
461  auto section_element_offset = std::ftell(file);
462  std::map<int,unsigned int> renumber;
463  for (int i=1; i<=number_of_elements; i++)
464  {
465  int id, elm_type, number_of_tags;
466  readfile(file,3,"%d %d %d ",&id,&elm_type,&number_of_tags);
467  for (int k=1; k<=number_of_tags; k++)
468  {
469  int blub;
470  readfile(file,1,"%d ",&blub);
471  // k == 1: physical entity
472  // k == 2: elementary entity (not used here)
473  // if version_number < 2.2:
474  // k == 3: mesh partition 0
475  // else
476  // k == 3: number of mesh partitions
477  // k => 4: mesh partition k-4
478  }
479  pass1HandleElement(file, elm_type, renumber, nodes);
480  }
481  if (verbose) std::cout << "number of real vertices = " << number_of_real_vertices << std::endl;
482  if (verbose) std::cout << "number of boundary elements = " << boundary_element_count << std::endl;
483  if (verbose) std::cout << "number of elements = " << element_count << std::endl;
484  readfile(file,1,"%s\n",buf);
485  if (strcmp(buf,"$EndElements")!=0)
486  DUNE_THROW(Dune::IOError, "expected $EndElements");
487  boundary_id_to_physical_entity.resize(boundary_element_count);
488  element_index_to_physical_entity.resize(element_count);
489 
490  //==============================================
491  // Pass 2: Insert boundary segments and elements
492  //==============================================
493 
494  std::fseek(file, section_element_offset, SEEK_SET);
495  boundary_element_count = 0;
496  element_count = 0;
497  for (int i=1; i<=number_of_elements; i++)
498  {
499  int id, elm_type, number_of_tags;
500  readfile(file,3,"%d %d %d ",&id,&elm_type,&number_of_tags);
501  int physical_entity = -1;
502 
503  for (int k=1; k<=number_of_tags; k++)
504  {
505  int blub;
506  readfile(file,1,"%d ",&blub);
507  if (k==1) physical_entity = blub;
508  }
509  pass2HandleElement(file, elm_type, renumber, nodes, physical_entity);
510  }
511  readfile(file,1,"%s\n",buf);
512  if (strcmp(buf,"$EndElements")!=0)
513  DUNE_THROW(Dune::IOError, "expected $EndElements");
514 
515  fclose(file);
516  }
517 
523  void pass1HandleElement(FILE* file, const int elm_type,
524  std::map<int,unsigned int> & renumber,
525  const std::vector< GlobalVector > & nodes)
526  {
527  // some data about gmsh elements
528  const int nDofs[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 3, 6, -1, 10, -1, -1, -1, 1};
529  const int nVertices[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 2, 3, -1, 4, -1, -1, -1, 1};
530  const int elementDim[16] = {-1, 1, 2, 2, 3, 3, 3, 3, 1, 2, -1, 3, -1, -1, -1, 0};
531 
532  // test whether we support the element type
533  if ( not (elm_type > 0 && elm_type <= 15 // index in suitable range?
534  && (elementDim[elm_type] == dim || elementDim[elm_type] == (dim-1) ) ) ) // real element or boundary element?
535  {
536  skipline(file); // skip rest of line if element is unknown
537  return;
538  }
539 
540  // The format string for parsing is n times '%d' in a row
541  std::string formatString = "%d";
542  for (int i=1; i<nDofs[elm_type]; i++)
543  formatString += " %d";
544  formatString += "\n";
545 
546  // '10' is the largest number of dofs we may encounter in a .msh file
547  std::vector<int> elementDofs(10);
548 
549  readfile(file,nDofs[elm_type], formatString.c_str(),
550  &(elementDofs[0]),&(elementDofs[1]),&(elementDofs[2]),
551  &(elementDofs[3]),&(elementDofs[4]),&(elementDofs[5]),
552  &(elementDofs[6]),&(elementDofs[7]),&(elementDofs[8]),
553  &(elementDofs[9]));
554 
555  // insert each vertex if it hasn't been inserted already
556  for (int i=0; i<nVertices[elm_type]; i++)
557  if (renumber.find(elementDofs[i])==renumber.end())
558  {
559  renumber[elementDofs[i]] = number_of_real_vertices++;
560  factory.insertVertex(nodes[elementDofs[i]]);
561  }
562 
563  // count elements and boundary elements
564  if (elementDim[elm_type] == dim)
565  element_count++;
566  else
567  boundary_element_count++;
568 
569  }
570 
571 
572 
573  // generic-case: This is not supposed to be used at runtime.
574  template <class E, class V, class V2>
575  void boundarysegment_insert(
576  const V&,
577  const E&,
578  const V2&
579  )
580  {
581  DUNE_THROW(Dune::IOError, "tried to create a 3D boundary segment in a non-3D Grid");
582  }
583 
584  // 3d-case:
585  template <class E, class V>
586  void boundarysegment_insert(
587  const std::vector<FieldVector<double, 3> >& nodes,
588  const E& elementDofs,
589  const V& vertices
590  )
591  {
592  std::array<FieldVector<double,dimWorld>, 6> v;
593  for (int i=0; i<6; i++)
594  for (int j=0; j<dimWorld; j++)
595  v[i][j] = nodes[elementDofs[i]][j];
596 
597  BoundarySegment<dim,dimWorld>* newBoundarySegment
598  = (BoundarySegment<dim,dimWorld>*) new GmshReaderQuadraticBoundarySegment< 3, 3 >( v[0], v[1], v[2],
599  v[3], v[4], v[5] );
600 
601  factory.insertBoundarySegment( vertices,
602  std::shared_ptr<BoundarySegment<dim,dimWorld> >(newBoundarySegment) );
603  }
604 
605 
606 
611  virtual void pass2HandleElement(FILE* file, const int elm_type,
612  std::map<int,unsigned int> & renumber,
613  const std::vector< GlobalVector > & nodes,
614  const int physical_entity)
615  {
616  // some data about gmsh elements
617  const int nDofs[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 3, 6, -1, 10, -1, -1, -1, 1};
618  const int nVertices[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 2, 3, -1, 4, -1, -1, -1, 1};
619  const int elementDim[16] = {-1, 1, 2, 2, 3, 3, 3, 3, 1, 2, -1, 3, -1, -1, -1, 0};
620 
621  // test whether we support the element type
622  if ( not (elm_type > 0 && elm_type <= 15 // index in suitable range?
623  && (elementDim[elm_type] == dim || elementDim[elm_type] == (dim-1) ) ) ) // real element or boundary element?
624  {
625  skipline(file); // skip rest of line if element is unknown
626  return;
627  }
628 
629  // The format string for parsing is n times '%d' in a row
630  std::string formatString = "%d";
631  for (int i=1; i<nDofs[elm_type]; i++)
632  formatString += " %d";
633  formatString += "\n";
634 
635  // '10' is the largest number of dofs we may encounter in a .msh file
636  std::vector<int> elementDofs(10);
637 
638  readfile(file,nDofs[elm_type], formatString.c_str(),
639  &(elementDofs[0]),&(elementDofs[1]),&(elementDofs[2]),
640  &(elementDofs[3]),&(elementDofs[4]),&(elementDofs[5]),
641  &(elementDofs[6]),&(elementDofs[7]),&(elementDofs[8]),
642  &(elementDofs[9]));
643 
644  // correct differences between gmsh and Dune in the local vertex numbering
645  switch (elm_type)
646  {
647  case 3 : // 4-node quadrilateral
648  std::swap(elementDofs[2],elementDofs[3]);
649  break;
650  case 5 : // 8-node hexahedron
651  std::swap(elementDofs[2],elementDofs[3]);
652  std::swap(elementDofs[6],elementDofs[7]);
653  break;
654  case 7 : // 5-node pyramid
655  std::swap(elementDofs[2],elementDofs[3]);
656  break;
657  }
658 
659  // renumber corners to account for the explicitly given vertex
660  // numbering in the file
661  std::vector<unsigned int> vertices(nVertices[elm_type]);
662 
663  for (int i=0; i<nVertices[elm_type]; i++)
664  vertices[i] = renumber[elementDofs[i]];
665 
666  // If it is an element, insert it as such
667  if (elementDim[elm_type] == dim) {
668 
669  switch (elm_type)
670  {
671  case 1 : // 2-node line
672  factory.insertElement(Dune::GeometryTypes::line,vertices);
673  break;
674  case 2 : // 3-node triangle
676  break;
677  case 3 : // 4-node quadrilateral
679  break;
680  case 4 : // 4-node tetrahedron
682  break;
683  case 5 : // 8-node hexahedron
685  break;
686  case 6 : // 6-node prism
687  factory.insertElement(Dune::GeometryTypes::prism,vertices);
688  break;
689  case 7 : // 5-node pyramid
691  break;
692  case 9 : // 6-node triangle
694  break;
695  case 11 : // 10-node tetrahedron
697  break;
698  }
699 
700  } else {
701  // it must be a boundary segment then
702  if (insert_boundary_segments) {
703 
704  switch (elm_type)
705  {
706  case 1 : // 2-node line
707  factory.insertBoundarySegment(vertices);
708  break;
709 
710  case 2 : // 3-node triangle
711  factory.insertBoundarySegment(vertices);
712  break;
713 
714  case 3 : // 4-node quadrilateral
715  factory.insertBoundarySegment(vertices);
716  break;
717 
718  case 15 : // 1-node point
719  factory.insertBoundarySegment(vertices);
720  break;
721 
722  case 8 : { // 3-node line
723  std::array<FieldVector<double,dimWorld>, 3> v;
724  for (int i=0; i<dimWorld; i++) {
725  v[0][i] = nodes[elementDofs[0]][i];
726  v[1][i] = nodes[elementDofs[2]][i]; // yes, the renumbering is intended!
727  v[2][i] = nodes[elementDofs[1]][i];
728  }
729  BoundarySegment<dim,dimWorld>* newBoundarySegment
730  = (BoundarySegment<dim,dimWorld>*) new GmshReaderQuadraticBoundarySegment< 2, dimWorld >(v[0], v[1], v[2]);
731  factory.insertBoundarySegment(vertices,
732  std::shared_ptr<BoundarySegment<dim,dimWorld> >(newBoundarySegment));
733  break;
734  }
735  case 9 : { // 6-node triangle
736  boundarysegment_insert(nodes, elementDofs, vertices);
737  break;
738  }
739  default: {
740  DUNE_THROW(Dune::IOError, "GmshReader does not support using element-type " << elm_type << " for boundary segments");
741  break;
742  }
743 
744  }
745 
746  }
747  }
748 
749  // count elements and boundary elements
750  if (elementDim[elm_type] == dim) {
751  element_index_to_physical_entity[element_count] = physical_entity;
752  element_count++;
753  } else {
754  boundary_id_to_physical_entity[boundary_element_count] = physical_entity;
755  boundary_element_count++;
756  }
757 
758  }
759 
760  };
761 
762 } // namespace Dune::Impl::Gmsh
763 
764 #endif
Definition: common.hh:141
void swap(Dune::PersistentContainer< G, T > &a, Dune::PersistentContainer< G, T > &b)
Definition: utility/persistentcontainer.hh:83
Base class for classes implementing geometries of boundary segments.
Definition: boundarysegment.hh:37
Base class for grid boundary segments of arbitrary geometry.
ALBERTA REAL_D GlobalVector
Definition: misc.hh:50
Provide a generic factory class for unstructured grids.
Definition: common.hh:134
Definition: common.hh:140
int renumber(const Dune::GeometryType &t, int i)
renumber VTK <-> Dune
Definition: common.hh:186
virtual void insertBoundarySegment([[maybe_unused]] const std::vector< unsigned int > &vertices)
insert a boundary segment
Definition: common/gridfactory.hh:325
Definition: common.hh:139
Provide a generic factory class for unstructured grids.
Definition: common/gridfactory.hh:275
Definition: filereader.hh:14
Definition: common.hh:138
Definition: common.hh:137
virtual void insertElement([[maybe_unused]] const GeometryType &type, [[maybe_unused]] const std::vector< unsigned int > &vertices)
Insert an element into the coarse grid.
Definition: common/gridfactory.hh:307
Definition: common.hh:135
static const int dimWorld
Definition: misc.hh:46
virtual void insertVertex([[maybe_unused]] const FieldVector< ctype, dimworld > &pos)
Insert a vertex into the coarse grid.
Definition: common/gridfactory.hh:296