4 #ifndef DUNE_GMSHREADER_HH
5 #define DUNE_GMSHREADER_HH
18 #include <dune/common/exceptions.hh>
19 #include <dune/common/fvector.hh>
21 #include <dune/geometry/type.hh>
48 template<
int dimension,
int dimWorld = dimension >
49 class GmshReaderQuadraticBoundarySegment
65 template<
int dimWorld >
66 struct GmshReaderQuadraticBoundarySegment< 2,
dimWorld >
69 typedef Dune::FieldVector< double, dimWorld >
GlobalVector;
72 : p0(p0_), p1(p1_), p2(p2_)
79 alpha=d1.two_norm()/(d1.two_norm()+d2.two_norm());
80 if (alpha<1E-6 || alpha>1-1E-6)
81 DUNE_THROW(Dune::IOError,
"ration in quadratic boundary segment bad");
84 virtual GlobalVector operator() (
const Dune::FieldVector<double,1> &local )
const
88 y.axpy((local[0]-alpha)*(local[0]-1.0)/alpha,p0);
89 y.axpy(local[0]*(local[0]-1.0)/(alpha*(alpha-1.0)),p1);
90 y.axpy(local[0]*(local[0]-alpha)/(1.0-alpha),p2);
124 class GmshReaderQuadraticBoundarySegment< 3, 3 >
128 GmshReaderQuadraticBoundarySegment (Dune::FieldVector<double,3> p0_, Dune::FieldVector<double,3> p1_,
129 Dune::FieldVector<double,3> p2_, Dune::FieldVector<double,3> p3_,
130 Dune::FieldVector<double,3> p4_, Dune::FieldVector<double,3> p5_)
131 : p0(p0_), p1(p1_), p2(p2_), p3(p3_), p4(p4_), p5(p5_)
134 Dune::FieldVector<double,3> d1,d2;
138 alpha=d1.two_norm()/(d1.two_norm()+d2.two_norm());
139 if (alpha<1E-6 || alpha>1-1E-6)
140 DUNE_THROW(Dune::IOError,
"alpha in quadratic boundary segment bad");
144 beta=d1.two_norm()/(d1.two_norm()+d2.two_norm());
145 if (beta<1E-6 || beta>1-1E-6)
146 DUNE_THROW(Dune::IOError,
"beta in quadratic boundary segment bad");
150 gamma=sqrt2*(d1.two_norm()/(d1.two_norm()+d2.two_norm()));
151 if (gamma<1E-6 || gamma>1-1E-6)
152 DUNE_THROW(Dune::IOError,
"gamma in quadratic boundary segment bad");
155 virtual Dune::FieldVector<double,3> operator() (
const Dune::FieldVector<double,2>& local)
const
157 Dune::FieldVector<double,3> y;
159 y.axpy(phi0(local),p0);
160 y.axpy(phi1(local),p1);
161 y.axpy(phi2(local),p2);
162 y.axpy(phi3(local),p3);
163 y.axpy(phi4(local),p4);
164 y.axpy(phi5(local),p5);
172 double phi0 (
const Dune::FieldVector<double,2>& local)
const
174 return (alpha*beta-beta*local[0]-alpha*local[1])*(1-local[0]-local[1])/(alpha*beta);
176 double phi3 (
const Dune::FieldVector<double,2>& local)
const
178 return local[0]*(1-local[0]-local[1])/(alpha*(1-alpha));
180 double phi1 (
const Dune::FieldVector<double,2>& local)
const
182 return local[0]*(gamma*local[0]-(sqrt2-gamma-sqrt2*alpha)*local[1]-alpha*gamma)/(gamma*(1-alpha));
184 double phi5 (
const Dune::FieldVector<double,2>& local)
const
186 return local[1]*(1-local[0]-local[1])/(beta*(1-beta));
188 double phi4 (
const Dune::FieldVector<double,2>& local)
const
190 return local[0]*local[1]/((1-gamma/sqrt2)*gamma/sqrt2);
192 double phi2 (
const Dune::FieldVector<double,2>& local)
const
194 return local[1]*(beta*(1-gamma/sqrt2)-local[0]*(beta-gamma/sqrt2)-local[1]*(1-gamma/sqrt2))/((1-gamma/sqrt2)*(beta-1));
197 Dune::FieldVector<double,3> p0,p1,p2,p3,p4,p5;
198 double alpha,beta,gamma,sqrt2;
204 template<
typename Gr
idType>
223 static const int dim = GridType::dimension;
224 static const int dimWorld = GridType::dimensionworld;
234 void readfile(FILE * file,
int cnt,
const char * format,
235 void* t1,
void* t2 = 0,
void* t3 = 0,
void* t4 = 0,
236 void* t5 = 0,
void* t6 = 0,
void* t7 = 0,
void* t8 = 0,
237 void* t9 = 0,
void* t10 = 0)
239 off_t pos = ftello(file);
240 int c = fscanf(file, format, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
242 DUNE_THROW(Dune::IOError,
"Error parsing " <<
fileName <<
" "
244 <<
": Expected '" << format <<
"', only read " << c <<
" entries instead of " << cnt <<
".");
252 c = std::fgetc(file);
253 }
while(c !=
'\n' && c != EOF);
271 void read (
const std::string& f)
273 if (
verbose) std::cout <<
"Reading " <<
dim <<
"d Gmsh grid..." << std::endl;
277 FILE* file = fopen(
fileName.c_str(),
"r");
279 DUNE_THROW(Dune::IOError,
"Could not open " <<
fileName);
291 double version_number;
292 int file_type, data_size;
295 if (strcmp(
buf,
"$MeshFormat")!=0)
296 DUNE_THROW(Dune::IOError,
"expected $MeshFormat in first line");
297 readfile(file,3,
"%lg %d %d\n",&version_number,&file_type,&data_size);
298 if( (version_number < 2.0) || (version_number > 2.2) )
299 DUNE_THROW(Dune::IOError,
"can only read Gmsh version 2 files");
300 if (
verbose) std::cout <<
"version " << version_number <<
" Gmsh file detected" << std::endl;
302 if (strcmp(
buf,
"$EndMeshFormat")!=0)
303 DUNE_THROW(Dune::IOError,
"expected $EndMeshFormat");
309 if (strcmp(
buf,
"$Nodes")!=0)
310 DUNE_THROW(Dune::IOError,
"expected $Nodes");
311 readfile(file,1,
"%d\n",&number_of_nodes);
312 if (
verbose) std::cout <<
"file contains " << number_of_nodes <<
" nodes" << std::endl;
315 std::vector< GlobalVector > nodes( number_of_nodes+1 );
319 for(
int i = 1; i <= number_of_nodes; ++i )
321 readfile(file,4,
"%d %lg %lg %lg\n", &
id, &x[ 0 ], &x[ 1 ], &x[ 2 ] );
323 DUNE_THROW( Dune::IOError,
"Expected id " << i <<
"(got id " <<
id <<
"." );
327 nodes[ i ][ j ] = x[ j ];
330 if (strcmp(
buf,
"$EndNodes")!=0)
331 DUNE_THROW(Dune::IOError,
"expected $EndNodes");
336 if (strcmp(
buf,
"$Elements")!=0)
337 DUNE_THROW(Dune::IOError,
"expected $Elements");
338 int number_of_elements;
339 readfile(file,1,
"%d\n",&number_of_elements);
340 if (
verbose) std::cout <<
"file contains " << number_of_elements <<
" elements" << std::endl;
346 long section_element_offset = ftell(file);
347 std::map<int,unsigned int>
renumber;
348 for (
int i=1; i<=number_of_elements; i++)
350 int id, elm_type, number_of_tags;
351 readfile(file,3,
"%d %d %d ",&
id,&elm_type,&number_of_tags);
352 for (
int k=1; k<=number_of_tags; k++)
370 if (strcmp(
buf,
"$EndElements")!=0)
371 DUNE_THROW(Dune::IOError,
"expected $EndElements");
379 fseek(file, section_element_offset, SEEK_SET);
382 for (
int i=1; i<=number_of_elements; i++)
384 int id, elm_type, number_of_tags;
385 readfile(file,3,
"%d %d %d ",&
id,&elm_type,&number_of_tags);
386 int physical_entity = -1;
387 std::vector<int> mesh_partitions;
388 if ( version_number < 2.2 )
390 mesh_partitions.resize(1);
392 for (
int k=1; k<=number_of_tags; k++)
396 if (k==1) physical_entity = blub;
398 if ( version_number < 2.2 )
400 if (k==3) mesh_partitions[0] = blub;
405 mesh_partitions[k-4] = blub;
407 mesh_partitions.resize(blub);
413 if (strcmp(
buf,
"$EndElements")!=0)
414 DUNE_THROW(Dune::IOError,
"expected $EndElements");
421 std::map<int,unsigned int> &
renumber,
422 const std::vector< GlobalVector > & nodes)
425 const int nDofs[12] = {-1, 2, 3, 4, 4, 8, 6, 5, 3, 6, -1, 10};
426 const int nVertices[12] = {-1, 2, 3, 4, 4, 8, 6, 5, 2, 3, -1, 4};
427 const int elementDim[12] = {-1, 1, 2, 2, 3, 3, 3, 3, 1, 2, -1, 3};
430 if ( not (elm_type >= 0 && elm_type < 12
431 && (elementDim[elm_type] ==
dim || elementDim[elm_type] == (
dim-1) ) ) )
438 std::string formatString =
"%d";
439 for (
int i=1; i<nDofs[elm_type]; i++)
440 formatString +=
" %d";
441 formatString +=
"\n";
444 std::vector<int> elementDofs(10);
446 readfile(file,nDofs[elm_type], formatString.c_str(),
447 &(elementDofs[0]),&(elementDofs[1]),&(elementDofs[2]),
448 &(elementDofs[3]),&(elementDofs[4]),&(elementDofs[5]),
449 &(elementDofs[6]),&(elementDofs[7]),&(elementDofs[8]),
453 for (
int i=0; i<nVertices[elm_type]; i++)
454 if (renumber.find(elementDofs[i])==renumber.end())
457 factory.insertVertex(nodes[elementDofs[i]]);
461 if (elementDim[elm_type] ==
dim)
471 template <
class E,
class V,
class V2>
474 const E& elementDofs,
478 DUNE_THROW(Dune::IOError,
"tried to create a 3D boundary segment in a non-3D Grid");
482 template <
class E,
class V>
484 const std::vector<FieldVector<double, 3> >& nodes,
485 const E& elementDofs,
489 array<FieldVector<double,dimWorld>, 6> v;
490 for (
int i=0; i<6; i++)
492 v[i][j] = nodes[elementDofs[i]][j];
498 factory.insertBoundarySegment( vertices,
507 std::map<int,unsigned int> &
renumber,
508 const std::vector< GlobalVector > & nodes,
509 const int physical_entity)
512 const int nDofs[12] = {-1, 2, 3, 4, 4, 8, 6, 5, 3, 6, -1, 10};
513 const int nVertices[12] = {-1, 2, 3, 4, 4, 8, 6, 5, 2, 3, -1, 4};
514 const int elementDim[12] = {-1, 1, 2, 2, 3, 3, 3, 3, 1, 2, -1, 3};
517 if ( not (elm_type >= 0 && elm_type < 12
518 && (elementDim[elm_type] ==
dim || elementDim[elm_type] == (
dim-1) ) ) )
525 std::string formatString =
"%d";
526 for (
int i=1; i<nDofs[elm_type]; i++)
527 formatString +=
" %d";
528 formatString +=
"\n";
531 std::vector<int> elementDofs(10);
533 readfile(file,nDofs[elm_type], formatString.c_str(),
534 &(elementDofs[0]),&(elementDofs[1]),&(elementDofs[2]),
535 &(elementDofs[3]),&(elementDofs[4]),&(elementDofs[5]),
536 &(elementDofs[6]),&(elementDofs[7]),&(elementDofs[8]),
543 std::swap(elementDofs[2],elementDofs[3]);
546 std::swap(elementDofs[2],elementDofs[3]);
547 std::swap(elementDofs[6],elementDofs[7]);
550 std::swap(elementDofs[2],elementDofs[3]);
556 std::vector<unsigned int> vertices(nVertices[elm_type]);
558 for (
int i=0; i<nVertices[elm_type]; i++)
559 vertices[i] = renumber[elementDofs[i]];
562 if (elementDim[elm_type] ==
dim) {
602 factory.insertBoundarySegment(vertices);
606 factory.insertBoundarySegment(vertices);
610 array<FieldVector<double,dimWorld>, 3> v;
612 v[0][i] = nodes[elementDofs[0]][i];
613 v[1][i] = nodes[elementDofs[2]][i];
614 v[2][i] = nodes[elementDofs[1]][i];
618 factory.insertBoundarySegment(vertices,
633 if (elementDim[elm_type] ==
dim) {
661 template<
typename Gr
idType>
668 static Grid*
read (
const std::string& fileName,
bool verbose =
true,
bool insert_boundary_segments=
true)
675 parser.
read(fileName);
682 std::vector<int>& boundary_id_to_physical_entity,
683 std::vector<int>& element_index_to_physical_entity,
684 bool verbose =
true,
bool insert_boundary_segments=
true)
691 parser.
read(fileName);
701 bool verbose =
true,
bool insert_boundary_segments=
true)
705 parser.
read(fileName);
710 const std::string& fileName,
711 std::vector<int>& boundary_id_to_physical_entity,
712 std::vector<int>& element_index_to_physical_entity,
713 bool verbose =
true,
bool insert_boundary_segments=
true)
717 parser.
read(fileName);