[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
msh_out.cpp
1 #include <float.h>
2 
3 #include <deal.II/numerics/data_out.h>
4 #include <deal.II/grid/tria.h>
5 
6 #include "msh_out.h"
7 
8 namespace PHiLiP {
9 
10 namespace GridRefinement {
11 
12 /* set of functions for outputting the mesh and data in .msh v4.1 format.
13  * contains 3 main sections:
14  * $MeshFormat - file description
15  * $Nodes - physical points of the mesh
16  * $Elements - element connectivity of mesh
17  *
18  * Additional optional section (comes before $Nodes):
19  * $Entities - geometric description of the domain
20  *
21  * And for data handling, may include multiple of section types:
22  * $NodeData - data field stored nodewise
23  * $ElementData - data field stored elementwise
24  * $ElementNodeData - data field stored nodes of each element (DG)
25  *
26  * See following for details:
27  * https://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format
28  */
29 // writing the mesh output with data if specified
30 template <int dim, typename real>
32  std::ostream &out)
33 {
34  // $MeshFormat
35  out << "$MeshFormat" << '\n';
36 
37  // version(ASCII double; currently 4.1) file-type(ASCII int; 0 for ASCII mode, 1 for binary mode) data-size(ASCII int; sizeof(size_t))
38  out << "4.1 0 8" << '\n';
39 
40  // $EndMeshFormat
41  out << "$EndMeshFormat" << '\n';
42 
43  // $Entities
44  // NOT IMPLEMENTED
45  // $EndEntities
46 
47  // $Nodes
48  out << "$Nodes" << '\n';
49 
50  const dealii::Triangulation<dim,dim> &tria = dof_handler.get_triangulation();
51 
52  const std::vector<dealii::Point<dim>> &vertices = tria.get_vertices();
53 
54  const std::vector<bool> &vertex_used = tria.get_used_vertices();
55  const unsigned int n_vertices = tria.n_used_vertices();
56 
57  // numEntityBlocks(size_t) numNodes(size_t) minNodeTag(size_t) maxNodeTag(size_t)
58  out << 1 << " " << n_vertices << " " << 1 << " " << vertices.size() << '\n';
59 
60  // entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesInBlock(size_t)
61  out << dim << " " << 1 << " " << 0 << " " << n_vertices << '\n';
62 
63  // looping over the nodes of the triangulation
64  // nodeTag(size_t)
65  for(unsigned int i = 0; i < vertices.size(); ++i){
66  if(!vertex_used[i]) continue;
67 
68  unsigned int node_tag = i + 1;
69  out << node_tag << '\n';
70  }
71 
72  // x(double) y(double) z(double)
73  for(unsigned int i = 0; i < vertices.size(); ++i){
74  if(!vertex_used[i]) continue;
75 
76  out << vertices[i];
77  for(unsigned int d = dim; d < 3; ++d)
78  out << " " << 0;
79 
80  out << '\n';
81  }
82 
83  // $EndNodes
84  out << "$EndNodes" << '\n';
85 
86 
87  // $Elements
88  out << "$Elements" << '\n';
89 
90  // elementType:
91  // 1 - 2 node line
92  // 3 - 4 node quadrangle
93  // 5 - 8 node hexahedron
94  unsigned int element_type;
95  switch(dim){
96  case 1:
97  element_type = 1;
98  break;
99 
100  case 2:
101  element_type = 3;
102  break;
103 
104  case 3:
105  element_type = 5;
106  break;
107  }
108 
109 
110  // numEntityBlocks(size_t) numElements(size_t) minElementTag(size_t) maxElementTag(size_t)
111  out << 1 << " " << tria.n_active_cells() << " " << 1 << " " << tria.n_cells() << '\n';
112 
113  // entityDim(int) entityTag(int) elementType(int; see above) numElementsInBlock(size_t)
114  out << dim << " " << 1 << " " << element_type << " " << tria.n_active_cells() << '\n';
115 
116  // elementTag(size_t) nodeTag(size_t) ...
117  for(auto cell = tria.begin_active(); cell != dof_handler.end(); ++cell){
118  if(!cell->is_locally_owned()) continue;
119 
120  unsigned int element_tag = cell->active_cell_index() + 1;
121  out << element_tag;
122 
123  // switching numbering order to match mesh writing, nodeTag = nodeIndex + 1
124  for(unsigned int vertex = 0; vertex < dealii::GeometryInfo<dim>::vertices_per_cell; ++vertex){
125  unsigned int node_tag = cell->vertex_index(dealii::GeometryInfo<dim>::ucd_to_deal[vertex]) + 1;
126  out << " " << node_tag;
127  }
128 
129  out << '\n';
130  }
131 
132  // $EndElements
133  out << "$EndElements" << '\n';
134 
135  // data sections
136  for(auto gmsh_data: data_vector)
137  gmsh_data->write_msh_data(dof_handler, out);
138 
139  out << std::flush;
140 }
141 
142 // writing the data from a MshOutData
143 template <int dim>
145  const dealii::DoFHandler<dim> &dof_handler,
146  std::ostream & out)
147 {
148  // opening section
149  switch(storage_type){
150  case StorageType::node:
151  out << "$NodeData" << '\n';
152  break;
153 
154  case StorageType::element:
155  out << "$ElementData" << '\n';
156  break;
157 
158  case StorageType::elementNode:
159  out << "$ElementNodeData" << '\n';
160  break;
161  }
162 
163  // writing the section header
164  int num_string_tags = string_tags.size();
165  int num_real_tags = real_tags.size();
166  int num_integer_tags = integer_tags.size();
167 
168  // numStringTags(ASCII int)
169  // stringTag(string) ...
170  out << num_string_tags << '\n';
171  for(auto string_tag: string_tags)
172  out << '"' << string_tag << '"' << '\n';
173 
174  // numRealTags(ASCII int)
175  // realTag(ASCII double) ...
176  out << num_real_tags << '\n';
177  for(auto real_tag: real_tags)
178  out << real_tag << '\n';
179 
180  // numIntegerTags(ASCII int)
181  // integerTag(ASCII int) ...
182  out << num_integer_tags << '\n';
183  for(auto integer_tag: integer_tags)
184  out << integer_tag << '\n';
185 
186  // writing the data (internal)
187  write_msh_data_internal(dof_handler, out);
188 
189  // closing the section
190  switch(storage_type){
191  case StorageType::node:
192  out << "$EndNodeData" << '\n';
193  break;
194 
195  case StorageType::element:
196  out << "$EndElementData" << '\n';
197  break;
198 
199  case StorageType::elementNode:
200  out << "$EndElementNodeData" << '\n';
201  break;
202  }
203 }
204 
205 // getting the number of entries (rows associated with the section)
206 template <int dim>
208  const dealii::DoFHandler<dim> &dof_handler)
209 {
210  switch(storage_type){
211  case StorageType::node:
212  return dof_handler.get_triangulation().n_used_vertices();
213 
214  case StorageType::element:
215  case StorageType::elementNode:
216  return dof_handler.get_triangulation().n_active_cells();
217  }
218 
219  return 0;
220 }
221 
222 // sets the string tags
223 template <int dim>
225  std::string name,
226  std::string interpolation_scheme)
227 {
228  string_tags.push_back(name);
229  string_tags.push_back(interpolation_scheme);
230 }
231 
232 // sets only the name
233 template <int dim>
235  std::string name)
236 {
237  string_tags.push_back(name);
238 }
239 
240 // sets the real tags
241 template <int dim>
243  double time)
244 {
245  real_tags.push_back(time);
246 }
247 
248 // sets the integer tags
249 template <int dim>
251  unsigned int time_step,
252  unsigned int num_components,
253  unsigned int num_entries)
254 {
255  integer_tags.push_back(time_step);
256  integer_tags.push_back(num_components);
257  integer_tags.push_back(num_entries);
258 }
259 
260 // different data output types
261 using Scalar = double;
262 using Vector = dealii::Tensor<1,PHILIP_DIM,double>;
263 using Matrix = dealii::Tensor<2,PHILIP_DIM,double>;
264 
265 // specifying the data size of each entry for storage
266 template <>
268 
269 template <>
271 
272 template <>
274 
275 // writing the data for scalar data
276 template <>
278  const dealii::DoFHandler<PHILIP_DIM> &dof_handler,
279  std::ostream & out)
280 {
281  const unsigned int dim = PHILIP_DIM;
282 
283  // looping through the data structure
284  switch(storage_type){
285  case StorageType::node:{
286  // nodeTag(size_t) value(double) ...
287  const dealii::Triangulation<dim,dim> &tria = dof_handler.get_triangulation();
288 
289  const std::vector<bool> &vertex_used = tria.get_used_vertices();
290 
291  // looping over the nodes of the triangulation
292  for(unsigned int i = 0; i < vertex_used.size(); ++i){
293  if(!vertex_used[i]) continue;
294 
295  Scalar node_data = data[i];
296 
297  // data entries
298  unsigned int node_tag = i + 1;
299  out << node_tag << " " << node_data << '\n';
300  }
301 
302  break;
303 
304  }case StorageType::element:{
305  // elementTag(size_t) value(double) ...
306  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
307  if(!cell->is_locally_owned()) continue;
308 
309  Scalar cell_data = data[cell->active_cell_index()];
310 
311  // data entries
312  unsigned int element_tag = cell->active_cell_index() + 1;
313  out << element_tag << " " << cell_data << '\n';
314  }
315 
316  break;
317 
318  }case StorageType::elementNode:{
319  // elementTag(size_t) numNodesPerElement(int) value(double) ...
320  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
321  if(!cell->is_locally_owned()) continue;
322 
323  unsigned int element_tag = cell->active_cell_index() + 1;
324  out << element_tag << " " << dealii::GeometryInfo<dim>::vertices_per_cell;
325 
326  // looping over the vertices
327  for(unsigned int vertex = 0; vertex < dealii::GeometryInfo<dim>::vertices_per_cell; ++vertex){
328  // nodeTag = nodeIndex + 1
329  unsigned int node_index = cell->vertex_index(dealii::GeometryInfo<dim>::ucd_to_deal[vertex]);
330 
331  Scalar node_data = data[node_index];
332 
333  out << " " << node_data;
334  }
335 
336  out << '\n';
337  }
338 
339  break;
340  }
341  }
342 }
343 
344 // writing the data for vector data
345 template <>
347  const dealii::DoFHandler<PHILIP_DIM> &dof_handler,
348  std::ostream & out)
349 {
350  const unsigned int dim = PHILIP_DIM;
351 
352  // looping through the data structure
353  switch(storage_type){
354  case StorageType::node:{
355  // nodeTag(size_t) value(double) ...
356  const dealii::Triangulation<dim,dim> &tria = dof_handler.get_triangulation();
357 
358  const std::vector<bool> &vertex_used = tria.get_used_vertices();
359 
360  // looping over the nodes of the triangulation
361  for(unsigned int i = 0; i < vertex_used.size(); ++i){
362  if(!vertex_used[i]) continue;
363 
364  Vector node_data = data[i];
365 
366  unsigned int node_tag = i + 1;
367  out << node_tag;
368 
369  // vector entries
370  for(unsigned int i = 0; i < dim; ++i)
371  out << " " << node_data[i];
372 
373  // padding zeros
374  for(unsigned int i = dim; i < 3; ++i)
375  out << " " << 0;
376 
377  out << '\n';
378  }
379 
380  break;
381 
382  }case StorageType::element:{
383  // elementTag(size_t) value(double) ...
384  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
385  if(!cell->is_locally_owned()) continue;
386 
387  Vector cell_data = data[cell->active_cell_index()];
388 
389  unsigned int element_tag = cell->active_cell_index() + 1;
390  out << element_tag;
391 
392  // vector entries
393  for(unsigned int i = 0; i < dim; ++i)
394  out << " " << cell_data[i];
395 
396  // padding zeros
397  for(unsigned int i = dim; i < 3; ++i)
398  out << " " << 0;
399 
400  out << '\n';
401  }
402 
403  break;
404 
405  }case StorageType::elementNode:{
406  // elementTag(size_t) numNodesPerElement(int) value(double) ...
407  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
408  if(!cell->is_locally_owned()) continue;
409 
410  unsigned int element_tag = cell->active_cell_index() + 1;
411  out << element_tag << " " << dealii::GeometryInfo<dim>::vertices_per_cell;
412 
413  // looping over the vertices
414  for(unsigned int vertex = 0; vertex < dealii::GeometryInfo<dim>::vertices_per_cell; ++vertex){
415  // switching numbering order to match mesh writing, nodeTag = nodeIndex + 1
416  unsigned int node_index = cell->vertex_index(dealii::GeometryInfo<dim>::ucd_to_deal[vertex]);
417 
418  Vector node_data = data[node_index];
419 
420  // vector entries
421  for(unsigned int i = 0; i < dim; ++i)
422  out << " " << node_data[i];
423 
424  // padding zeros
425  for(unsigned int i = dim; i < 3; ++i)
426  out << " " << 0;
427 
428  }
429 
430  out << '\n';
431  }
432 
433  break;
434  }
435  }
436 }
437 
438 // writing the data for matrix data
439 template <>
441  const dealii::DoFHandler<PHILIP_DIM> &dof_handler,
442  std::ostream & out)
443 {
444  const unsigned int dim = PHILIP_DIM;
445 
446  // looping through the data structure
447  switch(storage_type){
448  case StorageType::node:{
449  // nodeTag(size_t) value(double) ...
450  const dealii::Triangulation<dim,dim> &tria = dof_handler.get_triangulation();
451 
452  const std::vector<bool> &vertex_used = tria.get_used_vertices();
453 
454  // looping over the nodes of the triangulation
455  for(unsigned int i = 0; i < vertex_used.size(); ++i){
456  if(!vertex_used[i]) continue;
457 
458  Matrix node_data = data[i];
459 
460  unsigned int node_tag = i + 1;
461  out << node_tag;
462 
463  for(unsigned int i = 0; i < dim; ++i){
464  // matrix entries
465  for(unsigned int j = 0; j < dim; ++j)
466  out << " " << node_data[i][j];
467 
468  // padding zeros
469  for(unsigned int j = dim; j < 3; ++j)
470  out << " " << 0;
471  }
472 
473  // padding zeros
474  for(unsigned int i = dim; i < 3; ++i)
475  for(unsigned int j = 0; j < 3; ++j)
476  out << " " << 0;
477 
478  out << '\n';
479  }
480 
481  break;
482 
483  }case StorageType::element:{
484  // elementTag(size_t) value(double) ...
485  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
486  if(!cell->is_locally_owned()) continue;
487 
488  Matrix cell_data = data[cell->active_cell_index()];
489 
490  unsigned int element_tag = cell->active_cell_index() + 1;
491  out << element_tag;
492 
493  for(unsigned int i = 0; i < dim; ++i){
494  // matrix entries
495  for(unsigned int j = 0; j < dim; ++j)
496  out << " " << cell_data[i][j];
497 
498  // padding zeros
499  for(unsigned int j = dim; j < 3; ++j)
500  out << " " << 0;
501  }
502 
503  // padding zeros
504  for(unsigned int i = dim; i < 3; ++i)
505  for(unsigned int j = 0; j < 3; ++j)
506  out << " " << 0;
507 
508  out << '\n';
509  }
510 
511  break;
512 
513  }case StorageType::elementNode:{
514  // elementTag(size_t) numNodesPerElement(int) value(double) ...
515  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
516  if(!cell->is_locally_owned()) continue;
517 
518  unsigned int elementTag = cell->active_cell_index() + 1;
519  out << elementTag << " " << dealii::GeometryInfo<dim>::vertices_per_cell;
520 
521  // looping over the vertices
522  for(unsigned int vertex = 0; vertex < dealii::GeometryInfo<dim>::vertices_per_cell; ++vertex){
523  // switching numbering order to match mesh writing, nodeTag = nodeIndex + 1
524  unsigned int node_index = cell->vertex_index(dealii::GeometryInfo<dim>::ucd_to_deal[vertex]);
525 
526  Matrix node_data = data[node_index];
527 
528  for(unsigned int i = 0; i < dim; ++i){
529  // matrix entries
530  for(unsigned int j = 0; j < dim; ++j)
531  out << " " << node_data[i][j];
532 
533  // padding zeros
534  for(unsigned int j = dim; j < 3; ++j)
535  out << " " << 0;
536  }
537 
538  // padding zeros
539  for(unsigned int i = dim; i < 3; ++i)
540  for(unsigned int j = 0; j < 3; ++j)
541  out << " " << 0;
542 
543  }
544 
545  out << '\n';
546  }
547 
548  break;
549  }
550  }
551 }
552 
553 template class MshOut <PHILIP_DIM, double>;
554 template class MshOutData <PHILIP_DIM>;
555 
556 } // namespace GridRefinement
557 
558 } //namespace PHiLiP
Output class for GMSH .msh v4.1 file format.
Definition: msh_out.h:208
Data structure class for data fields of .msh files.
Definition: msh_out.h:34
void set_integer_tags(unsigned int time_step, unsigned int num_components, unsigned int num_entries)
Sets the required integer tags for the data field.
Definition: msh_out.cpp:250
Internal data handler class for .msh file data fields.
Definition: msh_out.h:136
Files for the baseline physics.
Definition: ADTypes.hpp:10
void write_msh(std::ostream &out)
Output formatted .msh v4.1 file with mesh description and data field.
Definition: msh_out.cpp:31
void write_msh_data_internal(const dealii::DoFHandler< dim > &dof_handler, std::ostream &out) override
Perform write of internal data field body at storage location.
unsigned int num_entries(const dealii::DoFHandler< dim > &dof_handler)
Gets the number of data entries associated with the mesh.
Definition: msh_out.cpp:207
void set_real_tags(double time)
Sets real tag to the data field.
Definition: msh_out.cpp:242
void set_string_tags(std::string name, std::string interpolation_scheme)
Sets the string tags for the data field.
Definition: msh_out.cpp:224
void write_msh_data(const dealii::DoFHandler< dim > &dof_handler, std::ostream &out)
Perform writing of .msh file data section.
Definition: msh_out.cpp:144