[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
gmsh_reader.cpp
1 #include <fstream>
2 #include <map>
3 
4 #include <deal.II/base/exceptions.h>
5 #include <deal.II/base/utilities.h>
6 
7 #include <deal.II/grid/grid_in.h> // Mostly just for their exceptions
8 #include <deal.II/grid/tria.h>
9 
10 #include <deal.II/grid/grid_reordering.h>
11 #include <deal.II/grid/grid_tools.h>
12 
13 #include <deal.II/grid/grid_out.h>
14 
15 #include <deal.II/fe/fe_tools.h>
16 
17 #include <deal.II/dofs/dof_renumbering.h>
18 
19 #include "high_order_grid.h"
20 #include "gmsh_reader.hpp"
21 
22 
23 namespace PHiLiP {
24 
33 template <int spacedim>
34 void
35 assign_1d_boundary_ids( const std::map<unsigned int, dealii::types::boundary_id> &boundary_ids,
36  dealii::Triangulation<1, spacedim> &triangulation)
37 {
38  if (boundary_ids.size() > 0) {
39  for (const auto &cell : triangulation.active_cell_iterators()) {
40  for (unsigned int f : dealii::GeometryInfo<1>::face_indices()) {
41  if (boundary_ids.find(cell->vertex_index(f)) != boundary_ids.end()) {
42 
43  AssertThrow( cell->at_boundary(f),
44  dealii::ExcMessage(
45  "You are trying to prescribe boundary ids on the face "
46  "of a 1d cell (i.e., on a vertex), but this face is not actually at "
47  "the boundary of the mesh. This is not allowed."));
48 
49  cell->face(f)->set_boundary_id(boundary_ids.find(cell->vertex_index(f))->second);
50  }
51  }
52  }
53  }
54 }
55 
56 template <int dim>
57 void rotate_indices(std::vector<unsigned int> &numbers, const unsigned int n_indices_per_direction, const char direction, const bool mesh_reader_verbose_output)
58 {
59 
60  const int mpi_rank = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
61  dealii::ConditionalOStream pcout(std::cout, mpi_rank==0);
62 
63  const unsigned int n = n_indices_per_direction;
64  unsigned int s = n;
65  for (unsigned int i = 1; i < dim; ++i)
66  s *= n;
67  numbers.resize(s);
68 
69  unsigned int l = 0;
70 
71  if (dim == 1)
72  {
73  // Mirror around midpoint
74  for (unsigned int i = n; i > 0;)
75  numbers[l++] = --i;
76  }
77  else if (dim == 2)
78  {
79  switch (direction)
80  {
81  // Rotate xy-plane
82  // counter-clockwise
83  // 3 6 2 2 5 1
84  // 7 8 5 becomes 6 8 4
85  // 0 4 1 3 7 0
86  case 'z':
87  for (unsigned int iz = 0; iz < ((dim > 2) ? n : 1); ++iz)
88  for (unsigned int j = 0; j < n; ++j)
89  for (unsigned int i = 0; i < n; ++i)
90  {
91  unsigned int k = n * i - j + n - 1 + n * n * iz;
92  numbers[l++] = k;
93  }
94  break;
95  // Rotate xy-plane
96  // clockwise
97  // 3 6 2 0 7 3
98  // 7 8 5 becomes 4 8 6
99  // 0 4 1 1 5 2
100  case 'Z':
101  for (unsigned int iz = 0; iz < ((dim > 2) ? n : 1); ++iz)
102  for (unsigned int iy = 0; iy < n; ++iy)
103  for (unsigned int ix = 0; ix < n; ++ix)
104  {
105  unsigned int k = n * ix - iy + n - 1 + n * n * iz;
106  numbers[k] = l++;
107  }
108  break;
109  // Change Z normal
110  // Instead of
111  // 3 6 2 1 5 2
112  // 7 8 5 becomes 4 8 6
113  // 0 4 1 0 7 3
114  case '3':
115  for (unsigned int iz = 0; iz < ((dim > 2) ? n : 1); ++iz)
116  for (unsigned int iy = 0; iy < n; ++iy)
117  for (unsigned int ix = 0; ix < n; ++ix)
118  {
119  unsigned int k = iy + n * ix + n * n * iz; // transpose x and y indices
120  numbers[k] = l++;
121  }
122  break;
123  // Rotate yz-plane
124  // counter-clockwise
125  case 'x':
126  Assert(dim > 2, dealii::ExcDimensionMismatch(dim, 3));
127  for (unsigned int iz = 0; iz < n; ++iz)
128  for (unsigned int iy = 0; iy < n; ++iy)
129  for (unsigned int ix = 0; ix < n; ++ix)
130  {
131  unsigned int k = n * (n * iy - iz + n - 1) + ix;
132  numbers[l++] = k;
133  }
134  break;
135  // Rotate yz-plane
136  // clockwise
137  case 'X':
138  Assert(dim > 2, dealii::ExcDimensionMismatch(dim, 3));
139  for (unsigned int iz = 0; iz < n; ++iz)
140  for (unsigned int iy = 0; iy < n; ++iy)
141  for (unsigned int ix = 0; ix < n; ++ix)
142  {
143  unsigned int k = n * (n * iy - iz + n - 1) + ix;
144  numbers[k] = l++;
145  }
146  break;
147  default:
148  Assert(false, dealii::ExcNotImplemented());
149  }
150  } else {
151 
152  //3D ROTATION
228  switch (direction)
229  {
230  // Rotate Cube in Z-Axis
231  case 'Z':
232  for (unsigned int iz = 0; iz < n; ++iz)
233  for (unsigned int iy = 0; iy < n; ++iy)
234  for (unsigned int ix = 0; ix < n; ++ix)
235  {
236  unsigned int k = (ix) * n + n - (iy + 1) + (n * n * iz);
237  numbers[k] = l++;
238  if(mesh_reader_verbose_output) pcout << "3D rotation matrix, physical node mapping, Z-axis : " << k << std::endl;
239  }
240  break;
241  // Rotate Cube in X-Axis
242  case 'X':
243  for (unsigned int iz = 0; iz < n; ++iz)
244  for (unsigned int iy = 0; iy < n; ++iy)
245  for (unsigned int ix = 0; ix < n; ++ix)
246  {
247  unsigned int k = (ix) + (n * (n-1)) + (n * n * iy) - (n * iz);
248  numbers[k] = l++;
249  if(mesh_reader_verbose_output) pcout << "3D rotation matrix, physical node mapping, X-axis : " << k << std::endl;
250  }
251  break;
252  // Rotate Cube in Y-Axis
253  case 'Y':
254  for (unsigned int iz = 0; iz < n; ++iz)
255  for (unsigned int iy = 0; iy < n; ++iy)
256  for (unsigned int ix = 0; ix < n; ++ix)
257  {
258  unsigned int k = (ix * n * n) + (n - 1) + (iy * n) - (iz);
259  numbers[k] = l++;
260  if(mesh_reader_verbose_output) pcout << "3D rotation matrix, physical node mapping, Y-axis : " << k << std::endl;
261  }
262  break;
263  // Flip Cube
264  case 'F':
265  for (unsigned int iz = 0; iz < n; ++iz)
266  for (unsigned int iy = 0; iy < n; ++iy)
267  for (unsigned int ix = 0; ix < n; ++ix)
268  {
269  unsigned int k = (n * (n - 1)) + ix - (iy * n) + (n * n * iz);
270  numbers[k] = l++;
271  if(mesh_reader_verbose_output) pcout << "3D rotation matrix, physical node mapping, Flip-axis : " << k << std::endl;
272  }
273  break;
274  }
275  }
276 }
277 
278 template <int dim, int spacedim>
279 void
280 assign_1d_boundary_ids(const std::map<unsigned int, dealii::types::boundary_id> &,
281  dealii::Triangulation<dim, spacedim> &)
282 {
283  // we shouldn't get here since boundary ids are not assigned to
284  // vertices except in 1d
285  Assert(dim != 1, dealii::ExcInternalError());
286 }
287 
288 
289 void open_file_toRead(const std::string filepath, std::ifstream& file_in)
290 {
291  file_in.open(filepath);
292  if(!file_in) {
293  std::cout << "Could not open file "<< filepath << std::endl;
294  std::abort();
295  }
296 }
297 
298 
299 void read_gmsh_entities(std::ifstream &infile, std::array<std::map<int, int>, 4> &tag_maps)
300 {
301  std::string line;
302  // if the next block is of kind $Entities, parse it
303  unsigned long n_points, n_curves, n_surfaces, n_volumes;
304 
305  infile >> n_points >> n_curves >> n_surfaces >> n_volumes;
306  int entity_tag;
307  unsigned int n_physicals;
308  double box_min_x, box_min_y, box_min_z, box_max_x, box_max_y, box_max_z;
309  (void) box_min_x; (void) box_min_y; (void) box_min_z;
310  (void) box_max_x; (void) box_max_y; (void) box_max_z;
311  for (unsigned int i = 0; i < n_points; ++i) {
312  // parse point ids
313 
314  // we only care for 'tag' as key for tag_maps[0]
315  infile >> entity_tag >> box_min_x >> box_min_y >> box_min_z >> n_physicals;
316 
317  // if there is a physical tag, we will use it as boundary id below
318  AssertThrow(n_physicals < 2, dealii::ExcMessage("More than one tag is not supported!"));
319  // if there is no physical tag, use 0 as default
320  int physical_tag = 0;
321  for (unsigned int j = 0; j < n_physicals; ++j) {
322  infile >> physical_tag;
323  }
324 
325  tag_maps[0][entity_tag] = physical_tag;
326  }
327  for (unsigned int i = 0; i < n_curves; ++i) {
328  // parse curve ids
329 
330  // we only care for 'tag' as key for tag_maps[1]
331  infile >> entity_tag >> box_min_x >> box_min_y >> box_min_z >> box_max_x >> box_max_y >> box_max_z >> n_physicals;
332  // if there is a physical tag, we will use it as boundary id below
333  AssertThrow(n_physicals < 2, dealii::ExcMessage("More than one tag is not supported!"));
334  // if there is no physical tag, use 0 as default
335  int physical_tag = 0;
336  for (unsigned int j = 0; j < n_physicals; ++j) {
337  infile >> physical_tag;
338  }
339  tag_maps[1][entity_tag] = physical_tag;
340 
341  // we don't care about the points associated to a curve, but have
342  // to parse them anyway because their format is unstructured
343  infile >> n_points;
344  for (unsigned int j = 0; j < n_points; ++j) {
345  infile >> entity_tag;
346  }
347  }
348  for (unsigned int i = 0; i < n_surfaces; ++i) {
349  // parse surface ids
350 
351  // we only care for 'tag' as key for tag_maps[2]
352  infile >> entity_tag >> box_min_x >> box_min_y >> box_min_z >> box_max_x >> box_max_y >> box_max_z >> n_physicals;
353  // if there is a physical tag, we will use it as boundary id below
354  AssertThrow(n_physicals < 2, dealii::ExcMessage("More than one tag is not supported!"));
355  // if there is no physical tag, use 0 as default
356  int physical_tag = 0;
357  for (unsigned int j = 0; j < n_physicals; ++j) {
358  infile >> physical_tag;
359  }
360 
361  tag_maps[2][entity_tag] = physical_tag;
362  // we don't care about the curves associated to a surface, but
363  // have to parse them anyway because their format is unstructured
364  infile >> n_curves;
365  for (unsigned int j = 0; j < n_curves; ++j) {
366  infile >> entity_tag;
367  }
368  }
369  for (unsigned int i = 0; i < n_volumes; ++i) {
370  // parse volume ids
371 
372  // we only care for 'tag' as key for tag_maps[3]
373  infile >> entity_tag >> box_min_x >> box_min_y >> box_min_z >> box_max_x >> box_max_y >> box_max_z >> n_physicals;
374  // if there is a physical tag, we will use it as boundary id below
375  AssertThrow(n_physicals < 2,
376  dealii::ExcMessage("More than one tag is not supported!"));
377  // if there is no physical tag, use 0 as default
378  int physical_tag = 0;
379  for (unsigned int j = 0; j < n_physicals; ++j) {
380  infile >> physical_tag;
381  }
382 
383  tag_maps[3][entity_tag] = physical_tag;
384  // we don't care about the surfaces associated to a volume, but
385  // have to parse them anyway because their format is unstructured
386  infile >> n_surfaces;
387  for (unsigned int j = 0; j < n_surfaces; ++j) {
388  infile >> entity_tag;
389  }
390  }
391  infile >> line;
392  //AssertThrow(line == "$EndEntities", PHiLiP::ExcInvalidGMSHInput(line));
393 }
394 
395 template<int spacedim>
396 void read_gmsh_nodes( std::ifstream &infile, std::vector<dealii::Point<spacedim>> &vertices, std::map<int, int> &vertex_indices, const bool mesh_reader_verbose_output )
397 {
398 
399  const int mpi_rank = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
400  dealii::ConditionalOStream pcout(std::cout, mpi_rank==0);
401 
402  std::string line;
403  // now read the nodes list
404  unsigned int n_entity_blocks, n_vertices;
405  int min_node_tag;
406  int max_node_tag;
407  infile >> n_entity_blocks >> n_vertices >> min_node_tag >> max_node_tag;
408  if(mesh_reader_verbose_output) pcout << "Reading nodes..." << std::endl;
409 
410  vertices.resize(n_vertices);
411 
412  unsigned int global_vertex = 0;
413  for (unsigned int entity_block = 0; entity_block < n_entity_blocks; ++entity_block) {
414  int parametric;
415  unsigned long numNodes;
416 
417  // for gmsh_file_format 4.1 the order of tag and dim is reversed,
418  // but we are ignoring both anyway.
419  int tagEntity, dimEntity;
420  infile >> tagEntity >> dimEntity >> parametric >> numNodes;
421 
422  std::vector<int> vertex_numbers;
423 
424  for (unsigned long vertex_per_entity = 0; vertex_per_entity < numNodes; ++vertex_per_entity) {
425  int vertex_number;
426  infile >> vertex_number;
427  vertex_numbers.push_back(vertex_number);
428  }
429 
430  for (unsigned long vertex_per_entity = 0; vertex_per_entity < numNodes; ++vertex_per_entity, ++global_vertex) {
431  // read vertex
432  double x[3];
433  infile >> x[0] >> x[1] >> x[2];
434 
435  for (unsigned int d = 0; d < spacedim; ++d) {
436  vertices[global_vertex](d) = x[d];
437  }
438 
439  int vertex_number;
440  vertex_number = vertex_numbers[vertex_per_entity];
441  // store mapping
442  vertex_indices[vertex_number] = global_vertex;
443 
444 
445  // ignore parametric coordinates
446  if (parametric != 0) {
447  int n_parametric = dimEntity;
448  if (dimEntity == 0) n_parametric = 1;
449  double uvw[3];
450  for (int d=0; d<n_parametric; ++d) {
451  infile >> uvw[d];
452  }
453  (void)uvw;
454  }
455  }
456  }
457  AssertDimension(global_vertex, n_vertices);
458  if(mesh_reader_verbose_output) pcout << "Finished reading nodes." << std::endl;
459 }
460 
461 unsigned int gmsh_cell_type_to_order(unsigned int cell_type)
462 {
463  unsigned int cell_order = 0;
464  if ( (cell_type == MSH_LIN_2) || (cell_type == MSH_QUA_4) || (cell_type == MSH_HEX_8) ) {
465  cell_order = 1;
466  } else if ( (cell_type == MSH_LIN_3) || (cell_type == MSH_QUA_9) || (cell_type == MSH_HEX_27) ) {
467  cell_order = 2;
468  } else if ( (cell_type == MSH_LIN_4) || (cell_type == MSH_QUA_16) || (cell_type == MSH_HEX_64) ) {
469  cell_order = 3;
470  } else if ( (cell_type == MSH_LIN_5) || (cell_type == MSH_QUA_25) || (cell_type == MSH_HEX_125) ) {
471  cell_order = 4;
472  } else if ( (cell_type == MSH_LIN_6) || (cell_type == MSH_QUA_36) || (cell_type == MSH_HEX_216) ) {
473  cell_order = 5;
474  } else if ( (cell_type == MSH_LIN_7) || (cell_type == MSH_QUA_49) || (cell_type == MSH_HEX_343) ) {
475  cell_order = 6;
476  } else if ( (cell_type == MSH_LIN_8) || (cell_type == MSH_QUA_64) || (cell_type == MSH_HEX_512) ) {
477  cell_order = 7;
478  } else if ( (cell_type == MSH_LIN_9) || (cell_type == MSH_QUA_81) || (cell_type == MSH_HEX_729) ) {
479  cell_order = 8;
480  } else if ( (cell_type == MSH_PNT) ) {
481  cell_order = 0;
482  } else {
483  std::cout << "Invalid element type read from GMSH " << cell_type << ". "
484  << "\n Valid element types are:"
485  << "\n " << MSH_PNT
486  << "\n " << MSH_LIN_2 << " " << MSH_LIN_3 << " " << MSH_LIN_4 << " " << MSH_LIN_5 << " " << MSH_LIN_6 << " " << MSH_LIN_7 << " " << MSH_LIN_8 << " " << MSH_LIN_9
487  << "\n " << MSH_QUA_4 << " " << MSH_QUA_9 << " " << MSH_QUA_16 << " " << MSH_QUA_25 << " " << MSH_QUA_36 << " " << MSH_QUA_49 << " " << MSH_QUA_64 << " " << MSH_QUA_81
488  << "\n " << MSH_HEX_8 << " " << MSH_HEX_27 << " " << MSH_HEX_64 << " " << MSH_HEX_125 << " " << MSH_HEX_216 << " " << MSH_HEX_343 << " " << MSH_HEX_512 << " " << MSH_HEX_729
489  << std::endl;
490  std::abort();
491  }
492 
493  return cell_order;
494 }
495 
501 template<int dim>
502 unsigned int find_grid_order(std::ifstream &infile,const bool mesh_reader_verbose_output)
503 {
504 
505  const int mpi_rank = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
506  dealii::ConditionalOStream pcout(std::cout, mpi_rank==0);
507 
508  auto entity_file_position = infile.tellg();
509 
510  unsigned int grid_order = 0;
511 
512  unsigned int n_entity_blocks, n_cells;
513  int min_ele_tag, max_ele_tag;
514  infile >> n_entity_blocks >> n_cells >> min_ele_tag >> max_ele_tag;
515 
516  if(mesh_reader_verbose_output) pcout << "Finding grid order..." << std::endl;
517  if(mesh_reader_verbose_output) pcout << n_entity_blocks << " entity blocks with a total of " << n_cells << " cells. " << std::endl;
518 
519  std::vector<unsigned int> vertices_id;
520 
521  unsigned int global_cell = 0;
522  for (unsigned int entity_block = 0; entity_block < n_entity_blocks; ++entity_block) {
523  unsigned long numElements;
524  int cell_type;
525 
526  int tagEntity, dimEntity;
527  infile >> dimEntity >> tagEntity >> cell_type >> numElements;
528 
529  const unsigned int cell_order = gmsh_cell_type_to_order(cell_type);
530  const unsigned int nodes_per_element = std::pow(cell_order + 1, dimEntity);
531 
532  grid_order = std::max(cell_order, grid_order);
533 
534  vertices_id.resize(nodes_per_element);
535 
536  for (unsigned int cell_per_entity = 0; cell_per_entity < numElements; ++cell_per_entity, ++global_cell) {
537  // note that since infile the input file we found the number of p1_cells at the top, there
538  // should still be input here, so check this:
539  AssertThrow(infile, dealii::ExcIO());
540 
541  int tag;
542  infile >> tag;
543 
544  for (unsigned int i = 0; i < nodes_per_element; ++i) {
545  infile >> vertices_id[i];
546  }
547  } // End of cell per entity
548  } // End of entity block
549 
550  infile.seekg(entity_file_position);
551 
552  AssertDimension(global_cell, n_cells);
553  if(mesh_reader_verbose_output) pcout << "Found grid order = " << grid_order << std::endl;
554  return grid_order;
555 }
556 
557 unsigned int ijk_to_num(const unsigned int i,
558  const unsigned int j,
559  const unsigned int k,
560  const unsigned int n_per_line)
561 {
562  return i + j*n_per_line + k*n_per_line*n_per_line;
563 }
564 unsigned int ij_to_num(const unsigned int i,
565  const unsigned int j,
566  const unsigned int n_per_line)
567 {
568  return i + j*n_per_line;
569 }
570 
581 std::vector<unsigned int>
582 face_node_finder(const unsigned int degree, const bool mesh_reader_verbose_output)
583 {
584 
588  const int mpi_rank = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
589  dealii::ConditionalOStream pcout(std::cout, mpi_rank==0);
590 
591  // number of support points in each direction
592  const unsigned int n = degree + 1;
593 
594  const unsigned int dofs_per_face = dealii::Utilities::fixed_power<2>(n);
595 
596  std::vector<unsigned int> h2l_2D(dofs_per_face);
597  if (degree == 0) {
598  h2l_2D[0] = 0;
599  return h2l_2D;
600  }
601 
602  if(mesh_reader_verbose_output) pcout << "DOF_PER_FACE = " << dofs_per_face << std::endl;
603 
604  unsigned int next_index = 0;
605  int subdegree = degree;
606  int square_reduction = 0;
607  while (subdegree > 0) {
608 
609  const unsigned int start = 0 + square_reduction;
610  const unsigned int end = n - square_reduction;
611 
612  // First the four vertices
613  {
614  unsigned int i, j;
615  // Bottom left
616  i = start; j = start;
617  h2l_2D[next_index++] = ij_to_num(i,j,n);
618  // Bottom right
619  i = end-1; j = start;
620  h2l_2D[next_index++] = ij_to_num(i,j,n);
621  // Top right
622  i = end-1; j = end-1;
623  h2l_2D[next_index++] = ij_to_num(i,j,n);
624  // Top left
625  i = start; j = end-1;
626  h2l_2D[next_index++] = ij_to_num(i,j,n);
627  }
628 
629  // Bottom line
630  {
631  unsigned int j = start;
632  for (unsigned int i = start+1; i < end-1; ++i)
633  h2l_2D[next_index++] = ij_to_num(i,j,n);
634  }
635  // Right line
636  {
637  unsigned int i = end-1;
638  for (unsigned int j = start+1; j < end-1; ++j)
639  h2l_2D[next_index++] = ij_to_num(i,j,n);
640  }
641  // Top line (right to left)
642  {
643  unsigned int j = end-1;
644  //for (unsigned int i = start+1; i < end-1; ++i)
645  // Need signed int otherwise, j=0 followed by --j results in j=UINT_MAX
646  for (int i = end-2; i > (int)start; --i)
647  h2l_2D[next_index++] = ij_to_num(i,j,n);
648  }
649  // Left line (top to bottom order)
650  {
651  unsigned int i = start;
652  //for (unsigned int j = start+1; j < end-1; ++j)
653  // Need signed int otherwise, j=0 followed by --j results in j=UINT_MAX
654  for (int j = end-2; j > (int)start; --j)
655  h2l_2D[next_index++] = ij_to_num(i,j,n);
656  }
657 
658  subdegree -= 2;
659  square_reduction += 1;
660 
661  }
662 
663  if (subdegree == 0) {
664  const unsigned int middle = (n-1)/2;
665  h2l_2D[next_index++] = ij_to_num(middle, middle, n);
666  }
667 
668  Assert(next_index == dofs_per_face, dealii::ExcInternalError());
669 
670  return h2l_2D;
671 }
672 
673 template <int dim>
674 std::vector<unsigned int>
675 gmsh_hierarchic_to_lexicographic(const unsigned int degree, const bool mesh_reader_verbose_output)
676 {
677 
681  const int mpi_rank = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
682  dealii::ConditionalOStream pcout(std::cout, mpi_rank==0);
683 
684  // number of support points in each direction
685  const unsigned int n = degree + 1;
686 
687  const unsigned int dofs_per_cell = dealii::Utilities::fixed_power<dim>(n);
688 
689  std::vector<unsigned int> h2l(dofs_per_cell);
690  if (degree == 0) {
691  h2l[0] = 0;
692  return h2l;
693  }
694 
695  //
696  const unsigned int inner_points_per_line = degree - 1;
697 
698  // The following lines of code are somewhat odd, due to the way the
699  // hierarchic numbering is organized. if someone would really want to
700  // understand these lines, you better draw some pictures where you
701  // indicate the indices and orders of vertices, lines, etc, along with the
702  // numbers of the degrees of freedom in hierarchical and lexicographical
703  // order
704  switch (dim) {
705  case 0: {
706  h2l[0] = 0;
707  break;
708  } case 1: {
709  h2l[0] = 0;
710  h2l[1] = dofs_per_cell - 1;
711  for (unsigned int i = 2; i < dofs_per_cell; ++i)
712  h2l[i] = i - 1;
713  break;
714  } case 2: {
715  unsigned int next_index = 0;
716 
717  int subdegree = degree;
718  int square_reduction = 0;
719  while (subdegree > 0) {
720 
721  const unsigned int start = 0 + square_reduction;
722  const unsigned int end = n - square_reduction;
723 
724  // First the four vertices
725  {
726  unsigned int i, j;
727  // Bottom left
728  i = start; j = start;
729  h2l[next_index++] = ij_to_num(i,j,n);
730  // Bottom right
731  i = end-1; j = start;
732  h2l[next_index++] = ij_to_num(i,j,n);
733  // Top right
734  i = end-1; j = end-1;
735  h2l[next_index++] = ij_to_num(i,j,n);
736  // Top left
737  i = start; j = end-1;
738  h2l[next_index++] = ij_to_num(i,j,n);
739  }
740 
741  // Bottom line
742  {
743  unsigned int j = start;
744  for (unsigned int i = start+1; i < end-1; ++i)
745  h2l[next_index++] = ij_to_num(i,j,n);
746  }
747  // Right line
748  {
749  unsigned int i = end-1;
750  for (unsigned int j = start+1; j < end-1; ++j)
751  h2l[next_index++] = ij_to_num(i,j,n);
752  }
753  // Top line (right to left)
754  {
755  unsigned int j = end-1;
756  //for (unsigned int i = start+1; i < end-1; ++i)
757  // Need signed int otherwise, j=0 followed by --j results in j=UINT_MAX
758  for (int i = end-2; i > (int)start; --i)
759  h2l[next_index++] = ij_to_num(i,j,n);
760  }
761  // Left line (top to bottom order)
762  {
763  unsigned int i = start;
764  //for (unsigned int j = start+1; j < end-1; ++j)
765  // Need signed int otherwise, j=0 followed by --j results in j=UINT_MAX
766  for (int j = end-2; j > (int)start; --j)
767  h2l[next_index++] = ij_to_num(i,j,n);
768  }
769 
770  subdegree -= 2;
771  square_reduction += 1;
772 
773  }
774  if (subdegree == 0) {
775  const unsigned int middle = (n-1)/2;
776  h2l[next_index++] = ij_to_num(middle, middle, n);
777  }
778 
779  Assert(next_index == dofs_per_cell, dealii::ExcInternalError());
780 
781  break;
782  } case 3: {
783 
784  //INDEX START AT 0
785  unsigned int next_index = 0;
786  std::vector<unsigned int> face_position;
787  std::vector<unsigned int> recursive_3D_position;
788  std::vector<unsigned int> recursive_3D_nodes;
789  std::vector<unsigned int> face_nodes;
790 
791  // First the eight corner vertices
792  h2l[next_index++] = 0; // 0
793  h2l[next_index++] = (1) * degree; // 1
794  h2l[next_index++] = (n + 1)*degree; // 2
795  h2l[next_index++] = (n) * degree; // 3
796  h2l[next_index++] = (n * n) * degree; // 4
797  h2l[next_index++] = (n * n + 1) * degree; // 5
798  h2l[next_index++] = (n * n + n + 1) * degree; // 6
799  h2l[next_index++] = (n * n + n) * degree; // 7
800 
801  if (degree > 1) {
802 
803  //PHYSICAL INTERPRETATION OF THE NODES (MAPPING)
804  //Degree is -2 because we are removing both end points
805  face_nodes = face_node_finder(degree-2,mesh_reader_verbose_output);
806 
807  //For debug
808  if(mesh_reader_verbose_output) pcout << "DEGREE " << degree << std::endl;
809  {
810  unsigned int n = degree - 1;
811  if(mesh_reader_verbose_output) pcout << "GMSH H2L " << std::endl;
812  for (int j = n - 1; j >= 0; --j) {
813  for (unsigned int i = 0; i < n; ++i) {
814  const unsigned int ij = ij_to_num(i, j, n);
815  if(mesh_reader_verbose_output) pcout << face_nodes[ij] << " ";
816  }
817  if(mesh_reader_verbose_output) pcout << std::endl;
818  }
819  }
820 
821  if(mesh_reader_verbose_output) pcout << "" << std::endl;
822 
823 
824  // line 0
825  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
826  h2l[next_index++] = i + 1;
827  if(mesh_reader_verbose_output) pcout << "line 0 - " << i + 1 << std::endl;
828  }
829 
830  // line 1
831  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
832  h2l[next_index++] = (i + 1) * n;
833  if(mesh_reader_verbose_output) pcout << "line 1 - " << (i + 1) * n << std::endl;
834  }
835 
836  // line 2
837  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
838  h2l[next_index++] = (i + 1) * n * n;
839  if(mesh_reader_verbose_output) pcout << "line 2 - " << (i + 1) * n * n << std::endl;
840  }
841 
842  // line 3
843  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
844  h2l[next_index++] = (2 + i) * n - 1;
845  if(mesh_reader_verbose_output) pcout << "line 3 - " << (2 + i) * n - 1 << std::endl;
846  }
847 
848  // line 4
849  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
850  h2l[next_index++] = (n * n * (i + 1)) + degree;
851  if(mesh_reader_verbose_output) pcout << "line 4 - " << (n * n * (i + 1)) + degree << std::endl;
852  }
853 
854  // line 5
855  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
856  h2l[next_index++] = n * n - (i + 1) - 1;
857  if(mesh_reader_verbose_output) pcout << "line 5 - " << n * n - (i + 1) - 1 << std::endl;
858  }
859 
860  // line 6
861  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
862  h2l[next_index++] = (degree * n + (n * n * (i+1))) + degree;
863  if(mesh_reader_verbose_output) pcout << "line 6 - " << (degree * n + (n * n * (i+1))) + degree << std::endl;
864  }
865 
866  // line 7
867  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
868  h2l[next_index++] = (degree * n + (n * n * (i+1)));
869  if(mesh_reader_verbose_output) pcout << "line 7 - " << (degree * n + (n * n * (i+1))) << std::endl;
870  }
871 
872  // line 8
873  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
874  h2l[next_index++] = (n * n) * degree + (i + 1);
875  if(mesh_reader_verbose_output) pcout << "line 8 - " << (n * n) * degree + (i + 1) << std::endl;
876  }
877 
878  // line 9
879  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
880  h2l[next_index++] = (i + 1) * n + (n * n) * degree;
881  if(mesh_reader_verbose_output) pcout << "line 9 - " << (i + 1) * n + (n * n) * degree << std::endl;
882  }
883  // line 10
884  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
885  h2l[next_index++] = (2 + i) * n - 1 + (n * n) * degree;
886  if(mesh_reader_verbose_output) pcout << "line 10 - " << (2 + i) * n - 1 + (n * n) * degree << std::endl;
887  }
888  // line 11
889  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
890  h2l[next_index++] = n * n * n - 1 - (i + 1);
891  if(mesh_reader_verbose_output) pcout << "line 11 - " << n * n * n - 1 - (i + 1) << std::endl;
892  }
893 
894  // inside quads
895  // face 0
896  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
897  for (unsigned int j = 0; j < inner_points_per_line; ++j) {
898  if(mesh_reader_verbose_output) pcout << "Face 0 : " << n + 1 + (n * j) + (i) << std::endl;
899  face_position.push_back(n + 1 + (n * j) + (i));
900  }
901  }
902 
903  for (unsigned int i = 0; i < (degree - 1) * (degree - 1); ++i) {
904  h2l[next_index++] = face_position.at(face_nodes[i]);
905  }
906 
907  face_position.clear();
908 
909  // face 1
910  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
911  for (unsigned int j = 0; j < inner_points_per_line; ++j) {
912  if(mesh_reader_verbose_output) pcout << "Face 1 : " << (n * n * (i + 1)) + (j + 1) << std::endl;
913  face_position.push_back((n * n * (i + 1)) + (j + 1));
914  }
915  }
916 
917  for (unsigned int i = 0; i < (degree - 1) * (degree - 1); ++i) {
918  h2l[next_index++] = face_position.at(face_nodes[i]);
919  }
920 
921  face_position.clear();
922 
923  // face 2 -> Orientation is changed
924 
925  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
926  for (unsigned int j = 0; j < inner_points_per_line; ++j) {
927 // face_position.push_back((n * n * (i + 1)) + n + n * j);
928  if(mesh_reader_verbose_output) pcout << "Face 2 : " << (n * n * (j + 1)) + n + i * n << std::endl;
929  face_position.push_back((n * n * (j + 1)) + n + i * n);
930  }
931  }
932 
933  for (unsigned int i = 0; i < (degree - 1) * (degree - 1); ++i) {
934  h2l[next_index++] = face_position.at(face_nodes[i]);
935  }
936 
937  face_position.clear();
938 
939  // face 3
940 
941  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
942  for (unsigned int j = 0; j < inner_points_per_line; ++j) {
943  if(mesh_reader_verbose_output) pcout << "Face 3 : " << n * (j + 2) - 1 + i * (n * n) + n * n << std::endl;
944  face_position.push_back(n * (j + 2) - 1 + i * (n * n) + n * n);
945  }
946  }
947 
948  for (unsigned int i = 0; i < (degree - 1) * (degree - 1); ++i) {
949  h2l[next_index++] = face_position.at(face_nodes[i]);
950  }
951 
952  face_position.clear();
953 
954  // face 4
955 
956  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
957  for (unsigned int j = 0; j < inner_points_per_line; ++j) {
958  if(mesh_reader_verbose_output) pcout << "Face 4 : " << (n * n * i) + (n * n * 2) - (j + 1) - 1 << std::endl;
959  face_position.push_back((n * n * i) + (n * n * 2) - (j + 1) - 1);
960  }
961  }
962 
963  for (unsigned int i = 0; i < (degree - 1) * (degree - 1); ++i) {
964  h2l[next_index++] = face_position.at(face_nodes[i]);
965  }
966 
967  face_position.clear();
968 
969  // face 5
970 
971  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
972  for (unsigned int j = 0; j < inner_points_per_line; ++j) {
973  if(mesh_reader_verbose_output) pcout << "Face 5 : " << (n * n * degree + n + (j + 1)) + i * n << std::endl;
974  face_position.push_back((n * n * degree + n + (j + 1)) + i * n);
975  }
976  }
977 
978  for (unsigned int i = 0; i < (degree - 1) * (degree - 1); ++i) {
979  h2l[next_index++] = face_position.at(face_nodes[i]);
980  }
981 
982  //Build the inner 3D structure with global index position
983  for (unsigned int i = 0; i < inner_points_per_line; ++i) {
984  for (unsigned int j = 0; j < inner_points_per_line; ++j) {
985  for (unsigned int k = 0; k < inner_points_per_line; ++k) {
986 // recursive_3D_position.push_back(n * n * (degree - i) - n - 2 - (n * k) - j);
987  recursive_3D_position.push_back(n * n + ((j+1) * n) + (k + 1) + (n * n * i));
988  }
989  }
990  }
991 
992  if(mesh_reader_verbose_output) pcout << "3D Inner Cube" << std::endl;
993  for (unsigned int aInt: recursive_3D_position) {
994  if(mesh_reader_verbose_output) pcout << aInt << std::endl;
995  }
996 
1001  if (degree == 2) {
1002  h2l[next_index++] = recursive_3D_position.at(0);
1003  } else {
1004 
1011  if(mesh_reader_verbose_output) pcout << "Begin recursive call to inner cube" << std::endl;
1012  recursive_3D_nodes = gmsh_hierarchic_to_lexicographic<dim>(degree - 2, mesh_reader_verbose_output);
1013 
1014  if(mesh_reader_verbose_output) pcout << "Printing recursive_3D_nodes" << std::endl;
1015  for (unsigned int aInt : recursive_3D_nodes) {
1016  if(mesh_reader_verbose_output) pcout << aInt << std::endl;
1017  }
1018 
1019  if(mesh_reader_verbose_output) pcout << "Degree = " << degree << std::endl;
1020  if(mesh_reader_verbose_output) pcout << "Dim = " << dim << std::endl;
1021 
1022  //Apply the recursive_3D_nodes on the recursive_3D_position vector
1023  for (unsigned int i = 0; i < pow((degree - 1),3); ++i) {
1024  h2l[next_index++] = recursive_3D_position.at(recursive_3D_nodes[i]);
1025  }
1026  }
1027  }
1028 
1029 // if(mesh_reader_verbose_output) pcout << "Next_index = " << next_index << std::endl;
1030 // Assert(next_index == dofs_per_cell, dealii::ExcInternalError());
1031 
1032  break;
1033  } default: {
1034  Assert(false, dealii::ExcNotImplemented());
1035  }
1036 
1037  } // End of switch
1038 
1039  return h2l;
1040 }
1041 
1042 unsigned int dealii_node_number(const unsigned int i,
1043  const unsigned int j,
1044  const unsigned int k)
1045 {
1046  return i+j+k;
1047 }
1048 
1049 void fe_q_node_number(const unsigned int index,
1050  unsigned int &i,
1051  unsigned int &j,
1052  unsigned int &k)
1053 {
1054  i = index;
1055  j = index;
1056  k = index;
1057 }
1058 
1062 template <int dim, int spacedim>
1063 bool get_new_rotated_indices(const dealii::CellAccessor<dim, spacedim>& cell,
1064  const std::vector<dealii::Point<spacedim>>& all_vertices,
1065  const std::vector<unsigned int>& deal_h2l,
1066  const std::vector<unsigned int>& rotate_z90degree,
1067  std::vector<unsigned int>& high_order_vertices_id)
1068 {
1069 
1070  const unsigned int n_vertices = cell.n_vertices();
1071  for (int zr = 0; zr < 4; ++zr) {
1072 
1073  std::vector<char> matching(n_vertices);
1074 
1075  for (unsigned int i_vertex=0; i_vertex < n_vertices; ++i_vertex) {
1076 
1077  const unsigned int base_index = i_vertex;
1078  const unsigned int lexicographic_index = deal_h2l[base_index];
1079 
1080  const unsigned int vertex_id = high_order_vertices_id[lexicographic_index];
1081  const dealii::Point<dim,double> high_order_vertex = all_vertices[vertex_id];
1082 
1083  bool found = false;
1084  for (unsigned int i=0; i < n_vertices; ++i) {
1085  if (cell.vertex(i) == high_order_vertex) {
1086  found = true;
1087  }
1088  }
1089  if (!found) {
1090  std::cout << "Wrong cell... High-order nodes do not match the cell's vertices." << std::endl;
1091  std::abort();
1092  }
1093 
1094  matching[i_vertex] = (high_order_vertex == cell.vertex(i_vertex)) ? 'T' : 'F';
1095  }
1096 
1097  bool all_matching = true;
1098  for (unsigned int i=0; i < n_vertices; ++i) {
1099  if (matching[i] == 'F') all_matching = false;
1100  }
1101  if (all_matching) return true;
1102 
1103  const auto high_order_vertices_id_temp = high_order_vertices_id;
1104  for (unsigned int i=0; i<high_order_vertices_id.size(); ++i) {
1105  high_order_vertices_id[i] = high_order_vertices_id_temp[rotate_z90degree[i]];
1106  }
1107  }
1108  return false;
1109 }
1110 
1114 template <int dim, int spacedim>
1115 bool get_new_rotated_indices_3D(const dealii::CellAccessor<dim, spacedim>& cell,
1116  const std::vector<dealii::Point<spacedim>>& all_vertices,
1117  const std::vector<unsigned int>& deal_h2l,
1118  const std::vector<unsigned int>& rotate_x90degree_3D,
1119  const std::vector<unsigned int>& rotate_y90degree_3D,
1120  const std::vector<unsigned int>& rotate_z90degree_3D,
1121  std::vector<unsigned int>& high_order_vertices_id_rotated,
1122  const bool /*mesh_reader_verbose_output*/)
1123 {
1124 
1125  const int mpi_rank = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
1126  dealii::ConditionalOStream pcout(std::cout, mpi_rank==0);
1127 
1128  //These variables are for 3D case
1129  auto high_order_flip_id_rotated = high_order_vertices_id_rotated;
1130  auto high_order_x_id_rotated = high_order_vertices_id_rotated;
1131  auto high_order_y_id_rotated = high_order_vertices_id_rotated;
1132  auto high_order_vertices_id = high_order_vertices_id_rotated;
1133 
1134  const unsigned int n_vertices = cell.n_vertices();
1135 
1136  bool good_rotation;
1137 
1138  for (int xr = 0; xr < 4; ++xr) { //Rotate in X-Axis
1139  for (int zr = 0; zr < 4; ++zr) { //Rotate in Y-Axis
1140  for (int zr3d = 0; zr3d < 4; ++zr3d) { //Rotate in Z-Axis
1141 
1142  std::vector<char> matching(n_vertices);
1143 
1144  //Parse through vertex points
1145  for (unsigned int i_vertex = 0; i_vertex < n_vertices; ++i_vertex) {
1146 
1147  const unsigned int base_index = i_vertex;
1148 
1149  //THESE ARE POSITIONS INDEX, SO GET THE LEXICOGRAHICAL_INDEX OF DEALII AND MAP IT BACK
1150  const unsigned int lexicographic_index = deal_h2l[base_index];
1151 
1152  const unsigned int vertex_id = high_order_vertices_id_rotated[lexicographic_index];
1153 
1154  //ALL_VERTICES IS IN HIERARCHICAL ORDER WITH POINTS (SO VERTEX_ID HITS BANG ON)
1155  const dealii::Point<dim, double> high_order_vertex = all_vertices[vertex_id];
1156 
1157  //.I.E. 0 4 20 24 5 -> POSITION 1 IS 4, SO FIRST NODE IN DEALII ORDERING WOULD BE AT POSITION 4 IN THE LEXICOGRPAHICAL ORDERING GENERATED BY GMSH
1158 
1159  //THIS IS JUST TO SEE IF THE HIGHER ORDER NODES ARE FOUND (TECHNICALLY, WE SHOULD BE ONLY TARGETING 2D NODES, NOT THE 1D)
1160  //-> THIS SHOULD BE FILTERED OUT FROM HIGH_ORDER_VERTEX
1161  bool found = false;
1162  for (unsigned int i = 0; i < n_vertices; ++i) {
1163  if (cell.vertex(i) == high_order_vertex) {
1164  found = true;
1165  }
1166  }
1167 
1168  if (!found) {
1169  std::cout
1170  << "Wrong cell... High order nodes do not match the cell's vertices | "
1171  << "mpi_rank = " << mpi_rank << std::endl;
1172  std::abort();
1173  }
1174 
1175  //CHECK FOR WHETHER THE VERTEX IS AT THE GOOD LOCATION OR NOT
1176  matching[i_vertex] = (high_order_vertex == cell.vertex(i_vertex)) ? 0 : 1;
1177  }
1178 
1183  // if(mesh_reader_verbose_output) pcout << "********** CELL VERTEX **********" << std::endl;
1184 
1185  bool all_matching = true;
1186  for (unsigned int i = 0; i < n_vertices; ++i) {
1187  if (matching[i] == 1) all_matching = false;
1188  }
1189 
1190  //Boolean for good rotation from the previous matching for loop
1191  good_rotation = all_matching;
1192 
1193  //If rotation is good, i.e., matching vertices, then we break.
1194  if (good_rotation) {
1195  break;
1196  }
1197 
1198  //If we did not find a good rotation, we rotate in the Z-axis,
1199  //Swap the high_order_vertices_id_rotated by Z-axis rotation
1200  high_order_vertices_id = high_order_vertices_id_rotated;
1201  for (unsigned int i = 0; i < high_order_vertices_id.size(); ++i) {
1202  high_order_vertices_id_rotated[i] = high_order_vertices_id[rotate_z90degree_3D[i]];
1203  }
1204  }
1205 
1206  //If rotation is good, i.e., matching vertices, then we break.
1207  if (good_rotation) {
1208  break;
1209  }
1210 
1211  //If we did not find a good rotation, we rotate in the Y-axis,
1212  //Swap the high_order_vertices_id_rotated by Y-axis rotation
1213  high_order_y_id_rotated = high_order_vertices_id_rotated;
1214  for (unsigned int i = 0; i < high_order_vertices_id.size(); ++i) {
1215  high_order_vertices_id_rotated[i] = high_order_y_id_rotated[rotate_y90degree_3D[i]];
1216  }
1217  }
1218 
1219  //If rotation is good, i.e., matching vertices, then we break.
1220  if (good_rotation) {
1221  break;
1222  }
1223 
1224  //If we did not find a good rotation, we rotate in the X-axis
1225  //Swap the high_order_vertices_id_rotated by X-axis rotation
1226  high_order_x_id_rotated = high_order_vertices_id_rotated;
1227  for (unsigned int i = 0; i < high_order_vertices_id.size(); ++i) {
1228  high_order_vertices_id_rotated[i] = high_order_x_id_rotated[rotate_x90degree_3D[i]];
1229  }
1230 
1231  }
1232 
1233  if (good_rotation) {
1234  return true;
1235  }
1236 
1237  return false;
1238 }
1239 
1240 
1241 // template <int dim, int spacedim>
1242 // std::shared_ptr< HighOrderGrid<dim, double> >
1243 // read_gmsh(std::string filename, bool periodic_x, bool periodic_y, bool periodic_z, int x_periodic_1, int x_periodic_2, int y_periodic_1, int y_periodic_2, int z_periodic_1, int z_periodic_2, true, int requested_grid_order)
1244 
1245 template <int dim, int spacedim>
1246 std::shared_ptr< HighOrderGrid<dim, double> >
1247 read_gmsh(std::string filename,
1248  const bool periodic_x, const bool periodic_y, const bool periodic_z,
1249  const int x_periodic_1, const int x_periodic_2,
1250  const int y_periodic_1, const int y_periodic_2,
1251  const int z_periodic_1, const int z_periodic_2,
1252  const bool mesh_reader_verbose_output,
1253  const bool do_renumber_dofs,
1254  int requested_grid_order,
1255  const bool use_mesh_smoothing)
1256 {
1257 
1258  const int mpi_rank = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
1259  dealii::ConditionalOStream pcout(std::cout, mpi_rank==0);
1260 
1261 // Assert(dim==2, dealii::ExcInternalError());
1262  std::ifstream infile;
1263 
1264  open_file_toRead(filename, infile);
1265 
1266  std::string line;
1267 
1268  // This array stores maps from the 'entities' to the 'physical tags' for
1269  // points, curves, surfaces and volumes. We use this information later to
1270  // assign boundary ids.
1271  std::array<std::map<int, int>, 4> tag_maps;
1272 
1273 
1274  infile >> line;
1275 
1276  //Assert(tria != nullptr, dealii::ExcNoTriangulationSelected());
1277 
1278  // first determine file format
1279  unsigned int gmsh_file_format = 0;
1280  if (line == "$MeshFormat") {
1281  gmsh_file_format = 20;
1282  } else {
1283  //AssertThrow(false, dealii::ExcInvalidGMSHInput(line));
1284  }
1285 
1286  // if file format is 2.0 or greater then we also have to read the rest of the
1287  // header
1288  if (gmsh_file_format == 20) {
1289  double version;
1290  unsigned int file_type, data_size;
1291 
1292  infile >> version >> file_type >> data_size;
1293 
1294  Assert((version == 4.1), dealii::ExcNotImplemented());
1295  gmsh_file_format = static_cast<unsigned int>(version * 10);
1296 
1297 
1298  Assert(file_type == 0, dealii::ExcNotImplemented());
1299  Assert(data_size == sizeof(double), dealii::ExcNotImplemented());
1300 
1301 
1302  // Read the end of the header and the first line of the nodes description
1303  // to synch ourselves with the format 1 handling above
1304  infile >> line;
1305  //AssertThrow(line == "$EndMeshFormat", PHiLiP::ExcInvalidGMSHInput(line));
1306 
1307  infile >> line;
1308  // if the next block is of kind $PhysicalNames, ignore it
1309  if (line == "$PhysicalNames") {
1310  do {
1311  infile >> line;
1312  } while (line != "$EndPhysicalNames");
1313  infile >> line;
1314  }
1315 
1316 
1317  // if the next block is of kind $Entities, parse it
1318  if (line == "$Entities") read_gmsh_entities(infile, tag_maps);
1319  infile >> line;
1320 
1321  // if the next block is of kind $PartitionedEntities, ignore it
1322  if (line == "$PartitionedEntities") {
1323  do {
1324  infile >> line;
1325  } while (line != "$EndPartitionedEntities");
1326  infile >> line;
1327  }
1328 
1329  // But the next thing should,
1330  // infile any case, be the list of
1331  // nodes:
1332  //AssertThrow(line == "$Nodes", PHiLiP::ExcInvalidGMSHInput(line));
1333  }
1334 
1335  std::vector<dealii::Point<spacedim>> vertices;
1336 
1337  // Set up mapping between numbering
1338  // infile msh-file (node) and infile the
1339  // vertices vector
1340 
1341  std::map<int, int> vertex_indices;
1342  read_gmsh_nodes( infile, vertices, vertex_indices, mesh_reader_verbose_output );
1343 
1344  // Assert we reached the end of the block
1345  infile >> line;
1346  static const std::string end_nodes_marker = "$EndNodes";
1347  //AssertThrow(line == end_nodes_marker, PHiLiP::ExcInvalidGMSHInput(line));
1348 
1349  // Now read infile next bit
1350  infile >> line;
1351  static const std::string begin_elements_marker = "$Elements";
1352  //AssertThrow(line == begin_elements_marker, PHiLiP::ExcInvalidGMSHInput(line));
1353 
1354  const unsigned int grid_order = find_grid_order<dim>(infile,mesh_reader_verbose_output);
1355 
1356  using Triangulation = dealii::parallel::distributed::Triangulation<dim>;
1357  std::shared_ptr<Triangulation> triangulation;
1358 
1359  if(use_mesh_smoothing) {
1360  triangulation = std::make_shared<Triangulation>(
1361  MPI_COMM_WORLD,
1362  typename dealii::Triangulation<dim>::MeshSmoothing(
1363  dealii::Triangulation<dim>::smoothing_on_refinement |
1364  dealii::Triangulation<dim>::smoothing_on_coarsening));
1365  }
1366  else
1367  {
1368  triangulation = std::make_shared<Triangulation>(MPI_COMM_WORLD); // Dealii's default mesh smoothing flag is none.
1369  }
1370 
1371  auto high_order_grid = std::make_shared<HighOrderGrid<dim, double>>(grid_order, triangulation);
1372 
1373  unsigned int n_entity_blocks, n_cells;
1374  int min_ele_tag, max_ele_tag;
1375  infile >> n_entity_blocks >> n_cells >> min_ele_tag >> max_ele_tag;
1376 
1377  // Set up array of p1_cells and subcells (faces). In 1d, there is currently no
1378  // standard way infile deal.II to pass boundary indicators attached to individual
1379  // vertices, so do this by hand via the boundary_ids_1d array
1380 
1381  std::vector<dealii::CellData<dim>> p1_cells;
1382  std::vector<dealii::CellData<dim>> high_order_cells;
1383  dealii::CellData<dim> temp_high_order_cells;
1384 
1385  dealii::SubCellData subcelldata;
1386  std::map<unsigned int, dealii::types::boundary_id> boundary_ids_1d;
1387 
1388  unsigned int global_cell = 0;
1389  for (unsigned int entity_block = 0; entity_block < n_entity_blocks; ++entity_block) {
1390  unsigned int material_id;
1391  unsigned long numElements;
1392  int cell_type;
1393 
1394  // For gmsh_file_format 4.1 the order of tag and dim is reversed,
1395  int tagEntity, dimEntity;
1396  infile >> dimEntity >> tagEntity >> cell_type >> numElements;
1397  material_id = tag_maps[dimEntity][tagEntity];
1398 
1399  const unsigned int cell_order = gmsh_cell_type_to_order(cell_type);
1400 
1401  unsigned int vertices_per_element = std::pow(2, dimEntity);
1402  unsigned int nodes_per_element = std::pow(cell_order + 1, dimEntity);
1403 
1404 
1405  for (unsigned int cell_per_entity = 0; cell_per_entity < numElements; ++cell_per_entity, ++global_cell) {
1406 
1407  // Ignore tag
1408  int tag;
1409  infile >> tag;
1410 
1411  if (dimEntity == dim) {
1412 
1417  // Allocate and read indices
1418  p1_cells.emplace_back(vertices_per_element);
1419  high_order_cells.emplace_back(vertices_per_element);
1420 
1421  auto &p1_vertices_id = p1_cells.back().vertices;
1422  auto &high_order_vertices_id = high_order_cells.back().vertices;
1423 
1424  p1_vertices_id.resize(vertices_per_element);
1425  high_order_vertices_id.resize(nodes_per_element);
1426 
1427  for (unsigned int i = 0; i < nodes_per_element; ++i) {
1428  infile >> high_order_vertices_id[i];
1429  }
1430  for (unsigned int i = 0; i < vertices_per_element; ++i) {
1431  p1_vertices_id[i] = high_order_vertices_id[i];
1432  }
1433 
1434  // To make sure that the cast won't fail
1435  Assert(material_id <= std::numeric_limits<dealii::types::material_id>::max(),
1436  dealii::ExcIndexRange( material_id, 0, std::numeric_limits<dealii::types::material_id>::max()));
1437  // We use only material_ids infile the range from 0 to dealii::numbers::invalid_material_id-1
1438  AssertIndexRange(material_id, dealii::numbers::invalid_material_id);
1439 
1440  p1_cells.back().material_id = material_id;
1441 
1442  // Transform from ucd to consecutive numbering
1443  for (unsigned int i = 0; i < vertices_per_element; ++i) {
1444  //AssertThrow( vertex_indices.find(p1_cells.back().vertices[i]) != vertex_indices.end(),
1445  // dealii::ExcInvalidVertexIndexGmsh(global_cell, elm_number, p1_cells.back().vertices[i]));
1446 
1447  // Vertex with this index exists
1448  p1_vertices_id[i] = vertex_indices[p1_cells.back().vertices[i]];
1449  }
1450  for (unsigned int i = 0; i < nodes_per_element; ++i) {
1451  high_order_vertices_id[i] = vertex_indices[high_order_cells.back().vertices[i]];
1452  }
1453  } else if (dimEntity == 1 && dimEntity < dim) {
1454 
1455  // Boundary info
1456  subcelldata.boundary_lines.emplace_back(vertices_per_element);
1457  auto &p1_vertices_id = subcelldata.boundary_lines.back().vertices;
1458  p1_vertices_id.resize(vertices_per_element);
1459 
1460  temp_high_order_cells.vertices.resize(nodes_per_element);
1461 
1462  for (unsigned int i = 0; i < nodes_per_element; ++i) {
1463  infile >> temp_high_order_cells.vertices[i];
1464  }
1465  for (unsigned int i = 0; i < vertices_per_element; ++i) {
1466  p1_vertices_id[i] = temp_high_order_cells.vertices[i];
1467  }
1468 
1469  // To make sure that the cast won't fail
1470  Assert(material_id <= std::numeric_limits<dealii::types::boundary_id>::max(),
1471  dealii::ExcIndexRange( material_id, 0, std::numeric_limits<dealii::types::boundary_id>::max()));
1472  // We use only boundary_ids infile the range from 0 to dealii::numbers::internal_face_boundary_id-1
1473  AssertIndexRange(material_id, dealii::numbers::internal_face_boundary_id);
1474 
1475  subcelldata.boundary_lines.back().boundary_id = static_cast<dealii::types::boundary_id>(material_id);
1476 
1477  // Transform from ucd to consecutive numbering
1478  for (unsigned int &vertex : subcelldata.boundary_lines.back().vertices) {
1479  if (vertex_indices.find(vertex) != vertex_indices.end()) {
1480  vertex = vertex_indices[vertex];
1481  } else {
1482  // No such vertex index
1483  //AssertThrow(false, dealii::ExcInvalidVertexIndex(cell_per_entity, vertex));
1484  vertex = dealii::numbers::invalid_unsigned_int;
1485  std::abort();
1486  }
1487  }
1488  } else if (dimEntity == 2 && dimEntity < dim) {
1489 
1490  // Boundary info
1491  subcelldata.boundary_quads.emplace_back(vertices_per_element);
1492  auto &p1_vertices_id = subcelldata.boundary_quads.back().vertices;
1493  p1_vertices_id.resize(vertices_per_element);
1494 
1495  temp_high_order_cells.vertices.resize(nodes_per_element);
1496 
1497  for (unsigned int i = 0; i < nodes_per_element; ++i) {
1498  infile >> temp_high_order_cells.vertices[i];
1499  }
1500  for (unsigned int i = 0; i < vertices_per_element; ++i) {
1501  p1_vertices_id[i] = temp_high_order_cells.vertices[i];
1502  }
1503 
1504  // To make sure that the cast won't fail
1505  Assert(material_id <= std::numeric_limits<dealii::types::boundary_id>::max(),
1506  dealii::ExcIndexRange( material_id, 0, std::numeric_limits<dealii::types::boundary_id>::max()));
1507  // We use only boundary_ids infile the range from 0 to dealii::numbers::internal_face_boundary_id-1
1508  AssertIndexRange(material_id, dealii::numbers::internal_face_boundary_id);
1509 
1510  subcelldata.boundary_quads.back().boundary_id = static_cast<dealii::types::boundary_id>(material_id);
1511 
1512  // Transform from gmsh to consecutive numbering
1513  for (unsigned int &vertex : subcelldata.boundary_quads.back().vertices) {
1514  if (vertex_indices.find(vertex) != vertex_indices.end()) {
1515  vertex = vertex_indices[vertex];
1516  } else {
1517  // No such vertex index
1518  //Assert(false, dealii::ExcInvalidVertexIndex(cell_per_entity, vertex));
1519  vertex = dealii::numbers::invalid_unsigned_int;
1520  }
1521  }
1522  } else if (cell_type == MSH_PNT) {
1523  // Read the indices of nodes given
1524  unsigned int node_index = 0;
1525  infile >> node_index;
1526 
1527  // We only care about boundary indicators assigned to individual
1528  // vertices infile 1d (because otherwise the vertices are not faces)
1529  if (dim == 1) {
1530  boundary_ids_1d[vertex_indices[node_index]] = material_id;
1531  }
1532  } else {
1533  //AssertThrow(false, dealii::ExcGmshUnsupportedGeometry(cell_type));
1534  }
1535  } // End of cell per entity
1536  } // End of entity block
1537 
1538  AssertDimension(global_cell, n_cells);
1539 
1540  // Assert we reached the end of the block
1541  infile >> line;
1542  static const std::string end_elements_marker[] = {"$ENDELM", "$EndElements"};
1543  //AssertThrow(line == end_elements_marker[gmsh_file_format == 10 ? 0 : 1],
1544  // PHiLiP::ExcInvalidGMSHInput(line));
1545 
1546  // Check that no forbidden arrays are used
1547  Assert(subcelldata.check_consistency(dim), dealii::ExcInternalError());
1548 
1549  AssertThrow(infile, dealii::ExcIO());
1550 
1551  // Check that we actually read some p1_cells.
1552  // AssertThrow(p1_cells.size() > 0, dealii::ExcGmshNoCellInformation());
1553 
1554  // Do some clean-up on vertices...
1555  const std::vector<dealii::Point<spacedim>> all_vertices = vertices;
1556  dealii::GridTools::delete_unused_vertices(vertices, p1_cells, subcelldata);
1557 
1558  // ... and p1_cells
1559  if (dim == spacedim) {
1560  dealii::GridReordering<dim, spacedim>::invert_all_cells_of_negative_grid(vertices, p1_cells);
1561  }
1562  dealii::GridReordering<dim, spacedim>::reorder_cells(p1_cells);
1563  triangulation->create_triangulation_compatibility(vertices, p1_cells, subcelldata);
1564 
1565  triangulation->repartition();
1566 
1567  dealii::GridOut gridout;
1568  gridout.write_mesh_per_processor_as_vtu(*(high_order_grid->triangulation), "tria");
1569 
1570  // in 1d, we also have to attach boundary ids to vertices, which does not
1571  // currently work through the call above
1572  if (dim == 1) {
1573  assign_1d_boundary_ids(boundary_ids_1d, *triangulation);
1574  }
1575 
1576  high_order_grid->initialize_with_triangulation_manifold();
1577 
1578  std::vector<unsigned int> deal_h2l = dealii::FETools::hierarchic_to_lexicographic_numbering<dim>(grid_order);
1579  std::vector<unsigned int> deal_l2h = dealii::Utilities::invert_permutation(deal_h2l);
1580 
1581  std::vector<unsigned int> gmsh_h2l = gmsh_hierarchic_to_lexicographic<dim>(grid_order,mesh_reader_verbose_output);
1582  std::vector<unsigned int> gmsh_l2h = dealii::Utilities::invert_permutation(gmsh_h2l);
1583 
1584  int icell = 0;
1585  std::vector<dealii::types::global_dof_index> dof_indices(high_order_grid->fe_system.dofs_per_cell);
1586 
1587  std::vector<unsigned int> rotate_z90degree;
1588 
1592  std::vector<unsigned int> rotate_z90degree_3D;
1593  std::vector<unsigned int> rotate_y90degree_3D;
1594  std::vector<unsigned int> rotate_x90degree_3D;
1595  std::vector<unsigned int> rotate_flip_z90degree_3D;
1596 
1597  //2D Rotation matrix (Pre allocate once)
1598  if constexpr(dim == 2) {
1599  if(mesh_reader_verbose_output) pcout << "Allocating 2D Rotate Z matrix..." << std::endl;
1600  rotate_indices<dim>(rotate_z90degree, grid_order+1, 'Z', mesh_reader_verbose_output);
1601  } else {
1602  //3D Rotation matrix (Pre allocate once)
1603  if(mesh_reader_verbose_output) pcout << "Allocating 3D Rotate Z matrix..." << std::endl;
1604  rotate_indices<dim>(rotate_z90degree_3D, grid_order + 1, 'Z', mesh_reader_verbose_output);
1605  if(mesh_reader_verbose_output) pcout << "Allocating 3D Rotate Y matrix..." << std::endl;
1606  rotate_indices<dim>(rotate_y90degree_3D, grid_order + 1, 'Y', mesh_reader_verbose_output);
1607  if(mesh_reader_verbose_output) pcout << "Allocating 3D Rotate X matrix..." << std::endl;
1608  rotate_indices<dim>(rotate_x90degree_3D, grid_order + 1, 'X', mesh_reader_verbose_output);
1609  if(mesh_reader_verbose_output) pcout << "Allocating 3D Rotate FLIP matrix..." << std::endl;
1610  rotate_indices<dim>(rotate_flip_z90degree_3D, grid_order + 1, 'F', mesh_reader_verbose_output);
1611  }
1612 
1613  if(mesh_reader_verbose_output) pcout << " " << std::endl;
1614  if(mesh_reader_verbose_output) pcout << "*********************************************************************\n";
1615  if(mesh_reader_verbose_output) pcout << "//********************** BEGIN ROTATING CELLS *********************//\n";
1616  if(mesh_reader_verbose_output) pcout << "*********************************************************************\n";
1617  if(mesh_reader_verbose_output) pcout << " " << std::endl;
1618 
1622  for (const auto &cell : high_order_grid->dof_handler_grid.active_cell_iterators()) {
1623  if (cell->is_locally_owned()) {
1624  auto &high_order_vertices_id = high_order_cells[icell].vertices;
1625 
1626  auto high_order_vertices_id_lexico = high_order_vertices_id;
1627  for (unsigned int ihierachic=0; ihierachic<high_order_vertices_id.size(); ++ihierachic) {
1628  const unsigned int lexico_id = gmsh_h2l[ihierachic];
1629  high_order_vertices_id_lexico[lexico_id] = high_order_vertices_id[ihierachic];
1630  }
1631 
1632  //auto high_order_vertices_id_rotated = high_order_cells[icell].vertices;
1633  auto high_order_vertices_id_rotated = high_order_vertices_id_lexico;
1634 
1635  if constexpr(dim == 2) { //2D case
1636 
1637  bool good_rotation = get_new_rotated_indices(*cell, all_vertices, deal_h2l, rotate_z90degree, high_order_vertices_id_rotated);
1638  if (!good_rotation) {
1639  //std::cout << "Couldn't find rotation... Flipping Z axis and doing it again" << std::endl;
1640 
1641  // Flip Z-axis and do above again
1642  std::vector<unsigned int> flipZ;
1643  rotate_indices<dim>(flipZ, grid_order+1, '3', mesh_reader_verbose_output);
1644  auto high_order_vertices_id_copy = high_order_vertices_id_rotated;
1645  for (unsigned int i=0; i<high_order_vertices_id_rotated.size(); ++i) {
1646  high_order_vertices_id_rotated[i] = high_order_vertices_id_copy[flipZ[i]];
1647  }
1648  good_rotation = get_new_rotated_indices(*cell, all_vertices, deal_h2l, rotate_z90degree, high_order_vertices_id_rotated);
1649  }
1650 
1651  if (!good_rotation) {
1652  std::cout << "Couldn't find rotation after flipping either... Aborting..." << std::endl;
1653  std::abort();
1654  }
1655 
1656  } else { //3D case
1657 
1658  bool good_rotation = get_new_rotated_indices_3D(*cell, all_vertices, deal_h2l, rotate_x90degree_3D, rotate_y90degree_3D, rotate_z90degree_3D, high_order_vertices_id_rotated, mesh_reader_verbose_output);
1659  if (!good_rotation) {
1660  if(mesh_reader_verbose_output) pcout << "3D -- Couldn't find rotation... Flipping Z axis and doing it again" << std::endl;
1661 
1662  // Flip Z-axis and perform rotation again.
1663  auto high_order_vertices_id_copy = high_order_vertices_id_rotated;
1664  for (unsigned int i=0; i<high_order_vertices_id_rotated.size(); ++i) {
1665  high_order_vertices_id_rotated[i] = high_order_vertices_id_copy[rotate_flip_z90degree_3D[i]];
1666  }
1667 
1668  //Flip boolean should be included inside this boolean if statement
1669  good_rotation = get_new_rotated_indices_3D(*cell, all_vertices, deal_h2l, rotate_x90degree_3D, rotate_y90degree_3D, rotate_z90degree_3D, high_order_vertices_id_rotated, mesh_reader_verbose_output);
1670  }
1671 
1672  if (!good_rotation) {
1673  if(mesh_reader_verbose_output) pcout << "3D -- Couldn't find rotation after flipping 3D either... Aborting..." << std::endl;
1674  std::abort();
1675  }
1676  }
1677 
1678  cell->get_dof_indices(dof_indices);
1679  for (unsigned int i_vertex = 0; i_vertex < high_order_vertices_id.size(); ++i_vertex) {
1680 
1681  const unsigned int base_index = i_vertex;
1682  const unsigned int lexicographic_index = deal_h2l[base_index];
1683 
1684  const unsigned int vertex_id = high_order_vertices_id_rotated[lexicographic_index];
1685  const dealii::Point<dim,double> vertex = all_vertices[vertex_id];
1686 
1687 
1688  for (int d = 0; d < dim; ++d) {
1689  const unsigned int comp = d;
1690  const unsigned int shape_index = high_order_grid->dof_handler_grid.get_fe().component_to_system_index(comp, base_index);
1691  const unsigned int idof_global = dof_indices[shape_index];
1692  high_order_grid->volume_nodes[idof_global] = vertex[d];
1693  }
1694  }
1695  }
1696  icell++;
1697  }
1698 
1699  if(mesh_reader_verbose_output) pcout << " " << std::endl;
1700  if(mesh_reader_verbose_output) pcout << "*********************************************************************\n";
1701  if(mesh_reader_verbose_output) pcout << "//********************** DONE ROTATING CELLS **********************//\n";
1702  if(mesh_reader_verbose_output) pcout << "*********************************************************************\n";
1703  if(mesh_reader_verbose_output) pcout << " " << std::endl;
1704 
1705  high_order_grid->volume_nodes.update_ghost_values();
1706  high_order_grid->ensure_conforming_mesh();
1707 
1709  {
1710  std::vector<dealii::Point<1>> equidistant_points(grid_order+1);
1711  const double dx = 1.0 / grid_order;
1712  for (unsigned int i=0; i<grid_order+1; ++i) {
1713  equidistant_points[i](0) = i*dx;
1714  }
1715  dealii::Quadrature<1> quad_equidistant(equidistant_points);
1716  dealii::FE_Q<dim> fe_q_equidistant(quad_equidistant);
1717  dealii::FESystem<dim> fe_system_equidistant(fe_q_equidistant, dim);
1718  dealii::DoFHandler<dim> dof_handler_equidistant(*triangulation);
1719 
1720  dof_handler_equidistant.initialize(*triangulation, fe_system_equidistant);
1721  dof_handler_equidistant.distribute_dofs(fe_system_equidistant);
1722 
1723  if(do_renumber_dofs) dealii::DoFRenumbering::Cuthill_McKee(dof_handler_equidistant);
1724 
1725  auto equidistant_nodes = high_order_grid->volume_nodes;
1726  equidistant_nodes.update_ghost_values();
1727  high_order_grid->volume_nodes.update_ghost_values();
1728  dealii::FETools::interpolate(dof_handler_equidistant, equidistant_nodes, high_order_grid->dof_handler_grid, high_order_grid->volume_nodes);
1729  high_order_grid->volume_nodes.update_ghost_values();
1730  high_order_grid->ensure_conforming_mesh();
1731  }
1732 
1733  high_order_grid->update_surface_nodes();
1734  high_order_grid->update_mapping_fe_field();
1735  high_order_grid->reset_initial_nodes();
1736 
1737  //Check for periodic boundary conditions and apply
1738  std::vector<dealii::GridTools::PeriodicFacePair<typename dealii::Triangulation<dim>::cell_iterator> > matched_pairs;
1739 
1740  if (periodic_x) {
1741  dealii::GridTools::collect_periodic_faces(*high_order_grid->triangulation, x_periodic_1, x_periodic_2, 0, matched_pairs);
1742  }
1743 
1744  if (periodic_y) {
1745  dealii::GridTools::collect_periodic_faces(*high_order_grid->triangulation, y_periodic_1, y_periodic_2, 1, matched_pairs);
1746  }
1747 
1748  if (periodic_z) {
1749  dealii::GridTools::collect_periodic_faces(*high_order_grid->triangulation, z_periodic_1, z_periodic_2, 2, matched_pairs);
1750  }
1751 
1752  if (periodic_x || periodic_y || periodic_z) {
1753  high_order_grid->triangulation->add_periodicity(matched_pairs);
1754  }
1755 
1756 
1757  if (requested_grid_order > 0) {
1758  auto grid = std::make_shared<HighOrderGrid<dim, double>>(requested_grid_order, triangulation);
1759  grid->initialize_with_triangulation_manifold();
1760 
1762  {
1763  std::vector<dealii::Point<1>> equidistant_points(grid_order+1);
1764  const double dx = 1.0 / grid_order;
1765  for (unsigned int i=0; i<grid_order+1; ++i) {
1766  equidistant_points[i](0) = i*dx;
1767  }
1768  dealii::Quadrature<1> quad_equidistant(equidistant_points);
1769  dealii::FE_Q<dim> fe_q_equidistant(quad_equidistant);
1770  dealii::FESystem<dim> fe_system_equidistant(fe_q_equidistant, dim);
1771  dealii::DoFHandler<dim> dof_handler_equidistant(*triangulation);
1772 
1773  dof_handler_equidistant.initialize(*triangulation, fe_system_equidistant);
1774  dof_handler_equidistant.distribute_dofs(fe_system_equidistant);
1775 
1776  if(do_renumber_dofs) dealii::DoFRenumbering::Cuthill_McKee(dof_handler_equidistant);
1777 
1778  auto equidistant_nodes = high_order_grid->volume_nodes;
1779  equidistant_nodes.update_ghost_values();
1780  grid->volume_nodes.update_ghost_values();
1781  dealii::FETools::interpolate(dof_handler_equidistant, equidistant_nodes, grid->dof_handler_grid, grid->volume_nodes);
1782  grid->volume_nodes.update_ghost_values();
1783  grid->ensure_conforming_mesh();
1784  }
1785  grid->update_surface_nodes();
1786  grid->update_mapping_fe_field();
1787  grid->reset_initial_nodes();
1788 
1789  //Check for periodic boundary conditions and apply
1790  std::vector<dealii::GridTools::PeriodicFacePair<typename dealii::Triangulation<dim>::cell_iterator> > matched_pairs;
1791 
1792  if (periodic_x) {
1793  dealii::GridTools::collect_periodic_faces(*grid->triangulation, x_periodic_1, x_periodic_2, 0, matched_pairs);
1794  }
1795 
1796  if (periodic_y) {
1797  dealii::GridTools::collect_periodic_faces(*grid->triangulation, y_periodic_1, y_periodic_2, 1, matched_pairs);
1798  }
1799 
1800  if (periodic_z) {
1801  dealii::GridTools::collect_periodic_faces(*grid->triangulation, z_periodic_1, z_periodic_2, 2, matched_pairs);
1802  }
1803 
1804  if (periodic_x || periodic_y || periodic_z) {
1805  grid->triangulation->add_periodicity(matched_pairs);
1806  }
1807 
1808  return grid;
1809 
1810  } else {
1811  return high_order_grid;
1812  }
1813 }
1814 
1815 template <int dim, int spacedim>
1816 std::shared_ptr< HighOrderGrid<dim, double> >
1817 read_gmsh(std::string filename, const bool do_renumber_dofs, int requested_grid_order, const bool use_mesh_smoothing)
1818 {
1819  // default parameters
1820  const bool periodic_x = false;
1821  const bool periodic_y = false;
1822  const bool periodic_z = false;
1823  const int x_periodic_1 = 0;
1824  const int x_periodic_2 = 0;
1825  const int y_periodic_1 = 0;
1826  const int y_periodic_2 = 0;
1827  const int z_periodic_1 = 0;
1828  const int z_periodic_2 = 0;
1829  const bool mesh_reader_verbose_output = true;
1830 
1831  return read_gmsh<dim,spacedim>(filename,
1832  periodic_x, periodic_y, periodic_z,
1833  x_periodic_1, x_periodic_2,
1834  y_periodic_1, y_periodic_2,
1835  z_periodic_1, z_periodic_2,
1836  mesh_reader_verbose_output,
1837  do_renumber_dofs,
1838  requested_grid_order,
1839  use_mesh_smoothing);
1840 }
1841 
1842 #if PHILIP_DIM!=1
1843 template std::shared_ptr< HighOrderGrid<PHILIP_DIM, double> > read_gmsh<PHILIP_DIM,PHILIP_DIM>(std::string filename, const bool periodic_x, const bool periodic_y, const bool periodic_z, const int x_periodic_1, const int x_periodic_2, const int y_periodic_1, const int y_periodic_2, const int z_periodic_1, const int z_periodic_2, const bool mesh_reader_verbose_output, const bool do_renumber_dofs, int requested_grid_order, const bool use_mesh_smoothing);
1844 template std::shared_ptr< HighOrderGrid<PHILIP_DIM, double> > read_gmsh<PHILIP_DIM,PHILIP_DIM>(std::string filename, const bool do_renumber_dofs, int requested_grid_order, const bool use_mesh_smoothing);
1845 #endif
1846 
1847 } // namespace PHiLiP
std::vector< unsigned int > gmsh_hierarchic_to_lexicographic(const unsigned int degree, const bool mesh_reader_verbose_output)
void assign_1d_boundary_ids(const std::map< unsigned int, dealii::types::boundary_id > &boundary_ids, dealii::Triangulation< 1, spacedim > &triangulation)
Definition: gmsh_reader.cpp:35
std::shared_ptr< HighOrderGrid< dim, double > > read_gmsh(std::string filename, const bool periodic_x, const bool periodic_y, const bool periodic_z, const int x_periodic_1, const int x_periodic_2, const int y_periodic_1, const int y_periodic_2, const int z_periodic_1, const int z_periodic_2, const bool mesh_reader_verbose_output, const bool do_renumber_dofs, int requested_grid_order, const bool use_mesh_smoothing)
void rotate_indices(std::vector< unsigned int > &numbers, const unsigned int n_indices_per_direction, const char direction, const bool mesh_reader_verbose_output)
Definition: gmsh_reader.cpp:57
Files for the baseline physics.
Definition: ADTypes.hpp:10
std::vector< unsigned int > face_node_finder(const unsigned int degree, const bool mesh_reader_verbose_output)
bool get_new_rotated_indices(const dealii::CellAccessor< dim, spacedim > &cell, const std::vector< dealii::Point< spacedim >> &all_vertices, const std::vector< unsigned int > &deal_h2l, const std::vector< unsigned int > &rotate_z90degree, std::vector< unsigned int > &high_order_vertices_id)
bool get_new_rotated_indices_3D(const dealii::CellAccessor< dim, spacedim > &cell, const std::vector< dealii::Point< spacedim >> &all_vertices, const std::vector< unsigned int > &deal_h2l, const std::vector< unsigned int > &rotate_x90degree_3D, const std::vector< unsigned int > &rotate_y90degree_3D, const std::vector< unsigned int > &rotate_z90degree_3D, std::vector< unsigned int > &high_order_vertices_id_rotated, const bool)
unsigned int find_grid_order(std::ifstream &infile, const bool mesh_reader_verbose_output)