Dune Core Modules (unstable)

gmsh2parser.hh
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
20
21#include <dune/geometry/type.hh>
22
25
26namespace 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_,
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 {
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);
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) {
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
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
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
Base class for grid boundary segments of arbitrary geometry.
constexpr FieldTraits< value_type >::real_type two_norm() const
two norm sqrt(sum over squared values of entries)
Definition: densevector.hh:642
constexpr 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:97
Provide a generic factory class for unstructured grids.
Definition: gridfactory.hh:275
virtual void insertElement(const GeometryType &type, const std::vector< unsigned int > &vertices)
Insert an element into the coarse grid.
Definition: gridfactory.hh:307
virtual void insertVertex(const FieldVector< ctype, dimworld > &pos)
Insert a vertex into the coarse grid.
Definition: gridfactory.hh:296
virtual void insertBoundarySegment(const std::vector< unsigned int > &vertices)
insert a boundary segment
Definition: gridfactory.hh:325
Default exception class for I/O errors.
Definition: exceptions.hh:325
Provide a generic factory class for unstructured grids.
A few common exception classes.
int renumber(const Dune::GeometryType &t, int i)
renumber VTK <-> Dune
Definition: common.hh:186
Implements a vector constructed from a given type representing a field and a compile-time given size.
#define DUNE_THROW(E,...)
Definition: exceptions.hh:314
constexpr GeometryType line
GeometryType representing a line.
Definition: type.hh:498
constexpr GeometryType prism
GeometryType representing a 3D prism.
Definition: type.hh:528
constexpr GeometryType triangle
GeometryType representing a triangle.
Definition: type.hh:504
constexpr GeometryType quadrilateral
GeometryType representing a quadrilateral (a square).
Definition: type.hh:510
constexpr GeometryType hexahedron
GeometryType representing a hexahedron.
Definition: type.hh:534
constexpr GeometryType pyramid
GeometryType representing a 3D pyramid.
Definition: type.hh:522
constexpr GeometryType tetrahedron
GeometryType representing a tetrahedron.
Definition: type.hh:516
static std::string formatString(const std::string &s, const T &... args)
Format values according to printf format string.
Definition: stringutility.hh:73
Base class for classes implementing geometries of boundary segments.
Definition: boundarysegment.hh:94
A unique label for each type of element that can occur in a grid.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Nov 2, 23:43, 2025)