Reference documentation for deal.II version 9.1.0-pre
grid_in.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/base/exceptions.h>
18 #include <deal.II/base/path_search.h>
19 #include <deal.II/base/utilities.h>
20 
21 #include <deal.II/grid/grid_in.h>
22 #include <deal.II/grid/grid_reordering.h>
23 #include <deal.II/grid/grid_tools.h>
24 #include <deal.II/grid/tria.h>
25 
26 #include <boost/io/ios_state.hpp>
27 
28 #include <algorithm>
29 #include <cctype>
30 #include <fstream>
31 #include <functional>
32 #include <map>
33 
34 
35 #ifdef DEAL_II_WITH_NETCDF
36 # include <netcdfcpp.h>
37 #endif
38 
39 #ifdef DEAL_II_WITH_ASSIMP
40 # include <assimp/Importer.hpp> // C++ importer interface
41 # include <assimp/postprocess.h> // Post processing flags
42 # include <assimp/scene.h> // Output data structure
43 #endif
44 
45 
46 DEAL_II_NAMESPACE_OPEN
47 
48 
49 namespace
50 {
59  template <int spacedim>
60  void
61  assign_1d_boundary_ids(
62  const std::map<unsigned int, types::boundary_id> &boundary_ids,
63  Triangulation<1, spacedim> & triangulation)
64  {
65  if (boundary_ids.size() > 0)
67  triangulation.begin_active();
68  cell != triangulation.end();
69  ++cell)
70  for (unsigned int f = 0; f < GeometryInfo<1>::faces_per_cell; ++f)
71  if (boundary_ids.find(cell->vertex_index(f)) != boundary_ids.end())
72  {
74  cell->at_boundary(f),
75  ExcMessage(
76  "You are trying to prescribe boundary ids on the face "
77  "of a 1d cell (i.e., on a vertex), but this face is not actually at "
78  "the boundary of the mesh. This is not allowed."));
79  cell->face(f)->set_boundary_id(
80  boundary_ids.find(cell->vertex_index(f))->second);
81  }
82  }
83 
84 
85  template <int dim, int spacedim>
86  void
87  assign_1d_boundary_ids(const std::map<unsigned int, types::boundary_id> &,
89  {
90  // we shouldn't get here since boundary ids are not assigned to
91  // vertices except in 1d
92  Assert(dim != 1, ExcInternalError());
93  }
94 } // namespace
95 
96 template <int dim, int spacedim>
98  : tria(nullptr, typeid(*this).name())
99  , default_format(ucd)
100 {}
101 
102 
103 template <int dim, int spacedim>
104 void
106 {
107  tria = &t;
108 }
109 
110 
111 
112 template <int dim, int spacedim>
113 void
115 {
116  Assert((dim == 2) || (dim == 3), ExcNotImplemented());
117  std::string line;
118 
119  // verify that the first, third and fourth lines match
120  // expectations. the second line of the file may essentially be
121  // anything the author of the file chose to identify what's in
122  // there, so we just ensure that we can read it
123  {
124  std::string text[4];
125  text[0] = "# vtk DataFile Version 3.0";
126  text[1] = "****";
127  text[2] = "ASCII";
128  text[3] = "DATASET UNSTRUCTURED_GRID";
129 
130  for (unsigned int i = 0; i < 4; ++i)
131  {
132  getline(in, line);
133  if (i != 1)
134  AssertThrow(
135  line.compare(text[i]) == 0,
136  ExcMessage(
137  std::string(
138  "While reading VTK file, failed to find a header line with text <") +
139  text[i] + ">"));
140  }
141  }
142 
144 
145  std::vector<Point<spacedim>> vertices;
146  std::vector<CellData<dim>> cells;
147  SubCellData subcelldata;
148 
149  std::string keyword;
150 
151  in >> keyword;
152 
154 
155  if (keyword == "POINTS")
156  {
157  unsigned int n_vertices;
158  in >> n_vertices;
159 
160  in.ignore(256,
161  '\n'); // ignoring the number beside the total no. of points.
162 
163  for (unsigned int vertex = 0; vertex < n_vertices; ++vertex)
164  {
165  // VTK format always specifies vertex coordinates with 3 components
166  Point<3> x;
167  in >> x(0) >> x(1) >> x(2);
168 
169  vertices.emplace_back();
170  for (unsigned int d = 0; d < spacedim; ++d)
171  vertices.back()(d) = x(d);
172  }
173  }
174 
175  else
176  AssertThrow(false,
177  ExcMessage(
178  "While reading VTK file, failed to find POINTS section"));
179 
180 
183  std::string checkline;
184  int no;
185  in.ignore(256,
186  '\n'); // this move pointer to the next line ignoring unwanted no.
187  no = in.tellg();
188  getline(in, checkline);
189  if (checkline.compare("") != 0)
190  {
191  in.seekg(no);
192  }
193 
194  in >> keyword;
195 
198 
199  if (keyword == "CELLS")
200  {
201  unsigned int n_geometric_objects;
202  in >> n_geometric_objects;
203  in.ignore(256, '\n');
204 
205  if (dim == 3)
206  {
207  for (unsigned int count = 0; count < n_geometric_objects; count++)
208  {
209  unsigned int type;
210  in >> type;
211 
212  if (type == 8)
213  {
214  // we assume that the file contains first all cells,
215  // and only then any faces or lines
216  AssertThrow(subcelldata.boundary_quads.size() == 0 &&
217  subcelldata.boundary_lines.size() == 0,
219 
220  cells.emplace_back();
221 
222  for (unsigned int j = 0; j < type; j++) // loop to feed data
223  in >> cells.back().vertices[j];
224 
225  cells.back().material_id = 0;
226  }
227 
228  else if (type == 4)
229  {
230  subcelldata.boundary_quads.emplace_back();
231 
232  for (unsigned int j = 0; j < type;
233  j++) // loop to feed the data to the boundary
234  in >> subcelldata.boundary_quads.back().vertices[j];
235 
236  subcelldata.boundary_quads.back().material_id = 0;
237  }
238 
239  else
240  AssertThrow(
241  false,
242  ExcMessage(
243  "While reading VTK file, unknown file type encountered"));
244  }
245  }
246 
247  else if (dim == 2)
248  {
249  for (unsigned int count = 0; count < n_geometric_objects; count++)
250  {
251  unsigned int type;
252  in >> type;
253 
254  if (type == 4)
255  {
256  // we assume that the file contains first all cells,
257  // and only then any faces
258  AssertThrow(subcelldata.boundary_lines.size() == 0,
260 
261  cells.emplace_back();
262 
263  for (unsigned int j = 0; j < type; j++) // loop to feed data
264  in >> cells.back().vertices[j];
265 
266  cells.back().material_id = 0;
267  }
268 
269  else if (type == 2)
270  {
271  // If this is encountered, the pointer comes out of the loop
272  // and starts processing boundaries.
273  subcelldata.boundary_lines.emplace_back();
274 
275  for (unsigned int j = 0; j < type;
276  j++) // loop to feed the data to the boundary
277  {
278  in >> subcelldata.boundary_lines.back().vertices[j];
279  }
280 
281  subcelldata.boundary_lines.back().material_id = 0;
282  }
283 
284  else
285  AssertThrow(
286  false,
287  ExcMessage(
288  "While reading VTK file, unknown file type encountered"));
289  }
290  }
291  else
292  AssertThrow(false,
293  ExcMessage(
294  "While reading VTK file, failed to find CELLS section"));
295 
298 
299  in >> keyword;
300 
301  if (keyword ==
302  "CELL_TYPES") // Entering the cell_types section and ignoring data.
303  {
304  in.ignore(256, '\n');
305 
306  while (!in.fail() && !in.eof())
307  {
308  in >> keyword;
309  if (keyword != "12" && keyword != "9")
310  {
311  break;
312  }
313  }
314  }
315 
318 
319  if (keyword == "CELL_DATA")
320  {
321  unsigned int n_ids;
322  in >> n_ids;
323 
324  AssertThrow(
325  n_ids == cells.size() +
326  (dim == 3 ?
327  subcelldata.boundary_quads.size() :
328  (dim == 2 ? subcelldata.boundary_lines.size() : 0)),
329  ExcMessage(
330  "The VTK reader found a CELL_DATA statement "
331  "that lists a total of " +
332  Utilities::int_to_string(n_ids) +
333  " cell data objects, but this needs to "
334  "equal the number of cells (which is " +
335  Utilities::int_to_string(cells.size()) +
336  ") plus the number of quads (" +
337  Utilities::int_to_string(subcelldata.boundary_quads.size()) +
338  " in 3d or the number of lines (" +
339  Utilities::int_to_string(subcelldata.boundary_lines.size()) +
340  ") in 2d."));
341 
342 
343  std::string linenew;
344  std::string textnew[2];
345  textnew[0] = "SCALARS MaterialID double";
346  textnew[1] = "LOOKUP_TABLE default";
347 
348  in.ignore(256, '\n');
349 
350  for (unsigned int i = 0; i < 2; i++)
351  {
352  getline(in, linenew);
353  if (i == 0)
354  if (linenew.size() > textnew[0].size())
355  linenew.resize(textnew[0].size());
356 
357  AssertThrow(linenew.compare(textnew[i]) == 0,
358  ExcMessage(
359  std::string(
360  "While reading VTK file, failed to find <") +
361  textnew[i] + "> section"));
362  }
363 
364  // read material ids first for all cells, then for all
365  // faces. the assumption that cells come before all faces
366  // has been verified above via an assertion, so the order
367  // used in the following blocks makes sense
368  for (unsigned int i = 0; i < cells.size(); i++)
369  {
370  double id;
371  in >> id;
372  cells[i].material_id = id;
373  }
374 
375  if (dim == 3)
376  {
377  for (unsigned int i = 0; i < subcelldata.boundary_quads.size();
378  i++)
379  {
380  double id;
381  in >> id;
382  subcelldata.boundary_quads[i].material_id = id;
383  }
384  }
385  else if (dim == 2)
386  {
387  for (unsigned int i = 0; i < subcelldata.boundary_lines.size();
388  i++)
389  {
390  double id;
391  in >> id;
392  subcelldata.boundary_lines[i].material_id = id;
393  }
394  }
395  }
396 
397  Assert(subcelldata.check_consistency(dim), ExcInternalError());
398 
399  GridTools::delete_unused_vertices(vertices, cells, subcelldata);
400 
401  if (dim == spacedim)
403  vertices, cells);
404 
406  tria->create_triangulation_compatibility(vertices, cells, subcelldata);
407 
408  return;
409  }
410  else
411  AssertThrow(false,
412  ExcMessage(
413  "While reading VTK file, failed to find CELLS section"));
414 }
415 
416 
417 
418 template <int dim, int spacedim>
419 void
421 {
422  Assert(tria != nullptr, ExcNoTriangulationSelected());
423  Assert((dim == 2) || (dim == 3), ExcNotImplemented());
424 
425  AssertThrow(in, ExcIO());
426  skip_comment_lines(in, '#'); // skip comments (if any) at beginning of file
427 
428  int tmp;
429 
430  AssertThrow(in, ExcIO());
431  in >> tmp;
432  AssertThrow(in, ExcIO());
433  in >> tmp;
434 
435  // section 2411 describes vertices: see
436  // http://www.sdrl.uc.edu/sdrl/referenceinfo/universalfileformats/file-format-storehouse/universal-dataset-number-2411
437  AssertThrow(tmp == 2411, ExcUnknownSectionType(tmp));
438 
439  std::vector<Point<spacedim>> vertices; // vector of vertex coordinates
440  std::map<int, int>
441  vertex_indices; // # vert in unv (key) ---> # vert in deal.II (value)
442 
443  int no_vertex = 0; // deal.II
444 
445  while (tmp != -1) // we do until reach end of 2411
446  {
447  int no; // unv
448  int dummy;
449  double x[3];
450 
451  AssertThrow(in, ExcIO());
452  in >> no;
453 
454  tmp = no;
455  if (tmp == -1)
456  break;
457 
458  in >> dummy >> dummy >> dummy;
459 
460  AssertThrow(in, ExcIO());
461  in >> x[0] >> x[1] >> x[2];
462 
463  vertices.emplace_back();
464 
465  for (unsigned int d = 0; d < spacedim; d++)
466  vertices.back()(d) = x[d];
467 
468  vertex_indices[no] = no_vertex;
469 
470  no_vertex++;
471  }
472 
473  AssertThrow(in, ExcIO());
474  in >> tmp;
475  AssertThrow(in, ExcIO());
476  in >> tmp;
477 
478  // section 2412 describes elements: see
479  // http://www.sdrl.uc.edu/sdrl/referenceinfo/universalfileformats/file-format-storehouse/universal-dataset-number-2412
480  AssertThrow(tmp == 2412, ExcUnknownSectionType(tmp));
481 
482  std::vector<CellData<dim>> cells; // vector of cells
483  SubCellData subcelldata;
484 
485  std::map<int, int>
486  cell_indices; // # cell in unv (key) ---> # cell in deal.II (value)
487  std::map<int, int>
488  line_indices; // # line in unv (key) ---> # line in deal.II (value)
489  std::map<int, int>
490  quad_indices; // # quad in unv (key) ---> # quad in deal.II (value)
491 
492  int no_cell = 0; // deal.II
493  int no_line = 0; // deal.II
494  int no_quad = 0; // deal.II
495 
496  while (tmp != -1) // we do until reach end of 2412
497  {
498  int no; // unv
499  int type;
500  int dummy;
501 
502  AssertThrow(in, ExcIO());
503  in >> no;
504 
505  tmp = no;
506  if (tmp == -1)
507  break;
508 
509  in >> type >> dummy >> dummy >> dummy >> dummy;
510 
511  AssertThrow((type == 11) || (type == 44) || (type == 94) || (type == 115),
512  ExcUnknownElementType(type));
513 
514  if ((((type == 44) || (type == 94)) && (dim == 2)) ||
515  ((type == 115) && (dim == 3))) // cell
516  {
517  cells.emplace_back();
518 
519  AssertThrow(in, ExcIO());
520  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
521  v++)
522  in >> cells.back().vertices[v];
523 
524  cells.back().material_id = 0;
525 
526  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
527  v++)
528  cells.back().vertices[v] = vertex_indices[cells.back().vertices[v]];
529 
530  cell_indices[no] = no_cell;
531 
532  no_cell++;
533  }
534  else if (((type == 11) && (dim == 2)) ||
535  ((type == 11) && (dim == 3))) // boundary line
536  {
537  AssertThrow(in, ExcIO());
538  in >> dummy >> dummy >> dummy;
539 
540  subcelldata.boundary_lines.emplace_back();
541 
542  AssertThrow(in, ExcIO());
543  for (unsigned int v = 0; v < 2; v++)
544  in >> subcelldata.boundary_lines.back().vertices[v];
545 
546  subcelldata.boundary_lines.back().material_id = 0;
547 
548  for (unsigned int v = 0; v < 2; v++)
549  subcelldata.boundary_lines.back().vertices[v] =
550  vertex_indices[subcelldata.boundary_lines.back().vertices[v]];
551 
552  line_indices[no] = no_line;
553 
554  no_line++;
555  }
556  else if (((type == 44) || (type == 94)) && (dim == 3)) // boundary quad
557  {
558  subcelldata.boundary_quads.emplace_back();
559 
560  AssertThrow(in, ExcIO());
561  for (unsigned int v = 0; v < 4; v++)
562  in >> subcelldata.boundary_quads.back().vertices[v];
563 
564  subcelldata.boundary_quads.back().material_id = 0;
565 
566  for (unsigned int v = 0; v < 4; v++)
567  subcelldata.boundary_quads.back().vertices[v] =
568  vertex_indices[subcelldata.boundary_quads.back().vertices[v]];
569 
570  quad_indices[no] = no_quad;
571 
572  no_quad++;
573  }
574  else
575  AssertThrow(false,
576  ExcMessage("Unknown element label <" +
578  "> when running in dim=" +
580  }
581 
582  // note that so far all materials and bcs are explicitly set to 0
583  // if we do not need more info on materials and bcs - this is end of file
584  // if we do - section 2467 or 2477 comes
585 
586  in >> tmp; // tmp can be either -1 or end-of-file
587 
588  if (!in.eof())
589  {
590  AssertThrow(in, ExcIO());
591  in >> tmp;
592 
593  // section 2467 (2477) describes (materials - first and bcs - second) or
594  // (bcs - first and materials - second) - sequence depends on which
595  // group is created first: see
596  // http://www.sdrl.uc.edu/sdrl/referenceinfo/universalfileformats/file-format-storehouse/universal-dataset-number-2467
597  AssertThrow((tmp == 2467) || (tmp == 2477), ExcUnknownSectionType(tmp));
598 
599  while (tmp != -1) // we do until reach end of 2467 or 2477
600  {
601  int n_entities; // number of entities in group
602  int id; // id is either material or bc
603  int no; // unv
604  int dummy;
605 
606  AssertThrow(in, ExcIO());
607  in >> dummy;
608 
609  tmp = dummy;
610  if (tmp == -1)
611  break;
612 
613  in >> dummy >> dummy >> dummy >> dummy >> dummy >> dummy >>
614  n_entities;
615 
616  AssertThrow(in, ExcIO());
617  in >> id;
618 
619  const unsigned int n_lines =
620  (n_entities % 2 == 0) ? (n_entities / 2) : ((n_entities + 1) / 2);
621 
622  for (unsigned int line = 0; line < n_lines; line++)
623  {
624  unsigned int n_fragments;
625 
626  if (line == n_lines - 1)
627  n_fragments = (n_entities % 2 == 0) ? (2) : (1);
628  else
629  n_fragments = 2;
630 
631  for (unsigned int no_fragment = 0; no_fragment < n_fragments;
632  no_fragment++)
633  {
634  AssertThrow(in, ExcIO());
635  in >> dummy >> no >> dummy >> dummy;
636 
637  if (cell_indices.count(no) > 0) // cell - material
638  cells[cell_indices[no]].material_id = id;
639 
640  if (line_indices.count(no) > 0) // boundary line - bc
641  subcelldata.boundary_lines[line_indices[no]].material_id =
642  id;
643 
644  if (quad_indices.count(no) > 0) // boundary quad - bc
645  subcelldata.boundary_quads[quad_indices[no]].material_id =
646  id;
647  }
648  }
649  }
650  }
651 
652  Assert(subcelldata.check_consistency(dim), ExcInternalError());
653 
654  GridTools::delete_unused_vertices(vertices, cells, subcelldata);
655 
656  if (dim == spacedim)
658  cells);
659 
661 
662  tria->create_triangulation_compatibility(vertices, cells, subcelldata);
663 }
664 
665 
666 
667 template <int dim, int spacedim>
668 void
670  const bool apply_all_indicators_to_manifolds)
671 {
672  Assert(tria != nullptr, ExcNoTriangulationSelected());
673  AssertThrow(in, ExcIO());
674 
675  // skip comments at start of file
676  skip_comment_lines(in, '#');
677 
678 
679  unsigned int n_vertices;
680  unsigned int n_cells;
681  int dummy;
682 
683  in >> n_vertices >> n_cells >> dummy // number of data vectors
684  >> dummy // cell data
685  >> dummy; // model data
686  AssertThrow(in, ExcIO());
687 
688  // set up array of vertices
689  std::vector<Point<spacedim>> vertices(n_vertices);
690  // set up mapping between numbering
691  // in ucd-file (key) and in the
692  // vertices vector
693  std::map<int, int> vertex_indices;
694 
695  for (unsigned int vertex = 0; vertex < n_vertices; ++vertex)
696  {
697  int vertex_number;
698  double x[3];
699 
700  // read vertex
701  AssertThrow(in, ExcIO());
702  in >> vertex_number >> x[0] >> x[1] >> x[2];
703 
704  // store vertex
705  for (unsigned int d = 0; d < spacedim; ++d)
706  vertices[vertex](d) = x[d];
707  // store mapping; note that
708  // vertices_indices[i] is automatically
709  // created upon first usage
710  vertex_indices[vertex_number] = vertex;
711  };
712 
713  // set up array of cells
714  std::vector<CellData<dim>> cells;
715  SubCellData subcelldata;
716 
717  for (unsigned int cell = 0; cell < n_cells; ++cell)
718  {
719  // note that since in the input
720  // file we found the number of
721  // cells at the top, there
722  // should still be input here,
723  // so check this:
724  AssertThrow(in, ExcIO());
725 
726  std::string cell_type;
727 
728  // we use an unsigned int because we
729  // fill this variable through an read-in process
730  unsigned int material_id;
731 
732  in >> dummy // cell number
733  >> material_id;
734  in >> cell_type;
735 
736  if (((cell_type == "line") && (dim == 1)) ||
737  ((cell_type == "quad") && (dim == 2)) ||
738  ((cell_type == "hex") && (dim == 3)))
739  // found a cell
740  {
741  // allocate and read indices
742  cells.emplace_back();
743  for (unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_cell;
744  ++i)
745  in >> cells.back().vertices[i];
746 
747  // to make sure that the cast won't fail
748  Assert(material_id <= std::numeric_limits<types::material_id>::max(),
749  ExcIndexRange(material_id,
750  0,
751  std::numeric_limits<types::material_id>::max()));
752  // we use only material_ids in the range from 0 to
753  // numbers::invalid_material_id-1
754  Assert(material_id < numbers::invalid_material_id,
756 
757  cells.back().material_id =
758  static_cast<types::material_id>(material_id);
759 
760  // transform from ucd to
761  // consecutive numbering
762  for (unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_cell;
763  ++i)
764  if (vertex_indices.find(cells.back().vertices[i]) !=
765  vertex_indices.end())
766  // vertex with this index exists
767  cells.back().vertices[i] =
768  vertex_indices[cells.back().vertices[i]];
769  else
770  {
771  // no such vertex index
772  AssertThrow(false,
774  cells.back().vertices[i]));
775 
776  cells.back().vertices[i] = numbers::invalid_unsigned_int;
777  }
778  }
779  else if ((cell_type == "line") && ((dim == 2) || (dim == 3)))
780  // boundary info
781  {
782  subcelldata.boundary_lines.emplace_back();
783  in >> subcelldata.boundary_lines.back().vertices[0] >>
784  subcelldata.boundary_lines.back().vertices[1];
785 
786  // to make sure that the cast won't fail
787  Assert(material_id <= std::numeric_limits<types::boundary_id>::max(),
788  ExcIndexRange(material_id,
789  0,
790  std::numeric_limits<types::boundary_id>::max()));
791  // we use only boundary_ids in the range from 0 to
792  // numbers::internal_face_boundary_id-1
794  ExcIndexRange(material_id,
795  0,
797 
798  if (apply_all_indicators_to_manifolds)
799  subcelldata.boundary_lines.back().manifold_id =
800  static_cast<types::manifold_id>(material_id);
801  else
802  subcelldata.boundary_lines.back().boundary_id =
803  static_cast<types::boundary_id>(material_id);
804 
805  // transform from ucd to
806  // consecutive numbering
807  for (unsigned int i = 0; i < 2; ++i)
808  if (vertex_indices.find(
809  subcelldata.boundary_lines.back().vertices[i]) !=
810  vertex_indices.end())
811  // vertex with this index exists
812  subcelldata.boundary_lines.back().vertices[i] =
813  vertex_indices[subcelldata.boundary_lines.back().vertices[i]];
814  else
815  {
816  // no such vertex index
817  AssertThrow(false,
819  cell,
820  subcelldata.boundary_lines.back().vertices[i]));
821  subcelldata.boundary_lines.back().vertices[i] =
823  };
824  }
825  else if ((cell_type == "quad") && (dim == 3))
826  // boundary info
827  {
828  subcelldata.boundary_quads.emplace_back();
829  in >> subcelldata.boundary_quads.back().vertices[0] >>
830  subcelldata.boundary_quads.back().vertices[1] >>
831  subcelldata.boundary_quads.back().vertices[2] >>
832  subcelldata.boundary_quads.back().vertices[3];
833 
834  // to make sure that the cast won't fail
835  Assert(material_id <= std::numeric_limits<types::boundary_id>::max(),
836  ExcIndexRange(material_id,
837  0,
838  std::numeric_limits<types::boundary_id>::max()));
839  // we use only boundary_ids in the range from 0 to
840  // numbers::internal_face_boundary_id-1
842  ExcIndexRange(material_id,
843  0,
845 
846  if (apply_all_indicators_to_manifolds)
847  subcelldata.boundary_quads.back().manifold_id =
848  static_cast<types::manifold_id>(material_id);
849  else
850  subcelldata.boundary_quads.back().boundary_id =
851  static_cast<types::boundary_id>(material_id);
852 
853  // transform from ucd to
854  // consecutive numbering
855  for (unsigned int i = 0; i < 4; ++i)
856  if (vertex_indices.find(
857  subcelldata.boundary_quads.back().vertices[i]) !=
858  vertex_indices.end())
859  // vertex with this index exists
860  subcelldata.boundary_quads.back().vertices[i] =
861  vertex_indices[subcelldata.boundary_quads.back().vertices[i]];
862  else
863  {
864  // no such vertex index
865  Assert(false,
867  cell, subcelldata.boundary_quads.back().vertices[i]));
868  subcelldata.boundary_quads.back().vertices[i] =
870  };
871  }
872  else
873  // cannot read this
874  AssertThrow(false, ExcUnknownIdentifier(cell_type));
875  };
876 
877 
878  // check that no forbidden arrays are used
879  Assert(subcelldata.check_consistency(dim), ExcInternalError());
880 
881  AssertThrow(in, ExcIO());
882 
883  // do some clean-up on vertices...
884  GridTools::delete_unused_vertices(vertices, cells, subcelldata);
885  // ... and cells
886  if (dim == spacedim)
888  cells);
890  tria->create_triangulation_compatibility(vertices, cells, subcelldata);
891 }
892 
893 namespace
894 {
895  template <int dim>
896  class Abaqus_to_UCD
897  {
898  public:
899  Abaqus_to_UCD();
900 
901  void
902  read_in_abaqus(std::istream &in);
903  void
904  write_out_avs_ucd(std::ostream &out) const;
905 
906  private:
907  const double tolerance;
908 
909  std::vector<double>
910  get_global_node_numbers(const int face_cell_no,
911  const int face_cell_face_no) const;
912 
913  // NL: Stored as [ global node-id (int), x-coord, y-coord, z-coord ]
914  std::vector<std::vector<double>> node_list;
915  // CL: Stored as [ material-id (int), node1, node2, node3, node4, node5,
916  // node6, node7, node8 ]
917  std::vector<std::vector<double>> cell_list;
918  // FL: Stored as [ sideset-id (int), node1, node2, node3, node4 ]
919  std::vector<std::vector<double>> face_list;
920  // ELSET: Stored as [ (std::string) elset_name = (std::vector) of cells
921  // numbers]
922  std::map<std::string, std::vector<int>> elsets_list;
923  };
924 } // namespace
925 
926 template <int dim, int spacedim>
927 void
929  const bool apply_all_indicators_to_manifolds)
930 {
931  Assert(tria != nullptr, ExcNoTriangulationSelected());
932  Assert(dim == 2 || dim == 3, ExcNotImplemented());
933  AssertThrow(in, ExcIO());
934 
935  // Read in the Abaqus file into an intermediate object
936  // that is to be passed along to the UCD reader
937  Abaqus_to_UCD<dim> abaqus_to_ucd;
938  abaqus_to_ucd.read_in_abaqus(in);
939 
940  std::stringstream in_ucd;
941  abaqus_to_ucd.write_out_avs_ucd(in_ucd);
942 
943  // This next call is wrapped in a try-catch for the following reason:
944  // It ensures that if the Abaqus mesh is read in correctly but produces
945  // an erroneous result then the user is alerted to the source of the problem
946  // and doesn't think that they've somehow called the wrong function.
947  try
948  {
949  read_ucd(in_ucd, apply_all_indicators_to_manifolds);
950  }
951  catch (std::exception &exc)
952  {
953  std::cerr << "Exception on processing internal UCD data: " << std::endl
954  << exc.what() << std::endl;
955 
956  AssertThrow(
957  false,
958  ExcMessage(
959  "Internal conversion from ABAQUS file to UCD format was unsuccessful. "
960  "More information is provided in an error message printed above. "
961  "Are you sure that your ABAQUS mesh file conforms with the requirements "
962  "listed in the documentation?"));
963  }
964  catch (...)
965  {
966  AssertThrow(
967  false,
968  ExcMessage(
969  "Internal conversion from ABAQUS file to UCD format was unsuccessful. "
970  "Are you sure that your ABAQUS mesh file conforms with the requirements "
971  "listed in the documentation?"));
972  }
973 }
974 
975 
976 template <int dim, int spacedim>
977 void
979 {
980  Assert(tria != nullptr, ExcNoTriangulationSelected());
981  Assert(dim == 2, ExcNotImplemented());
982 
983  AssertThrow(in, ExcIO());
984 
985  // skip comments at start of file
986  skip_comment_lines(in, '#');
987 
988  // first read in identifier string
989  std::string line;
990  getline(in, line);
991 
992  AssertThrow(line == "MeshVersionFormatted 0", ExcInvalidDBMESHInput(line));
993 
994  skip_empty_lines(in);
995 
996  // next read dimension
997  getline(in, line);
998  AssertThrow(line == "Dimension", ExcInvalidDBMESHInput(line));
999  unsigned int dimension;
1000  in >> dimension;
1001  AssertThrow(dimension == dim, ExcDBMESHWrongDimension(dimension));
1002  skip_empty_lines(in);
1003 
1004  // now there are a lot of fields of
1005  // which we don't know the exact
1006  // meaning and which are far from
1007  // being properly documented in the
1008  // manual. we skip everything until
1009  // we find a comment line with the
1010  // string "# END". at some point in
1011  // the future, someone may have the
1012  // knowledge to parse and interpret
1013  // the other fields in between as
1014  // well...
1015  while (getline(in, line), line.find("# END") == std::string::npos)
1016  ;
1017  skip_empty_lines(in);
1018 
1019 
1020  // now read vertices
1021  getline(in, line);
1022  AssertThrow(line == "Vertices", ExcInvalidDBMESHInput(line));
1023 
1024  unsigned int n_vertices;
1025  double dummy;
1026 
1027  in >> n_vertices;
1028  std::vector<Point<spacedim>> vertices(n_vertices);
1029  for (unsigned int vertex = 0; vertex < n_vertices; ++vertex)
1030  {
1031  // read vertex coordinates
1032  for (unsigned int d = 0; d < dim; ++d)
1033  in >> vertices[vertex][d];
1034  // read Ref phi_i, whatever that may be
1035  in >> dummy;
1036  };
1038 
1039  skip_empty_lines(in);
1040 
1041  // read edges. we ignore them at
1042  // present, so just read them and
1043  // discard the input
1044  getline(in, line);
1045  AssertThrow(line == "Edges", ExcInvalidDBMESHInput(line));
1046 
1047  unsigned int n_edges;
1048  in >> n_edges;
1049  for (unsigned int edge = 0; edge < n_edges; ++edge)
1050  {
1051  // read vertex indices
1052  in >> dummy >> dummy;
1053  // read Ref phi_i, whatever that may be
1054  in >> dummy;
1055  };
1057 
1058  skip_empty_lines(in);
1059 
1060 
1061 
1062  // read cracked edges (whatever
1063  // that may be). we ignore them at
1064  // present, so just read them and
1065  // discard the input
1066  getline(in, line);
1067  AssertThrow(line == "CrackedEdges", ExcInvalidDBMESHInput(line));
1068 
1069  in >> n_edges;
1070  for (unsigned int edge = 0; edge < n_edges; ++edge)
1071  {
1072  // read vertex indices
1073  in >> dummy >> dummy;
1074  // read Ref phi_i, whatever that may be
1075  in >> dummy;
1076  };
1078 
1079  skip_empty_lines(in);
1080 
1081 
1082  // now read cells.
1083  // set up array of cells
1084  getline(in, line);
1085  AssertThrow(line == "Quadrilaterals", ExcInvalidDBMESHInput(line));
1086 
1087  std::vector<CellData<dim>> cells;
1088  SubCellData subcelldata;
1089  unsigned int n_cells;
1090  in >> n_cells;
1091  for (unsigned int cell = 0; cell < n_cells; ++cell)
1092  {
1093  // read in vertex numbers. they
1094  // are 1-based, so subtract one
1095  cells.emplace_back();
1096  for (unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_cell; ++i)
1097  {
1098  in >> cells.back().vertices[i];
1099 
1100  AssertThrow((cells.back().vertices[i] >= 1) &&
1101  (static_cast<unsigned int>(cells.back().vertices[i]) <=
1102  vertices.size()),
1103  ExcInvalidVertexIndex(cell, cells.back().vertices[i]));
1104 
1105  --cells.back().vertices[i];
1106  };
1107 
1108  // read and discard Ref phi_i
1109  in >> dummy;
1110  };
1112 
1113  skip_empty_lines(in);
1114 
1115 
1116  // then there are again a whole lot
1117  // of fields of which I have no
1118  // clue what they mean. skip them
1119  // all and leave the interpretation
1120  // to other implementors...
1121  while (getline(in, line), ((line.find("End") == std::string::npos) && (in)))
1122  ;
1123  // ok, so we are not at the end of
1124  // the file, that's it, mostly
1125 
1126 
1127  // check that no forbidden arrays are used
1128  Assert(subcelldata.check_consistency(dim), ExcInternalError());
1129 
1130  AssertThrow(in, ExcIO());
1131 
1132  // do some clean-up on vertices...
1133  GridTools::delete_unused_vertices(vertices, cells, subcelldata);
1134  // ...and cells
1136  cells);
1138  tria->create_triangulation_compatibility(vertices, cells, subcelldata);
1139 }
1140 
1141 
1142 
1143 template <int dim, int spacedim>
1144 void
1146 {
1147  Assert(false, ExcNotImplemented());
1148 }
1149 
1150 
1151 
1152 template <>
1153 void
1154 GridIn<2>::read_xda(std::istream &in)
1155 {
1156  Assert(tria != nullptr, ExcNoTriangulationSelected());
1157  AssertThrow(in, ExcIO());
1158 
1159  std::string line;
1160  // skip comments at start of file
1161  getline(in, line);
1162 
1163 
1164  unsigned int n_vertices;
1165  unsigned int n_cells;
1166 
1167  // read cells, throw away rest of line
1168  in >> n_cells;
1169  getline(in, line);
1170 
1171  in >> n_vertices;
1172  getline(in, line);
1173 
1174  // ignore following 8 lines
1175  for (unsigned int i = 0; i < 8; ++i)
1176  getline(in, line);
1177 
1178  // set up array of cells
1179  std::vector<CellData<2>> cells(n_cells);
1180  SubCellData subcelldata;
1181 
1182  for (unsigned int cell = 0; cell < n_cells; ++cell)
1183  {
1184  // note that since in the input
1185  // file we found the number of
1186  // cells at the top, there
1187  // should still be input here,
1188  // so check this:
1189  AssertThrow(in, ExcIO());
1191 
1192  for (unsigned int i = 0; i < 4; ++i)
1193  in >> cells[cell].vertices[i];
1194  };
1195 
1196 
1197 
1198  // set up array of vertices
1199  std::vector<Point<2>> vertices(n_vertices);
1200  for (unsigned int vertex = 0; vertex < n_vertices; ++vertex)
1201  {
1202  double x[3];
1203 
1204  // read vertex
1205  in >> x[0] >> x[1] >> x[2];
1206 
1207  // store vertex
1208  for (unsigned int d = 0; d < 2; ++d)
1209  vertices[vertex](d) = x[d];
1210  };
1211  AssertThrow(in, ExcIO());
1212 
1213  // do some clean-up on vertices...
1214  GridTools::delete_unused_vertices(vertices, cells, subcelldata);
1215  // ... and cells
1218  tria->create_triangulation_compatibility(vertices, cells, subcelldata);
1219 }
1220 
1221 
1222 
1223 template <>
1224 void
1225 GridIn<3>::read_xda(std::istream &in)
1226 {
1227  Assert(tria != nullptr, ExcNoTriangulationSelected());
1228  AssertThrow(in, ExcIO());
1229 
1230  static const unsigned int xda_to_dealII_map[] = {0, 1, 5, 4, 3, 2, 6, 7};
1231 
1232  std::string line;
1233  // skip comments at start of file
1234  getline(in, line);
1235 
1236 
1237  unsigned int n_vertices;
1238  unsigned int n_cells;
1239 
1240  // read cells, throw away rest of line
1241  in >> n_cells;
1242  getline(in, line);
1243 
1244  in >> n_vertices;
1245  getline(in, line);
1246 
1247  // ignore following 8 lines
1248  for (unsigned int i = 0; i < 8; ++i)
1249  getline(in, line);
1250 
1251  // set up array of cells
1252  std::vector<CellData<3>> cells(n_cells);
1253  SubCellData subcelldata;
1254 
1255  for (unsigned int cell = 0; cell < n_cells; ++cell)
1256  {
1257  // note that since in the input
1258  // file we found the number of
1259  // cells at the top, there
1260  // should still be input here,
1261  // so check this:
1262  AssertThrow(in, ExcIO());
1264 
1265  unsigned int xda_ordered_nodes[8];
1266 
1267  for (unsigned int i = 0; i < 8; ++i)
1268  in >> xda_ordered_nodes[i];
1269 
1270  for (unsigned int i = 0; i < 8; i++)
1271  cells[cell].vertices[i] = xda_ordered_nodes[xda_to_dealII_map[i]];
1272  };
1273 
1274 
1275 
1276  // set up array of vertices
1277  std::vector<Point<3>> vertices(n_vertices);
1278  for (unsigned int vertex = 0; vertex < n_vertices; ++vertex)
1279  {
1280  double x[3];
1281 
1282  // read vertex
1283  in >> x[0] >> x[1] >> x[2];
1284 
1285  // store vertex
1286  for (unsigned int d = 0; d < 3; ++d)
1287  vertices[vertex](d) = x[d];
1288  };
1289  AssertThrow(in, ExcIO());
1290 
1291  // do some clean-up on vertices...
1292  GridTools::delete_unused_vertices(vertices, cells, subcelldata);
1293  // ... and cells
1296  tria->create_triangulation_compatibility(vertices, cells, subcelldata);
1297 }
1298 
1299 
1300 
1301 template <int dim, int spacedim>
1302 void
1304 {
1305  Assert(tria != nullptr, ExcNoTriangulationSelected());
1306  AssertThrow(in, ExcIO());
1307 
1308  unsigned int n_vertices;
1309  unsigned int n_cells;
1310  unsigned int dummy;
1311  std::string line;
1312 
1313  in >> line;
1314 
1315  // first determine file format
1316  unsigned int gmsh_file_format = 0;
1317  if (line == "@f$NOD")
1318  gmsh_file_format = 1;
1319  else if (line == "@f$MeshFormat")
1320  gmsh_file_format = 2;
1321  else
1322  AssertThrow(false, ExcInvalidGMSHInput(line));
1323 
1324  // if file format is 2 or greater
1325  // then we also have to read the
1326  // rest of the header
1327  if (gmsh_file_format == 2)
1328  {
1329  double version;
1330  unsigned int file_type, data_size;
1331 
1332  in >> version >> file_type >> data_size;
1333 
1334  Assert((version >= 2.0) && (version <= 2.2), ExcNotImplemented());
1335  Assert(file_type == 0, ExcNotImplemented());
1336  Assert(data_size == sizeof(double), ExcNotImplemented());
1337 
1338  // read the end of the header
1339  // and the first line of the
1340  // nodes description to synch
1341  // ourselves with the format 1
1342  // handling above
1343  in >> line;
1344  AssertThrow(line == "@f$EndMeshFormat", ExcInvalidGMSHInput(line));
1345 
1346  in >> line;
1347  // if the next block is of kind
1348  // @f$PhysicalNames, ignore it
1349  if (line == "@f$PhysicalNames")
1350  {
1351  do
1352  {
1353  in >> line;
1354  }
1355  while (line != "@f$EndPhysicalNames");
1356  in >> line;
1357  }
1358 
1359  // but the next thing should,
1360  // in any case, be the list of
1361  // nodes:
1362  AssertThrow(line == "@f$Nodes", ExcInvalidGMSHInput(line));
1363  }
1364 
1365  // now read the nodes list
1366  in >> n_vertices;
1367  std::vector<Point<spacedim>> vertices(n_vertices);
1368  // set up mapping between numbering
1369  // in msh-file (nod) and in the
1370  // vertices vector
1371  std::map<int, int> vertex_indices;
1372 
1373  for (unsigned int vertex = 0; vertex < n_vertices; ++vertex)
1374  {
1375  int vertex_number;
1376  double x[3];
1377 
1378  // read vertex
1379  in >> vertex_number >> x[0] >> x[1] >> x[2];
1380 
1381  for (unsigned int d = 0; d < spacedim; ++d)
1382  vertices[vertex](d) = x[d];
1383  // store mapping
1384  vertex_indices[vertex_number] = vertex;
1385  }
1386 
1387  // Assert we reached the end of the block
1388  in >> line;
1389  static const std::string end_nodes_marker[] = {"@f$ENDNOD", "@f$EndNodes"};
1390  AssertThrow(line == end_nodes_marker[gmsh_file_format - 1],
1391  ExcInvalidGMSHInput(line));
1392 
1393  // Now read in next bit
1394  in >> line;
1395  static const std::string begin_elements_marker[] = {"@f$ELM", "@f$Elements"};
1396  AssertThrow(line == begin_elements_marker[gmsh_file_format - 1],
1397  ExcInvalidGMSHInput(line));
1398 
1399  in >> n_cells;
1400 
1401  // set up array of cells and subcells (faces). In 1d, there is currently no
1402  // standard way in deal.II to pass boundary indicators attached to individual
1403  // vertices, so do this by hand via the boundary_ids_1d array
1404  std::vector<CellData<dim>> cells;
1405  SubCellData subcelldata;
1406  std::map<unsigned int, types::boundary_id> boundary_ids_1d;
1407 
1408  for (unsigned int cell = 0; cell < n_cells; ++cell)
1409  {
1410  // note that since in the input
1411  // file we found the number of
1412  // cells at the top, there
1413  // should still be input here,
1414  // so check this:
1415  AssertThrow(in, ExcIO());
1416 
1417  unsigned int cell_type;
1418  unsigned int material_id;
1419  unsigned int nod_num;
1420 
1421  /*
1422  For file format version 1, the format of each cell is as follows:
1423  elm-number elm-type reg-phys reg-elem number-of-nodes node-number-list
1424 
1425  However, for version 2, the format reads like this:
1426  elm-number elm-type number-of-tags < tag > ... node-number-list
1427 
1428  In the following, we will ignore the element number (we simply enumerate
1429  them in the order in which we read them, and we will take reg-phys
1430  (version 1) or the first tag (version 2, if any tag is given at all) as
1431  material id.
1432  */
1433 
1434  unsigned int elm_number;
1435  in >> elm_number // ELM-NUMBER
1436  >> cell_type; // ELM-TYPE
1437 
1438  switch (gmsh_file_format)
1439  {
1440  case 1:
1441  {
1442  in >> material_id // REG-PHYS
1443  >> dummy // reg_elm
1444  >> nod_num;
1445  break;
1446  }
1447 
1448  case 2:
1449  {
1450  // read the tags; ignore all but the first one which we will
1451  // interpret as the material_id (for cells) or boundary_id
1452  // (for faces)
1453  unsigned int n_tags;
1454  in >> n_tags;
1455  if (n_tags > 0)
1456  in >> material_id;
1457  else
1458  material_id = 0;
1459 
1460  for (unsigned int i = 1; i < n_tags; ++i)
1461  in >> dummy;
1462 
1464 
1465  break;
1466  }
1467 
1468  default:
1469  AssertThrow(false, ExcNotImplemented());
1470  }
1471 
1472 
1473  /* `ELM-TYPE'
1474  defines the geometrical type of the N-th element:
1475  `1'
1476  Line (2 nodes, 1 edge).
1477 
1478  `3'
1479  Quadrangle (4 nodes, 4 edges).
1480 
1481  `5'
1482  Hexahedron (8 nodes, 12 edges, 6 faces).
1483 
1484  `15'
1485  Point (1 node).
1486  */
1487 
1488  if (((cell_type == 1) && (dim == 1)) ||
1489  ((cell_type == 3) && (dim == 2)) || ((cell_type == 5) && (dim == 3)))
1490  // found a cell
1491  {
1493  ExcMessage("Number of nodes does not coincide with the "
1494  "number required for this object"));
1495 
1496  // allocate and read indices
1497  cells.emplace_back();
1498  for (unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_cell;
1499  ++i)
1500  in >> cells.back().vertices[i];
1501 
1502  // to make sure that the cast won't fail
1503  Assert(material_id <= std::numeric_limits<types::material_id>::max(),
1504  ExcIndexRange(material_id,
1505  0,
1506  std::numeric_limits<types::material_id>::max()));
1507  // we use only material_ids in the range from 0 to
1508  // numbers::invalid_material_id-1
1509  Assert(material_id < numbers::invalid_material_id,
1510  ExcIndexRange(material_id, 0, numbers::invalid_material_id));
1511 
1512  cells.back().material_id =
1513  static_cast<types::material_id>(material_id);
1514 
1515  // transform from ucd to
1516  // consecutive numbering
1517  for (unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_cell;
1518  ++i)
1519  {
1520  AssertThrow(vertex_indices.find(cells.back().vertices[i]) !=
1521  vertex_indices.end(),
1523  elm_number,
1524  cells.back().vertices[i]));
1525 
1526  // vertex with this index exists
1527  cells.back().vertices[i] =
1528  vertex_indices[cells.back().vertices[i]];
1529  }
1530  }
1531  else if ((cell_type == 1) && ((dim == 2) || (dim == 3)))
1532  // boundary info
1533  {
1534  subcelldata.boundary_lines.emplace_back();
1535  in >> subcelldata.boundary_lines.back().vertices[0] >>
1536  subcelldata.boundary_lines.back().vertices[1];
1537 
1538  // to make sure that the cast won't fail
1539  Assert(material_id <= std::numeric_limits<types::boundary_id>::max(),
1540  ExcIndexRange(material_id,
1541  0,
1542  std::numeric_limits<types::boundary_id>::max()));
1543  // we use only boundary_ids in the range from 0 to
1544  // numbers::internal_face_boundary_id-1
1546  ExcIndexRange(material_id,
1547  0,
1549 
1550  subcelldata.boundary_lines.back().boundary_id =
1551  static_cast<types::boundary_id>(material_id);
1552 
1553  // transform from ucd to
1554  // consecutive numbering
1555  for (unsigned int i = 0; i < 2; ++i)
1556  if (vertex_indices.find(
1557  subcelldata.boundary_lines.back().vertices[i]) !=
1558  vertex_indices.end())
1559  // vertex with this index exists
1560  subcelldata.boundary_lines.back().vertices[i] =
1561  vertex_indices[subcelldata.boundary_lines.back().vertices[i]];
1562  else
1563  {
1564  // no such vertex index
1565  AssertThrow(false,
1567  cell,
1568  subcelldata.boundary_lines.back().vertices[i]));
1569  subcelldata.boundary_lines.back().vertices[i] =
1571  };
1572  }
1573  else if ((cell_type == 3) && (dim == 3))
1574  // boundary info
1575  {
1576  subcelldata.boundary_quads.emplace_back();
1577  in >> subcelldata.boundary_quads.back().vertices[0] >>
1578  subcelldata.boundary_quads.back().vertices[1] >>
1579  subcelldata.boundary_quads.back().vertices[2] >>
1580  subcelldata.boundary_quads.back().vertices[3];
1581 
1582  // to make sure that the cast won't fail
1583  Assert(material_id <= std::numeric_limits<types::boundary_id>::max(),
1584  ExcIndexRange(material_id,
1585  0,
1586  std::numeric_limits<types::boundary_id>::max()));
1587  // we use only boundary_ids in the range from 0 to
1588  // numbers::internal_face_boundary_id-1
1590  ExcIndexRange(material_id,
1591  0,
1593 
1594  subcelldata.boundary_quads.back().boundary_id =
1595  static_cast<types::boundary_id>(material_id);
1596 
1597  // transform from gmsh to
1598  // consecutive numbering
1599  for (unsigned int i = 0; i < 4; ++i)
1600  if (vertex_indices.find(
1601  subcelldata.boundary_quads.back().vertices[i]) !=
1602  vertex_indices.end())
1603  // vertex with this index exists
1604  subcelldata.boundary_quads.back().vertices[i] =
1605  vertex_indices[subcelldata.boundary_quads.back().vertices[i]];
1606  else
1607  {
1608  // no such vertex index
1609  Assert(false,
1611  cell, subcelldata.boundary_quads.back().vertices[i]));
1612  subcelldata.boundary_quads.back().vertices[i] =
1614  }
1615  }
1616  else if (cell_type == 15)
1617  {
1618  // read the indices of nodes given
1619  unsigned int node_index = 0;
1620  switch (gmsh_file_format)
1621  {
1622  case 1:
1623  {
1624  for (unsigned int i = 0; i < nod_num; ++i)
1625  in >> node_index;
1626  break;
1627  }
1628  case 2:
1629  {
1630  in >> node_index;
1631  break;
1632  }
1633  default:
1634  Assert(false, ExcInternalError());
1635  }
1636 
1637  // we only care about boundary indicators assigned to individual
1638  // vertices in 1d (because otherwise the vertices are not faces)
1639  if (dim == 1)
1640  boundary_ids_1d[vertex_indices[node_index]] = material_id;
1641  }
1642  else
1643  // cannot read this, so throw
1644  // an exception. treat
1645  // triangles and tetrahedra
1646  // specially since this
1647  // deserves a more explicit
1648  // error message
1649  {
1650  AssertThrow(cell_type != 2,
1651  ExcMessage("Found triangles while reading a file "
1652  "in gmsh format. deal.II does not "
1653  "support triangles"));
1654  AssertThrow(cell_type != 11,
1655  ExcMessage("Found tetrahedra while reading a file "
1656  "in gmsh format. deal.II does not "
1657  "support tetrahedra"));
1658 
1659  AssertThrow(false, ExcGmshUnsupportedGeometry(cell_type));
1660  }
1661  }
1662 
1663  // Assert we reached the end of the block
1664  in >> line;
1665  static const std::string end_elements_marker[] = {"@f$ENDELM", "@f$EndElements"};
1666  AssertThrow(line == end_elements_marker[gmsh_file_format - 1],
1667  ExcInvalidGMSHInput(line));
1668 
1669  // check that no forbidden arrays are used
1670  Assert(subcelldata.check_consistency(dim), ExcInternalError());
1671 
1672  AssertThrow(in, ExcIO());
1673 
1674  // check that we actually read some
1675  // cells.
1676  AssertThrow(cells.size() > 0, ExcGmshNoCellInformation());
1677 
1678  // do some clean-up on
1679  // vertices...
1680  GridTools::delete_unused_vertices(vertices, cells, subcelldata);
1681  // ... and cells
1682  if (dim == spacedim)
1684  cells);
1686  tria->create_triangulation_compatibility(vertices, cells, subcelldata);
1687 
1688  // in 1d, we also have to attach boundary ids to vertices, which does not
1689  // currently work through the call above
1690  if (dim == 1)
1691  assign_1d_boundary_ids(boundary_ids_1d, *tria);
1692 }
1693 
1694 
1695 template <>
1696 void
1697 GridIn<1>::read_netcdf(const std::string &)
1698 {
1699  AssertThrow(false, ExcImpossibleInDim(1));
1700 }
1701 
1702 template <>
1703 void
1704 GridIn<1, 2>::read_netcdf(const std::string &)
1705 {
1706  AssertThrow(false, ExcImpossibleInDim(1));
1707 }
1708 
1709 
1710 template <>
1711 void
1712 GridIn<1, 3>::read_netcdf(const std::string &)
1713 {
1714  AssertThrow(false, ExcImpossibleInDim(1));
1715 }
1716 
1717 
1718 template <>
1719 void
1720 GridIn<2, 3>::read_netcdf(const std::string &)
1721 {
1722  Assert(false, ExcNotImplemented());
1723 }
1724 
1725 template <>
1726 void
1727 GridIn<2>::read_netcdf(const std::string &filename)
1728 {
1729 #ifndef DEAL_II_WITH_NETCDF
1730  (void)filename;
1731  AssertThrow(false, ExcNeedsNetCDF());
1732 #else
1733  const unsigned int dim = 2;
1734  const unsigned int spacedim = 2;
1735  Assert(tria != nullptr, ExcNoTriangulationSelected());
1736  // this function assumes the TAU
1737  // grid format.
1738  //
1739  // This format stores 2d grids as
1740  // 3d grids. In particular, a 2d
1741  // grid of n_cells quadrilaterals
1742  // in the y=0 plane is duplicated
1743  // to y=1 to build n_cells
1744  // hexaeders. The surface
1745  // quadrilaterals of this 3d grid
1746  // are marked with boundary
1747  // marker. In the following we read
1748  // in all data required, find the
1749  // boundary marker associated with
1750  // the plane y=0, and extract the
1751  // corresponding 2d data to build a
1752  // Triangulation<2>.
1753 
1754  // In the following, we assume that
1755  // the 2d grid lies in the x-z
1756  // plane (y=0). I.e. we choose:
1757  // point[coord]=0, with coord=1
1758  const unsigned int coord = 1;
1759  // Also x-y-z (0-1-2) point
1760  // coordinates will be transformed
1761  // to x-y (x2d-y2d) coordinates.
1762  // With coord=1 as above, we have
1763  // x-z (0-2) -> (x2d-y2d)
1764  const unsigned int x2d = 0;
1765  const unsigned int y2d = 2;
1766  // For the case, the 2d grid lies
1767  // in x-y or y-z plane instead, the
1768  // following code must be extended
1769  // to find the right value for
1770  // coord, and setting x2d and y2d
1771  // accordingly.
1772 
1773  // First, open the file
1774  NcFile nc(filename.c_str());
1775  AssertThrow(nc.is_valid(), ExcIO());
1776 
1777  // then read n_cells
1778  NcDim *elements_dim = nc.get_dim("no_of_elements");
1779  AssertThrow(elements_dim->is_valid(), ExcIO());
1780  const unsigned int n_cells = elements_dim->size();
1781 
1782  // then we read
1783  // int marker(no_of_markers)
1784  NcDim *marker_dim = nc.get_dim("no_of_markers");
1785  AssertThrow(marker_dim->is_valid(), ExcIO());
1786  const unsigned int n_markers = marker_dim->size();
1787 
1788  NcVar *marker_var = nc.get_var("marker");
1789  AssertThrow(marker_var->is_valid(), ExcIO());
1790  AssertThrow(marker_var->num_dims() == 1, ExcIO());
1791  AssertThrow(static_cast<unsigned int>(marker_var->get_dim(0)->size()) ==
1792  n_markers,
1793  ExcIO());
1794 
1795  std::vector<int> marker(n_markers);
1796  // use &* to convert
1797  // vector<int>::iterator to int *
1798  marker_var->get(&*marker.begin(), n_markers);
1799 
1800  // next we read
1801  // int boundarymarker_of_surfaces(
1802  // no_of_surfaceelements)
1803  NcDim *bquads_dim = nc.get_dim("no_of_surfacequadrilaterals");
1804  AssertThrow(bquads_dim->is_valid(), ExcIO());
1805  const unsigned int n_bquads = bquads_dim->size();
1806 
1807  NcVar *bmarker_var = nc.get_var("boundarymarker_of_surfaces");
1808  AssertThrow(bmarker_var->is_valid(), ExcIO());
1809  AssertThrow(bmarker_var->num_dims() == 1, ExcIO());
1810  AssertThrow(static_cast<unsigned int>(bmarker_var->get_dim(0)->size()) ==
1811  n_bquads,
1812  ExcIO());
1813 
1814  std::vector<int> bmarker(n_bquads);
1815  bmarker_var->get(&*bmarker.begin(), n_bquads);
1816 
1817  // for each marker count the
1818  // number of boundary quads
1819  // which carry this marker
1820  std::map<int, unsigned int> n_bquads_per_bmarker;
1821  for (unsigned int i = 0; i < n_markers; ++i)
1822  {
1823  // the markers should all be
1824  // different
1825  AssertThrow(n_bquads_per_bmarker.find(marker[i]) ==
1826  n_bquads_per_bmarker.end(),
1827  ExcIO());
1828 
1829  n_bquads_per_bmarker[marker[i]] =
1830  count(bmarker.begin(), bmarker.end(), marker[i]);
1831  }
1832  // Note: the n_bquads_per_bmarker
1833  // map could be used to find the
1834  // right coord by finding the
1835  // marker0 such that
1836  // a/ n_bquads_per_bmarker[marker0]==n_cells
1837  // b/ point[coord]==0,
1838  // Condition a/ would hold for at
1839  // least two markers, marker0 and
1840  // marker1, whereas b/ would hold
1841  // for marker0 only. For marker1 we
1842  // then had point[coord]=constant
1843  // with e.g. constant=1 or -1
1844 
1845  // next we read
1846  // int points_of_surfacequadrilaterals(
1847  // no_of_surfacequadrilaterals,
1848  // points_per_surfacequadrilateral)
1849  NcDim *quad_vertices_dim = nc.get_dim("points_per_surfacequadrilateral");
1850  AssertThrow(quad_vertices_dim->is_valid(), ExcIO());
1851  const unsigned int vertices_per_quad = quad_vertices_dim->size();
1853  ExcIO());
1854 
1855  NcVar *vertex_indices_var = nc.get_var("points_of_surfacequadrilaterals");
1856  AssertThrow(vertex_indices_var->is_valid(), ExcIO());
1857  AssertThrow(vertex_indices_var->num_dims() == 2, ExcIO());
1858  AssertThrow(static_cast<unsigned int>(
1859  vertex_indices_var->get_dim(0)->size()) == n_bquads,
1860  ExcIO());
1861  AssertThrow(static_cast<unsigned int>(
1862  vertex_indices_var->get_dim(1)->size()) == vertices_per_quad,
1863  ExcIO());
1864 
1865  std::vector<int> vertex_indices(n_bquads * vertices_per_quad);
1866  vertex_indices_var->get(&*vertex_indices.begin(),
1867  n_bquads,
1868  vertices_per_quad);
1869 
1870  for (unsigned int i = 0; i < vertex_indices.size(); ++i)
1871  AssertThrow(vertex_indices[i] >= 0, ExcIO());
1872 
1873  // next we read
1874  // double points_xc(no_of_points)
1875  // double points_yc(no_of_points)
1876  // double points_zc(no_of_points)
1877  NcDim *vertices_dim = nc.get_dim("no_of_points");
1878  AssertThrow(vertices_dim->is_valid(), ExcIO());
1879  const unsigned int n_vertices = vertices_dim->size();
1880 
1881  NcVar *points_xc = nc.get_var("points_xc");
1882  NcVar *points_yc = nc.get_var("points_yc");
1883  NcVar *points_zc = nc.get_var("points_zc");
1884  AssertThrow(points_xc->is_valid(), ExcIO());
1885  AssertThrow(points_yc->is_valid(), ExcIO());
1886  AssertThrow(points_zc->is_valid(), ExcIO());
1887  AssertThrow(points_xc->num_dims() == 1, ExcIO());
1888  AssertThrow(points_yc->num_dims() == 1, ExcIO());
1889  AssertThrow(points_zc->num_dims() == 1, ExcIO());
1890  AssertThrow(points_yc->get_dim(0)->size() == static_cast<int>(n_vertices),
1891  ExcIO());
1892  AssertThrow(points_zc->get_dim(0)->size() == static_cast<int>(n_vertices),
1893  ExcIO());
1894  AssertThrow(points_xc->get_dim(0)->size() == static_cast<int>(n_vertices),
1895  ExcIO());
1896  std::vector<std::vector<double>> point_values(
1897  3, std::vector<double>(n_vertices));
1898  points_xc->get(&*point_values[0].begin(), n_vertices);
1899  points_yc->get(&*point_values[1].begin(), n_vertices);
1900  points_zc->get(&*point_values[2].begin(), n_vertices);
1901 
1902  // and fill the vertices
1903  std::vector<Point<spacedim>> vertices(n_vertices);
1904  for (unsigned int i = 0; i < n_vertices; ++i)
1905  {
1906  vertices[i](0) = point_values[x2d][i];
1907  vertices[i](1) = point_values[y2d][i];
1908  }
1909 
1910  // For all boundary quads in the
1911  // point[coord]=0 plane add the
1912  // bmarker to zero_plane_markers
1913  std::map<int, bool> zero_plane_markers;
1914  for (unsigned int quad = 0; quad < n_bquads; ++quad)
1915  {
1916  bool zero_plane = true;
1917  for (unsigned int i = 0; i < vertices_per_quad; ++i)
1918  if (point_values[coord][vertex_indices[quad * vertices_per_quad + i]] !=
1919  0)
1920  {
1921  zero_plane = false;
1922  break;
1923  }
1924 
1925  if (zero_plane)
1926  zero_plane_markers[bmarker[quad]] = true;
1927  }
1928  unsigned int sum_of_zero_plane_cells = 0;
1929  for (std::map<int, bool>::const_iterator iter = zero_plane_markers.begin();
1930  iter != zero_plane_markers.end();
1931  ++iter)
1932  sum_of_zero_plane_cells += n_bquads_per_bmarker[iter->first];
1933  AssertThrow(sum_of_zero_plane_cells == n_cells, ExcIO());
1934 
1935  // fill cells with all quads
1936  // associated with
1937  // zero_plane_markers
1938  std::vector<CellData<dim>> cells(n_cells);
1939  for (unsigned int quad = 0, cell = 0; quad < n_bquads; ++quad)
1940  {
1941  bool zero_plane = false;
1942  for (std::map<int, bool>::const_iterator iter =
1943  zero_plane_markers.begin();
1944  iter != zero_plane_markers.end();
1945  ++iter)
1946  if (bmarker[quad] == iter->first)
1947  {
1948  zero_plane = true;
1949  break;
1950  }
1951 
1952  if (zero_plane)
1953  {
1954  for (unsigned int i = 0; i < vertices_per_quad; ++i)
1955  {
1956  Assert(
1957  point_values[coord]
1958  [vertex_indices[quad * vertices_per_quad + i]] == 0,
1959  ExcNotImplemented());
1960  cells[cell].vertices[i] =
1961  vertex_indices[quad * vertices_per_quad + i];
1962  }
1963  ++cell;
1964  }
1965  }
1966 
1967  SubCellData subcelldata;
1968  GridTools::delete_unused_vertices(vertices, cells, subcelldata);
1970  tria->create_triangulation_compatibility(vertices, cells, subcelldata);
1971 #endif
1972 }
1973 
1974 
1975 template <>
1976 void
1977 GridIn<3>::read_netcdf(const std::string &filename)
1978 {
1979 #ifndef DEAL_II_WITH_NETCDF
1980  // do something with the function argument
1981  // to make sure it at least looks used,
1982  // even if it is not
1983  (void)filename;
1984  AssertThrow(false, ExcNeedsNetCDF());
1985 #else
1986  const unsigned int dim = 3;
1987  const unsigned int spacedim = 3;
1988  Assert(tria != nullptr, ExcNoTriangulationSelected());
1989  // this function assumes the TAU
1990  // grid format.
1991 
1992  // First, open the file
1993  NcFile nc(filename.c_str());
1994  AssertThrow(nc.is_valid(), ExcIO());
1995 
1996  // then read n_cells
1997  NcDim *elements_dim = nc.get_dim("no_of_elements");
1998  AssertThrow(elements_dim->is_valid(), ExcIO());
1999  const unsigned int n_cells = elements_dim->size();
2000  // and n_hexes
2001  NcDim *hexes_dim = nc.get_dim("no_of_hexaeders");
2002  AssertThrow(hexes_dim->is_valid(), ExcIO());
2003  const unsigned int n_hexes = hexes_dim->size();
2004  AssertThrow(n_hexes == n_cells,
2005  ExcMessage("deal.II can handle purely hexaedral grids, only."));
2006 
2007  // next we read
2008  // int points_of_hexaeders(
2009  // no_of_hexaeders,
2010  // points_per_hexaeder)
2011  NcDim *hex_vertices_dim = nc.get_dim("points_per_hexaeder");
2012  AssertThrow(hex_vertices_dim->is_valid(), ExcIO());
2013  const unsigned int vertices_per_hex = hex_vertices_dim->size();
2015  ExcIO());
2016 
2017  NcVar *vertex_indices_var = nc.get_var("points_of_hexaeders");
2018  AssertThrow(vertex_indices_var->is_valid(), ExcIO());
2019  AssertThrow(vertex_indices_var->num_dims() == 2, ExcIO());
2020  AssertThrow(static_cast<unsigned int>(
2021  vertex_indices_var->get_dim(0)->size()) == n_cells,
2022  ExcIO());
2023  AssertThrow(static_cast<unsigned int>(
2024  vertex_indices_var->get_dim(1)->size()) == vertices_per_hex,
2025  ExcIO());
2026 
2027  std::vector<int> vertex_indices(n_cells * vertices_per_hex);
2028  // use &* to convert
2029  // vector<int>::iterator to int *
2030  vertex_indices_var->get(&*vertex_indices.begin(), n_cells, vertices_per_hex);
2031 
2032  for (unsigned int i = 0; i < vertex_indices.size(); ++i)
2033  AssertThrow(vertex_indices[i] >= 0, ExcIO());
2034 
2035  // next we read
2036  // double points_xc(no_of_points)
2037  // double points_yc(no_of_points)
2038  // double points_zc(no_of_points)
2039  NcDim *vertices_dim = nc.get_dim("no_of_points");
2040  AssertThrow(vertices_dim->is_valid(), ExcIO());
2041  const unsigned int n_vertices = vertices_dim->size();
2042 
2043  NcVar *points_xc = nc.get_var("points_xc");
2044  NcVar *points_yc = nc.get_var("points_yc");
2045  NcVar *points_zc = nc.get_var("points_zc");
2046  AssertThrow(points_xc->is_valid(), ExcIO());
2047  AssertThrow(points_yc->is_valid(), ExcIO());
2048  AssertThrow(points_zc->is_valid(), ExcIO());
2049  AssertThrow(points_xc->num_dims() == 1, ExcIO());
2050  AssertThrow(points_yc->num_dims() == 1, ExcIO());
2051  AssertThrow(points_zc->num_dims() == 1, ExcIO());
2052  AssertThrow(points_yc->get_dim(0)->size() == static_cast<int>(n_vertices),
2053  ExcIO());
2054  AssertThrow(points_zc->get_dim(0)->size() == static_cast<int>(n_vertices),
2055  ExcIO());
2056  AssertThrow(points_xc->get_dim(0)->size() == static_cast<int>(n_vertices),
2057  ExcIO());
2058  std::vector<std::vector<double>> point_values(
2059  3, std::vector<double>(n_vertices));
2060  points_xc->get(&*point_values[0].begin(), n_vertices);
2061  points_yc->get(&*point_values[1].begin(), n_vertices);
2062  points_zc->get(&*point_values[2].begin(), n_vertices);
2063 
2064  // and fill the vertices
2065  std::vector<Point<spacedim>> vertices(n_vertices);
2066  for (unsigned int i = 0; i < n_vertices; ++i)
2067  {
2068  vertices[i](0) = point_values[0][i];
2069  vertices[i](1) = point_values[1][i];
2070  vertices[i](2) = point_values[2][i];
2071  }
2072 
2073  // and cells
2074  std::vector<CellData<dim>> cells(n_cells);
2075  for (unsigned int cell = 0; cell < n_cells; ++cell)
2076  for (unsigned int i = 0; i < vertices_per_hex; ++i)
2077  cells[cell].vertices[i] = vertex_indices[cell * vertices_per_hex + i];
2078 
2079  // for setting up the SubCellData
2080  // we read the vertex indices of
2081  // the boundary quadrilaterals and
2082  // their boundary markers
2083 
2084  // first we read
2085  // int points_of_surfacequadrilaterals(
2086  // no_of_surfacequadrilaterals,
2087  // points_per_surfacequadrilateral)
2088  NcDim *quad_vertices_dim = nc.get_dim("points_per_surfacequadrilateral");
2089  AssertThrow(quad_vertices_dim->is_valid(), ExcIO());
2090  const unsigned int vertices_per_quad = quad_vertices_dim->size();
2092  ExcIO());
2093 
2094  NcVar *bvertex_indices_var = nc.get_var("points_of_surfacequadrilaterals");
2095  AssertThrow(bvertex_indices_var->is_valid(), ExcIO());
2096  AssertThrow(bvertex_indices_var->num_dims() == 2, ExcIO());
2097  const unsigned int n_bquads = bvertex_indices_var->get_dim(0)->size();
2098  AssertThrow(static_cast<unsigned int>(
2099  bvertex_indices_var->get_dim(1)->size()) ==
2101  ExcIO());
2102 
2103  std::vector<int> bvertex_indices(n_bquads * vertices_per_quad);
2104  bvertex_indices_var->get(&*bvertex_indices.begin(),
2105  n_bquads,
2106  vertices_per_quad);
2107 
2108  // next we read
2109  // int boundarymarker_of_surfaces(
2110  // no_of_surfaceelements)
2111  NcDim *bquads_dim = nc.get_dim("no_of_surfacequadrilaterals");
2112  AssertThrow(bquads_dim->is_valid(), ExcIO());
2113  AssertThrow(static_cast<unsigned int>(bquads_dim->size()) == n_bquads,
2114  ExcIO());
2115 
2116  NcVar *bmarker_var = nc.get_var("boundarymarker_of_surfaces");
2117  AssertThrow(bmarker_var->is_valid(), ExcIO());
2118  AssertThrow(bmarker_var->num_dims() == 1, ExcIO());
2119  AssertThrow(static_cast<unsigned int>(bmarker_var->get_dim(0)->size()) ==
2120  n_bquads,
2121  ExcIO());
2122 
2123  std::vector<int> bmarker(n_bquads);
2124  bmarker_var->get(&*bmarker.begin(), n_bquads);
2125  // we only handle boundary
2126  // indicators that fit into an
2127  // types::boundary_id. Also, we don't
2128  // take numbers::internal_face_boundary_id
2129  // as it denotes an internal face
2130  for (unsigned int i = 0; i < bmarker.size(); ++i)
2131  Assert(0 <= bmarker[i] && static_cast<types::boundary_id>(bmarker[i]) !=
2133  ExcIO());
2134 
2135  // finally we setup the boundary
2136  // information
2137  SubCellData subcelldata;
2138  subcelldata.boundary_quads.resize(n_bquads);
2139  for (unsigned int i = 0; i < n_bquads; ++i)
2140  {
2141  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_face; ++v)
2142  subcelldata.boundary_quads[i].vertices[v] =
2143  bvertex_indices[i * GeometryInfo<dim>::vertices_per_face + v];
2144  subcelldata.boundary_quads[i].boundary_id =
2145  static_cast<types::boundary_id>(bmarker[i]);
2146  }
2147 
2148  GridTools::delete_unused_vertices(vertices, cells, subcelldata);
2150  cells);
2152  tria->create_triangulation_compatibility(vertices, cells, subcelldata);
2153 #endif
2154 }
2155 
2156 
2157 template <int dim, int spacedim>
2158 void
2160  std::string & header,
2161  std::vector<unsigned int> &tecplot2deal,
2162  unsigned int & n_vars,
2163  unsigned int & n_vertices,
2164  unsigned int & n_cells,
2165  std::vector<unsigned int> &IJK,
2166  bool & structured,
2167  bool & blocked)
2168 {
2169  Assert(tecplot2deal.size() == dim, ExcInternalError());
2170  Assert(IJK.size() == dim, ExcInternalError());
2171  // initialize the output variables
2172  n_vars = 0;
2173  n_vertices = 0;
2174  n_cells = 0;
2175  switch (dim)
2176  {
2177  case 3:
2178  IJK[2] = 0;
2179  DEAL_II_FALLTHROUGH;
2180  case 2:
2181  IJK[1] = 0;
2182  DEAL_II_FALLTHROUGH;
2183  case 1:
2184  IJK[0] = 0;
2185  }
2186  structured = true;
2187  blocked = false;
2188 
2189  // convert the string to upper case
2190  std::transform(header.begin(), header.end(), header.begin(), ::toupper);
2191 
2192  // replace all tabs, commas, newlines by
2193  // whitespaces
2194  std::replace(header.begin(), header.end(), '\t', ' ');
2195  std::replace(header.begin(), header.end(), ',', ' ');
2196  std::replace(header.begin(), header.end(), '\n', ' ');
2197 
2198  // now remove whitespace in front of and
2199  // after '='
2200  std::string::size_type pos = header.find('=');
2201 
2202  while (pos != static_cast<std::string::size_type>(std::string::npos))
2203  if (header[pos + 1] == ' ')
2204  header.erase(pos + 1, 1);
2205  else if (header[pos - 1] == ' ')
2206  {
2207  header.erase(pos - 1, 1);
2208  --pos;
2209  }
2210  else
2211  pos = header.find('=', ++pos);
2212 
2213  // split the string into individual entries
2214  std::vector<std::string> entries =
2215  Utilities::break_text_into_lines(header, 1, ' ');
2216 
2217  // now go through the list and try to extract
2218  for (unsigned int i = 0; i < entries.size(); ++i)
2219  {
2220  if (Utilities::match_at_string_start(entries[i], "VARIABLES=\""))
2221  {
2222  ++n_vars;
2223  // we assume, that the first variable
2224  // is x or no coordinate at all (not y or z)
2225  if (Utilities::match_at_string_start(entries[i], "VARIABLES=\"X\""))
2226  {
2227  tecplot2deal[0] = 0;
2228  }
2229  ++i;
2230  while (entries[i][0] == '"')
2231  {
2232  if (entries[i] == "\"X\"")
2233  tecplot2deal[0] = n_vars;
2234  else if (entries[i] == "\"Y\"")
2235  {
2236  // we assume, that y contains
2237  // zero data in 1d, so do
2238  // nothing
2239  if (dim > 1)
2240  tecplot2deal[1] = n_vars;
2241  }
2242  else if (entries[i] == "\"Z\"")
2243  {
2244  // we assume, that z contains
2245  // zero data in 1d and 2d, so
2246  // do nothing
2247  if (dim > 2)
2248  tecplot2deal[2] = n_vars;
2249  }
2250  ++n_vars;
2251  ++i;
2252  }
2253  // set i back, so that the next
2254  // string is treated correctly
2255  --i;
2256 
2257  AssertThrow(
2258  n_vars >= dim,
2259  ExcMessage(
2260  "Tecplot file must contain at least one variable for each dimension"));
2261  for (unsigned int d = 1; d < dim; ++d)
2262  AssertThrow(
2263  tecplot2deal[d] > 0,
2264  ExcMessage(
2265  "Tecplot file must contain at least one variable for each dimension."));
2266  }
2267  else if (Utilities::match_at_string_start(entries[i], "ZONETYPE=ORDERED"))
2268  structured = true;
2269  else if (Utilities::match_at_string_start(entries[i],
2270  "ZONETYPE=FELINESEG") &&
2271  dim == 1)
2272  structured = false;
2273  else if (Utilities::match_at_string_start(entries[i],
2274  "ZONETYPE=FEQUADRILATERAL") &&
2275  dim == 2)
2276  structured = false;
2277  else if (Utilities::match_at_string_start(entries[i],
2278  "ZONETYPE=FEBRICK") &&
2279  dim == 3)
2280  structured = false;
2281  else if (Utilities::match_at_string_start(entries[i], "ZONETYPE="))
2282  // unsupported ZONETYPE
2283  {
2284  AssertThrow(false,
2285  ExcMessage(
2286  "The tecplot file contains an unsupported ZONETYPE."));
2287  }
2288  else if (Utilities::match_at_string_start(entries[i],
2289  "DATAPACKING=POINT"))
2290  blocked = false;
2291  else if (Utilities::match_at_string_start(entries[i],
2292  "DATAPACKING=BLOCK"))
2293  blocked = true;
2294  else if (Utilities::match_at_string_start(entries[i], "F=POINT"))
2295  {
2296  structured = true;
2297  blocked = false;
2298  }
2299  else if (Utilities::match_at_string_start(entries[i], "F=BLOCK"))
2300  {
2301  structured = true;
2302  blocked = true;
2303  }
2304  else if (Utilities::match_at_string_start(entries[i], "F=FEPOINT"))
2305  {
2306  structured = false;
2307  blocked = false;
2308  }
2309  else if (Utilities::match_at_string_start(entries[i], "F=FEBLOCK"))
2310  {
2311  structured = false;
2312  blocked = true;
2313  }
2314  else if (Utilities::match_at_string_start(entries[i],
2315  "ET=QUADRILATERAL") &&
2316  dim == 2)
2317  structured = false;
2318  else if (Utilities::match_at_string_start(entries[i], "ET=BRICK") &&
2319  dim == 3)
2320  structured = false;
2321  else if (Utilities::match_at_string_start(entries[i], "ET="))
2322  // unsupported ElementType
2323  {
2324  AssertThrow(
2325  false,
2326  ExcMessage(
2327  "The tecplot file contains an unsupported ElementType."));
2328  }
2329  else if (Utilities::match_at_string_start(entries[i], "I="))
2330  IJK[0] = Utilities::get_integer_at_position(entries[i], 2).first;
2331  else if (Utilities::match_at_string_start(entries[i], "J="))
2332  {
2333  IJK[1] = Utilities::get_integer_at_position(entries[i], 2).first;
2334  AssertThrow(
2335  dim > 1 || IJK[1] == 1,
2336  ExcMessage(
2337  "Parameter 'J=' found in tecplot, although this is only possible for dimensions greater than 1."));
2338  }
2339  else if (Utilities::match_at_string_start(entries[i], "K="))
2340  {
2341  IJK[2] = Utilities::get_integer_at_position(entries[i], 2).first;
2342  AssertThrow(
2343  dim > 2 || IJK[2] == 1,
2344  ExcMessage(
2345  "Parameter 'K=' found in tecplot, although this is only possible for dimensions greater than 2."));
2346  }
2347  else if (Utilities::match_at_string_start(entries[i], "N="))
2348  n_vertices = Utilities::get_integer_at_position(entries[i], 2).first;
2349  else if (Utilities::match_at_string_start(entries[i], "E="))
2350  n_cells = Utilities::get_integer_at_position(entries[i], 2).first;
2351  }
2352 
2353  // now we have read all the fields we are
2354  // interested in. do some checks and
2355  // calculate the variables
2356  if (structured)
2357  {
2358  n_vertices = 1;
2359  n_cells = 1;
2360  for (unsigned int d = 0; d < dim; ++d)
2361  {
2362  AssertThrow(
2363  IJK[d] > 0,
2364  ExcMessage(
2365  "Tecplot file does not contain a complete and consistent set of parameters"));
2366  n_vertices *= IJK[d];
2367  n_cells *= (IJK[d] - 1);
2368  }
2369  }
2370  else
2371  {
2372  AssertThrow(
2373  n_vertices > 0,
2374  ExcMessage(
2375  "Tecplot file does not contain a complete and consistent set of parameters"));
2376  if (n_cells == 0)
2377  // this means an error, although
2378  // tecplot itself accepts entries like
2379  // 'J=20' instead of 'E=20'. therefore,
2380  // take the max of IJK
2381  n_cells = *std::max_element(IJK.begin(), IJK.end());
2382  AssertThrow(
2383  n_cells > 0,
2384  ExcMessage(
2385  "Tecplot file does not contain a complete and consistent set of parameters"));
2386  }
2387 }
2388 
2389 
2390 
2391 template <>
2392 void
2393 GridIn<2>::read_tecplot(std::istream &in)
2394 {
2395  const unsigned int dim = 2;
2396  const unsigned int spacedim = 2;
2397  Assert(tria != nullptr, ExcNoTriangulationSelected());
2398  AssertThrow(in, ExcIO());
2399 
2400  // skip comments at start of file
2401  skip_comment_lines(in, '#');
2402 
2403  // some strings for parsing the header
2404  std::string line, header;
2405 
2406  // first, concatenate all header lines
2407  // create a searchstring with almost all
2408  // letters. exclude e and E from the letters
2409  // to search, as they might appear in
2410  // exponential notation
2411  std::string letters = "abcdfghijklmnopqrstuvwxyzABCDFGHIJKLMNOPQRSTUVWXYZ";
2412 
2413  getline(in, line);
2414  while (line.find_first_of(letters) != std::string::npos)
2415  {
2416  header += " " + line;
2417  getline(in, line);
2418  }
2419 
2420  // now create some variables holding
2421  // important information on the mesh, get
2422  // this information from the header string
2423  std::vector<unsigned int> tecplot2deal(dim);
2424  std::vector<unsigned int> IJK(dim);
2425  unsigned int n_vars, n_vertices, n_cells;
2426  bool structured, blocked;
2427 
2428  parse_tecplot_header(header,
2429  tecplot2deal,
2430  n_vars,
2431  n_vertices,
2432  n_cells,
2433  IJK,
2434  structured,
2435  blocked);
2436 
2437  // reserve space for vertices. note, that in
2438  // tecplot vertices are ordered beginning
2439  // with 1, whereas in deal all indices start
2440  // with 0. in order not to use -1 for all the
2441  // connectivity information, a 0th vertex
2442  // (unused) is inserted at the origin.
2443  std::vector<Point<spacedim>> vertices(n_vertices + 1);
2444  vertices[0] = Point<spacedim>();
2445  // reserve space for cells
2446  std::vector<CellData<dim>> cells(n_cells);
2447  SubCellData subcelldata;
2448 
2449  if (blocked)
2450  {
2451  // blocked data format. first we get all
2452  // the values of the first variable for
2453  // all points, after that we get all
2454  // values for the second variable and so
2455  // on.
2456 
2457  // dummy variable to read in all the info
2458  // we do not want to use
2459  double dummy;
2460  // which is the first index to read in
2461  // the loop (see below)
2462  unsigned int next_index = 0;
2463 
2464  // note, that we have already read the
2465  // first line containing the first variable
2466  if (tecplot2deal[0] == 0)
2467  {
2468  // we need the information in this
2469  // line, so extract it
2470  std::vector<std::string> first_var =
2472  char *endptr;
2473  for (unsigned int i = 1; i < first_var.size() + 1; ++i)
2474  vertices[i](0) = std::strtod(first_var[i - 1].c_str(), &endptr);
2475 
2476  // if there are many points, the data
2477  // for this var might continue in the
2478  // next line(s)
2479  for (unsigned int j = first_var.size() + 1; j < n_vertices + 1; ++j)
2480  in >> vertices[j](next_index);
2481  // now we got all values of the first
2482  // variable, so increase the counter
2483  next_index = 1;
2484  }
2485 
2486  // main loop over all variables
2487  for (unsigned int i = 1; i < n_vars; ++i)
2488  {
2489  // if we read all the important
2490  // variables and do not want to
2491  // read further, because we are
2492  // using a structured grid, we can
2493  // stop here (and skip, for
2494  // example, a whole lot of solution
2495  // variables)
2496  if (next_index == dim && structured)
2497  break;
2498 
2499  if ((next_index < dim) && (i == tecplot2deal[next_index]))
2500  {
2501  // we need this line, read it in
2502  for (unsigned int j = 1; j < n_vertices + 1; ++j)
2503  in >> vertices[j](next_index);
2504  ++next_index;
2505  }
2506  else
2507  {
2508  // we do not need this line, read
2509  // it in and discard it
2510  for (unsigned int j = 1; j < n_vertices + 1; ++j)
2511  in >> dummy;
2512  }
2513  }
2514  Assert(next_index == dim, ExcInternalError());
2515  }
2516  else
2517  {
2518  // the data is not blocked, so we get all
2519  // the variables for one point, then the
2520  // next and so on. create a vector to
2521  // hold these components
2522  std::vector<double> vars(n_vars);
2523 
2524  // now fill the first vertex. note, that we
2525  // have already read the first line
2526  // containing the first vertex
2527  std::vector<std::string> first_vertex =
2529  char *endptr;
2530  for (unsigned int d = 0; d < dim; ++d)
2531  vertices[1](d) =
2532  std::strtod(first_vertex[tecplot2deal[d]].c_str(), &endptr);
2533 
2534  // read the remaining vertices from the
2535  // list
2536  for (unsigned int v = 2; v < n_vertices + 1; ++v)
2537  {
2538  for (unsigned int i = 0; i < n_vars; ++i)
2539  in >> vars[i];
2540  // fill the vertex
2541  // coordinates. respect the position
2542  // of coordinates in the list of
2543  // variables
2544  for (unsigned int i = 0; i < dim; ++i)
2545  vertices[v](i) = vars[tecplot2deal[i]];
2546  }
2547  }
2548 
2549  if (structured)
2550  {
2551  // this is the part of the code that only
2552  // works in 2d
2553  unsigned int I = IJK[0], J = IJK[1];
2554 
2555  unsigned int cell = 0;
2556  // set up array of cells
2557  for (unsigned int j = 0; j < J - 1; ++j)
2558  for (unsigned int i = 1; i < I; ++i)
2559  {
2560  cells[cell].vertices[0] = i + j * I;
2561  cells[cell].vertices[1] = i + 1 + j * I;
2562  cells[cell].vertices[2] = i + 1 + (j + 1) * I;
2563  cells[cell].vertices[3] = i + (j + 1) * I;
2564  ++cell;
2565  }
2566  Assert(cell == n_cells, ExcInternalError());
2567  std::vector<unsigned int> boundary_vertices(2 * I + 2 * J - 4);
2568  unsigned int k = 0;
2569  for (unsigned int i = 1; i < I + 1; ++i)
2570  {
2571  boundary_vertices[k] = i;
2572  ++k;
2573  boundary_vertices[k] = i + (J - 1) * I;
2574  ++k;
2575  }
2576  for (unsigned int j = 1; j < J - 1; ++j)
2577  {
2578  boundary_vertices[k] = 1 + j * I;
2579  ++k;
2580  boundary_vertices[k] = I + j * I;
2581  ++k;
2582  }
2583  Assert(k == boundary_vertices.size(), ExcInternalError());
2584  // delete the duplicated vertices at the
2585  // boundary, which occur, e.g. in c-type
2586  // or o-type grids around a body
2587  // (airfoil). this automatically deletes
2588  // unused vertices as well.
2590  cells,
2591  subcelldata,
2592  boundary_vertices);
2593  }
2594  else
2595  {
2596  // set up array of cells, unstructured
2597  // mode, so the connectivity is
2598  // explicitly given
2599  for (unsigned int i = 0; i < n_cells; ++i)
2600  {
2601  // note that since in the input file
2602  // we found the number of cells at
2603  // the top, there should still be
2604  // input here, so check this:
2605  AssertThrow(in, ExcIO());
2606 
2607  // get the connectivity from the
2608  // input file. the vertices are
2609  // ordered like in the ucd format
2610  for (unsigned int j = 0; j < GeometryInfo<dim>::vertices_per_cell;
2611  ++j)
2612  in >> cells[i].vertices[j];
2613  }
2614  // do some clean-up on vertices
2615  GridTools::delete_unused_vertices(vertices, cells, subcelldata);
2616  }
2617 
2618  // check that no forbidden arrays are
2619  // used. as we do not read in any
2620  // subcelldata, nothing should happen here.
2621  Assert(subcelldata.check_consistency(dim), ExcInternalError());
2622  AssertThrow(in, ExcIO());
2623 
2624  // do some cleanup on cells
2626  cells);
2628  tria->create_triangulation_compatibility(vertices, cells, subcelldata);
2629 }
2630 
2631 
2632 
2633 template <int dim, int spacedim>
2634 void
2636 {
2637  Assert(false, ExcNotImplemented());
2638 }
2639 
2640 
2641 
2642 template <int dim, int spacedim>
2643 void
2644 GridIn<dim, spacedim>::read_assimp(const std::string &filename,
2645  const unsigned int mesh_index,
2646  const bool remove_duplicates,
2647  const double tol,
2648  const bool ignore_unsupported_types)
2649 {
2650 #ifdef DEAL_II_WITH_ASSIMP
2651  // Only good for surface grids.
2652  AssertThrow(dim < 3, ExcImpossibleInDim(dim));
2653 
2654  // Create an instance of the Importer class
2655  Assimp::Importer importer;
2656 
2657  // And have it read the given file with some postprocessing
2658  const aiScene *scene =
2659  importer.ReadFile(filename.c_str(),
2660  aiProcess_RemoveComponent |
2661  aiProcess_JoinIdenticalVertices |
2662  aiProcess_ImproveCacheLocality | aiProcess_SortByPType |
2663  aiProcess_OptimizeGraph | aiProcess_OptimizeMeshes);
2664 
2665  // If the import failed, report it
2666  AssertThrow(scene, ExcMessage(importer.GetErrorString()))
2667 
2668  AssertThrow(scene->mNumMeshes,
2669  ExcMessage("Input file contains no meshes."));
2670 
2671  AssertThrow((mesh_index == numbers::invalid_unsigned_int) ||
2672  (mesh_index < scene->mNumMeshes),
2673  ExcMessage("Too few meshes in the file."));
2674 
2675  unsigned int start_mesh =
2676  (mesh_index == numbers::invalid_unsigned_int ? 0 : mesh_index);
2677  unsigned int end_mesh =
2678  (mesh_index == numbers::invalid_unsigned_int ? scene->mNumMeshes :
2679  mesh_index + 1);
2680 
2681  // Deal.II objects are created empty, and then filled with imported file.
2682  std::vector<Point<spacedim>> vertices;
2683  std::vector<CellData<dim>> cells;
2684  SubCellData subcelldata;
2685 
2686  // A series of counters to merge cells.
2687  unsigned int v_offset = 0;
2688  unsigned int c_offset = 0;
2689 
2690  // The index of the mesh will be used as a material index.
2691  for (unsigned int m = start_mesh; m < end_mesh; ++m)
2692  {
2693  const aiMesh *mesh = scene->mMeshes[m];
2694 
2695  // Check that we know what to do with this mesh, otherwise just
2696  // ignore it
2697  if ((dim == 2) && mesh->mPrimitiveTypes != aiPrimitiveType_POLYGON)
2698  {
2699  AssertThrow(ignore_unsupported_types,
2700  ExcMessage("Incompatible mesh " + std::to_string(m) +
2701  "/" + std::to_string(scene->mNumMeshes)));
2702  continue;
2703  }
2704  else if ((dim == 1) && mesh->mPrimitiveTypes != aiPrimitiveType_LINE)
2705  {
2706  AssertThrow(ignore_unsupported_types,
2707  ExcMessage("Incompatible mesh " + std::to_string(m) +
2708  "/" + std::to_string(scene->mNumMeshes)));
2709  continue;
2710  }
2711  // Vertices
2712  const unsigned int n_vertices = mesh->mNumVertices;
2713  const aiVector3D * mVertices = mesh->mVertices;
2714 
2715  // Faces
2716  const unsigned int n_faces = mesh->mNumFaces;
2717  const aiFace * mFaces = mesh->mFaces;
2718 
2719  vertices.resize(v_offset + n_vertices);
2720  cells.resize(c_offset + n_faces);
2721 
2722  for (unsigned int i = 0; i < n_vertices; ++i)
2723  for (unsigned int d = 0; d < spacedim; ++d)
2724  vertices[i + v_offset][d] = mVertices[i][d];
2725 
2726  unsigned int valid_cell = c_offset;
2727  for (unsigned int i = 0; i < n_faces; ++i)
2728  {
2729  if (mFaces[i].mNumIndices == GeometryInfo<dim>::vertices_per_cell)
2730  {
2731  for (unsigned int f = 0; f < GeometryInfo<dim>::vertices_per_cell;
2732  ++f)
2733  {
2734  cells[valid_cell].vertices[f] =
2735  mFaces[i].mIndices[f] + v_offset;
2736  }
2737  cells[valid_cell].material_id = (types::material_id)m;
2738  ++valid_cell;
2739  }
2740  else
2741  {
2742  AssertThrow(ignore_unsupported_types,
2743  ExcMessage("Face " + std::to_string(i) + " of mesh " +
2744  std::to_string(m) + " has " +
2745  std::to_string(mFaces[i].mNumIndices) +
2746  " vertices. We expected only " +
2747  std::to_string(
2749  }
2750  }
2751  cells.resize(valid_cell);
2752 
2753  // The vertices are added all at once. Cells are checked for
2754  // validity, so only valid_cells are now present in the deal.II
2755  // list of cells.
2756  v_offset += n_vertices;
2757  c_offset = valid_cell;
2758  }
2759 
2760  // No cells were read
2761  if (cells.size() == 0)
2762  return;
2763 
2764  if (remove_duplicates)
2765  {
2766  // The function delete_duplicated_vertices() needs to be called more
2767  // than once if a vertex is duplicated more than once. So we keep
2768  // calling it until the number of vertices does not change any more.
2769  unsigned int n_verts = 0;
2770  while (n_verts != vertices.size())
2771  {
2772  n_verts = vertices.size();
2773  std::vector<unsigned int> considered_vertices;
2775  vertices, cells, subcelldata, considered_vertices, tol);
2776  }
2777  }
2778 
2779  GridTools::delete_unused_vertices(vertices, cells, subcelldata);
2780  if (dim == spacedim)
2782  cells);
2783 
2785  if (dim == 2)
2786  tria->create_triangulation_compatibility(vertices, cells, subcelldata);
2787  else
2788  tria->create_triangulation(vertices, cells, subcelldata);
2789 #else
2790  (void)filename;
2791  (void)mesh_index;
2792  (void)remove_duplicates;
2793  (void)tol;
2794  (void)ignore_unsupported_types;
2795  Assert(false, ExcNeedsAssimp());
2796 #endif
2797 }
2798 
2799 
2800 template <int dim, int spacedim>
2801 void
2803 {
2804  std::string line;
2805  while (in)
2806  {
2807  // get line
2808  getline(in, line);
2809 
2810  // check if this is a line that
2811  // consists only of spaces, and
2812  // if not put the whole thing
2813  // back and return
2814  if (std::find_if(line.begin(),
2815  line.end(),
2816  std::bind(std::not_equal_to<char>(),
2817  std::placeholders::_1,
2818  ' ')) != line.end())
2819  {
2820  in.putback('\n');
2821  for (int i = line.length() - 1; i >= 0; --i)
2822  in.putback(line[i]);
2823  return;
2824  }
2825 
2826  // else: go on with next line
2827  }
2828 }
2829 
2830 
2831 
2832 template <int dim, int spacedim>
2833 void
2835  const char comment_start)
2836 {
2837  char c;
2838  // loop over the following comment
2839  // lines
2840  while (in.get(c) && c == comment_start)
2841  // loop over the characters after
2842  // the comment starter
2843  while (in.get() != '\n')
2844  ;
2845 
2846 
2847  // put back first character of
2848  // first non-comment line
2849  if (in)
2850  in.putback(c);
2851 
2852  // at last: skip additional empty lines, if present
2853  skip_empty_lines(in);
2854 }
2855 
2856 
2857 
2858 template <int dim, int spacedim>
2859 void
2861  const std::vector<CellData<dim>> & /*cells*/,
2862  const std::vector<Point<spacedim>> & /*vertices*/,
2863  std::ostream & /*out*/)
2864 {
2865  Assert(false, ExcNotImplemented());
2866 }
2867 
2868 
2869 
2870 template <>
2871 void
2872 GridIn<2>::debug_output_grid(const std::vector<CellData<2>> &cells,
2873  const std::vector<Point<2>> & vertices,
2874  std::ostream & out)
2875 {
2876  double min_x = vertices[cells[0].vertices[0]](0),
2877  max_x = vertices[cells[0].vertices[0]](0),
2878  min_y = vertices[cells[0].vertices[0]](1),
2879  max_y = vertices[cells[0].vertices[0]](1);
2880 
2881  for (unsigned int i = 0; i < cells.size(); ++i)
2882  {
2883  for (unsigned int v = 0; v < 4; ++v)
2884  {
2885  const Point<2> &p = vertices[cells[i].vertices[v]];
2886 
2887  if (p(0) < min_x)
2888  min_x = p(0);
2889  if (p(0) > max_x)
2890  max_x = p(0);
2891  if (p(1) < min_y)
2892  min_y = p(1);
2893  if (p(1) > max_y)
2894  max_y = p(1);
2895  };
2896 
2897  out << "# cell " << i << std::endl;
2898  Point<2> center;
2899  for (unsigned int f = 0; f < 4; ++f)
2900  center += vertices[cells[i].vertices[f]];
2901  center /= 4;
2902 
2903  out << "set label \"" << i << "\" at " << center(0) << ',' << center(1)
2904  << " center" << std::endl;
2905 
2906  // first two line right direction
2907  for (unsigned int f = 0; f < 2; ++f)
2908  out << "set arrow from " << vertices[cells[i].vertices[f]](0) << ','
2909  << vertices[cells[i].vertices[f]](1) << " to "
2910  << vertices[cells[i].vertices[(f + 1) % 4]](0) << ','
2911  << vertices[cells[i].vertices[(f + 1) % 4]](1) << std::endl;
2912  // other two lines reverse direction
2913  for (unsigned int f = 2; f < 4; ++f)
2914  out << "set arrow from " << vertices[cells[i].vertices[(f + 1) % 4]](0)
2915  << ',' << vertices[cells[i].vertices[(f + 1) % 4]](1) << " to "
2916  << vertices[cells[i].vertices[f]](0) << ','
2917  << vertices[cells[i].vertices[f]](1) << std::endl;
2918  out << std::endl;
2919  };
2920 
2921 
2922  out << std::endl
2923  << "set nokey" << std::endl
2924  << "pl [" << min_x << ':' << max_x << "][" << min_y << ':' << max_y
2925  << "] " << min_y << std::endl
2926  << "pause -1" << std::endl;
2927 }
2928 
2929 
2930 
2931 template <>
2932 void
2933 GridIn<3>::debug_output_grid(const std::vector<CellData<3>> &cells,
2934  const std::vector<Point<3>> & vertices,
2935  std::ostream & out)
2936 {
2937  for (unsigned int cell = 0; cell < cells.size(); ++cell)
2938  {
2939  // line 0
2940  out << vertices[cells[cell].vertices[0]] << std::endl
2941  << vertices[cells[cell].vertices[1]] << std::endl
2942  << std::endl
2943  << std::endl;
2944  // line 1
2945  out << vertices[cells[cell].vertices[1]] << std::endl
2946  << vertices[cells[cell].vertices[2]] << std::endl
2947  << std::endl
2948  << std::endl;
2949  // line 2
2950  out << vertices[cells[cell].vertices[3]] << std::endl
2951  << vertices[cells[cell].vertices[2]] << std::endl
2952  << std::endl
2953  << std::endl;
2954  // line 3
2955  out << vertices[cells[cell].vertices[0]] << std::endl
2956  << vertices[cells[cell].vertices[3]] << std::endl
2957  << std::endl
2958  << std::endl;
2959  // line 4
2960  out << vertices[cells[cell].vertices[4]] << std::endl
2961  << vertices[cells[cell].vertices[5]] << std::endl
2962  << std::endl
2963  << std::endl;
2964  // line 5
2965  out << vertices[cells[cell].vertices[5]] << std::endl
2966  << vertices[cells[cell].vertices[6]] << std::endl
2967  << std::endl
2968  << std::endl;
2969  // line 6
2970  out << vertices[cells[cell].vertices[7]] << std::endl
2971  << vertices[cells[cell].vertices[6]] << std::endl
2972  << std::endl
2973  << std::endl;
2974  // line 7
2975  out << vertices[cells[cell].vertices[4]] << std::endl
2976  << vertices[cells[cell].vertices[7]] << std::endl
2977  << std::endl
2978  << std::endl;
2979  // line 8
2980  out << vertices[cells[cell].vertices[0]] << std::endl
2981  << vertices[cells[cell].vertices[4]] << std::endl
2982  << std::endl
2983  << std::endl;
2984  // line 9
2985  out << vertices[cells[cell].vertices[1]] << std::endl
2986  << vertices[cells[cell].vertices[5]] << std::endl
2987  << std::endl
2988  << std::endl;
2989  // line 10
2990  out << vertices[cells[cell].vertices[2]] << std::endl
2991  << vertices[cells[cell].vertices[6]] << std::endl
2992  << std::endl
2993  << std::endl;
2994  // line 11
2995  out << vertices[cells[cell].vertices[3]] << std::endl
2996  << vertices[cells[cell].vertices[7]] << std::endl
2997  << std::endl
2998  << std::endl;
2999  };
3000 }
3001 
3002 
3003 
3004 template <int dim, int spacedim>
3005 void
3006 GridIn<dim, spacedim>::read(const std::string &filename, Format format)
3007 {
3008  // Search file class for meshes
3009  PathSearch search("MESH");
3010  std::string name;
3011  // Open the file and remember its name
3012  if (format == Default)
3013  name = search.find(filename);
3014  else
3015  name = search.find(filename, default_suffix(format));
3016 
3017  std::ifstream in(name.c_str());
3018 
3019  if (format == Default)
3020  {
3021  const std::string::size_type slashpos = name.find_last_of('/');
3022  const std::string::size_type dotpos = name.find_last_of('.');
3023  if (dotpos < name.length() &&
3024  (dotpos > slashpos || slashpos == std::string::npos))
3025  {
3026  std::string ext = name.substr(dotpos + 1);
3027  format = parse_format(ext);
3028  }
3029  }
3030  if (format == netcdf)
3031  read_netcdf(filename);
3032  else
3033  read(in, format);
3034 }
3035 
3036 
3037 template <int dim, int spacedim>
3038 void
3039 GridIn<dim, spacedim>::read(std::istream &in, Format format)
3040 {
3041  if (format == Default)
3042  format = default_format;
3043 
3044  switch (format)
3045  {
3046  case dbmesh:
3047  read_dbmesh(in);
3048  return;
3049 
3050  case msh:
3051  read_msh(in);
3052  return;
3053 
3054  case vtk:
3055  read_vtk(in);
3056  return;
3057 
3058  case unv:
3059  read_unv(in);
3060  return;
3061 
3062  case ucd:
3063  read_ucd(in);
3064  return;
3065 
3066  case abaqus:
3067  read_abaqus(in);
3068  return;
3069 
3070  case xda:
3071  read_xda(in);
3072  return;
3073 
3074  case netcdf:
3075  Assert(false,
3076  ExcMessage("There is no read_netcdf(istream &) function. "
3077  "Use the read_netcdf(string &filename) "
3078  "functions, instead."));
3079  return;
3080 
3081  case tecplot:
3082  read_tecplot(in);
3083  return;
3084 
3085  case assimp:
3086  Assert(false,
3087  ExcMessage("There is no read_assimp(istream &) function. "
3088  "Use the read_assimp(string &filename, ...) "
3089  "functions, instead."));
3090  return;
3091 
3092  case Default:
3093  break;
3094  }
3095  Assert(false, ExcInternalError());
3096 }
3097 
3098 
3099 
3100 template <int dim, int spacedim>
3101 std::string
3103 {
3104  switch (format)
3105  {
3106  case dbmesh:
3107  return ".dbmesh";
3108  case msh:
3109  return ".msh";
3110  case vtk:
3111  return ".vtk";
3112  case unv:
3113  return ".unv";
3114  case ucd:
3115  return ".inp";
3116  case abaqus:
3117  return ".inp"; // Typical suffix for Abaqus mesh files conflicts with
3118  // UCD.
3119  case xda:
3120  return ".xda";
3121  case netcdf:
3122  return ".nc";
3123  case tecplot:
3124  return ".dat";
3125  default:
3126  Assert(false, ExcNotImplemented());
3127  return ".unknown_format";
3128  }
3129 }
3130 
3131 
3132 
3133 template <int dim, int spacedim>
3135 GridIn<dim, spacedim>::parse_format(const std::string &format_name)
3136 {
3137  if (format_name == "dbmesh")
3138  return dbmesh;
3139 
3140  if (format_name == "msh")
3141  return msh;
3142 
3143  if (format_name == "unv")
3144  return unv;
3145 
3146  if (format_name == "vtk")
3147  return vtk;
3148 
3149  // This is also the typical extension of Abaqus input files.
3150  if (format_name == "inp")
3151  return ucd;
3152 
3153  if (format_name == "ucd")
3154  return ucd;
3155 
3156  if (format_name == "xda")
3157  return xda;
3158 
3159  if (format_name == "netcdf")
3160  return netcdf;
3161 
3162  if (format_name == "nc")
3163  return netcdf;
3164 
3165  if (format_name == "tecplot")
3166  return tecplot;
3167 
3168  if (format_name == "dat")
3169  return tecplot;
3170 
3171  if (format_name == "plt")
3172  // Actually, this is the extension for the
3173  // tecplot binary format, which we do not
3174  // support right now. However, some people
3175  // tend to create tecplot ascii files with
3176  // the extension 'plt' instead of
3177  // 'dat'. Thus, include this extension
3178  // here. If it actually is a binary file,
3179  // the read_tecplot() function will fail
3180  // and throw an exception, anyway.
3181  return tecplot;
3182 
3183  AssertThrow(false, ExcInvalidState());
3184  // return something weird
3185  return Format(Default);
3186 }
3187 
3188 
3189 
3190 template <int dim, int spacedim>
3191 std::string
3193 {
3194  return "dbmesh|msh|unv|vtk|ucd|abaqus|xda|netcdf|tecplot|assimp";
3195 }
3196 
3197 namespace
3198 {
3199  template <int dim>
3200  Abaqus_to_UCD<dim>::Abaqus_to_UCD()
3201  : tolerance(5e-16) // Used to offset Cubit tolerance error when outputting
3202  // value close to zero
3203  {
3204  AssertThrow(dim == 2 || dim == 3, ExcNotImplemented());
3205  }
3206 
3207  // Convert from a string to some other data type
3208  // Reference: http://www.codeguru.com/forum/showthread.php?t=231054
3209  template <class T>
3210  bool
3211  from_string(T &t, const std::string &s, std::ios_base &(*f)(std::ios_base &))
3212  {
3213  std::istringstream iss(s);
3214  return !(iss >> f >> t).fail();
3215  }
3216 
3217  // Extract an integer from a string
3218  int
3219  extract_int(const std::string &s)
3220  {
3221  std::string tmp;
3222  for (unsigned int i = 0; i < s.size(); ++i)
3223  {
3224  if (isdigit(s[i]))
3225  {
3226  tmp += s[i];
3227  }
3228  }
3229 
3230  int number = 0;
3231  from_string(number, tmp, std::dec);
3232  return number;
3233  }
3234 
3235  template <int dim>
3236  void
3237  Abaqus_to_UCD<dim>::read_in_abaqus(std::istream &input_stream)
3238  {
3239  // References:
3240  // http://www.egr.msu.edu/software/abaqus/Documentation/docs/v6.7/books/usb/default.htm?startat=pt01ch02.html
3241  // http://www.cprogramming.com/tutorial/string.html
3242 
3243  AssertThrow(input_stream, ExcIO());
3244  std::string line;
3245  std::getline(input_stream, line);
3246 
3247  while (!input_stream.fail() && !input_stream.eof())
3248  {
3249  std::transform(line.begin(), line.end(), line.begin(), ::toupper);
3250 
3251  if (line.compare("*HEADING") == 0 || line.compare(0, 2, "**") == 0 ||
3252  line.compare(0, 5, "*PART") == 0)
3253  {
3254  // Skip header and comments
3255  while (!input_stream.fail() && !input_stream.eof())
3256  {
3257  std::getline(input_stream, line);
3258  if (line[0] == '*')
3259  goto cont; // My eyes, they burn!
3260  }
3261  }
3262  else if (line.compare(0, 5, "*NODE") == 0)
3263  {
3264  // Extract list of vertices
3265  // Header line might be:
3266  // *NODE, NSET=ALLNODES
3267  // *NODE
3268 
3269  // Contains lines in the form:
3270  // Index, x, y, z
3271  while (!input_stream.fail() && !input_stream.eof())
3272  {
3273  std::getline(input_stream, line);
3274  if (line[0] == '*')
3275  goto cont;
3276 
3277  std::vector<double> node(dim + 1);
3278 
3279  std::istringstream iss(line);
3280  char comma;
3281  for (unsigned int i = 0; i < dim + 1; ++i)
3282  iss >> node[i] >> comma;
3283 
3284  node_list.push_back(node);
3285  }
3286  }
3287  else if (line.compare(0, 8, "*ELEMENT") == 0)
3288  {
3289  // Element construction.
3290  // There are different header formats, the details
3291  // of which we're not particularly interested in except
3292  // whether they represent quads or hexahedrals.
3293  // *ELEMENT, TYPE=S4R, ELSET=EB<material id>
3294  // *ELEMENT, TYPE=C3D8R, ELSET=EB<material id>
3295  // *ELEMENT, TYPE=C3D8
3296  // Elements itself (n=4 or n=8):
3297  // Index, i[0], ..., i[n]
3298 
3299  int material = 0;
3300  // Scan for material id
3301  {
3302  const std::string before_material = "ELSET=EB";
3303  const std::size_t idx = line.find(before_material);
3304  if (idx != std::string::npos)
3305  {
3306  from_string(material,
3307  line.substr(idx + before_material.size()),
3308  std::dec);
3309  }
3310  }
3311 
3312  // Read ELEMENT definition
3313  std::getline(input_stream, line);
3314  while (!input_stream.fail() && !input_stream.eof())
3315  {
3316  if (line[0] == '*')
3317  goto cont;
3318 
3319  std::istringstream iss(line);
3320  char comma;
3321 
3322  // We will store the material id in the zeroth entry of the
3323  // vector and the rest of the elements represent the global
3324  // node numbers
3325  const unsigned int n_data_per_cell =
3327  std::vector<double> cell(n_data_per_cell);
3328  for (unsigned int i = 0; i < n_data_per_cell; ++i)
3329  iss >> cell[i] >> comma;
3330 
3331  // Overwrite cell index from file by material
3332  cell[0] = static_cast<double>(material);
3333  cell_list.push_back(cell);
3334 
3335  std::getline(input_stream, line);
3336  }
3337  }
3338  else if (line.compare(0, 8, "*SURFACE") == 0)
3339  {
3340  // Extract the definitions of boundary surfaces
3341  // Old format from Cubit:
3342  // *SURFACE, NAME=SS<boundary indicator>
3343  // <element index>, S<face number>
3344  // Abaqus default format:
3345  // *SURFACE, TYPE=ELEMENT, NAME=SURF-<indicator>
3346 
3347  // Get name of the surface and extract id from it;
3348  // this will be the boundary indicator
3349  const std::string name_key = "NAME=";
3350  const std::size_t name_idx_start =
3351  line.find(name_key) + name_key.size();
3352  std::size_t name_idx_end = line.find(',', name_idx_start);
3353  if (name_idx_end == std::string::npos)
3354  {
3355  name_idx_end = line.size();
3356  }
3357  const int b_indicator = extract_int(
3358  line.substr(name_idx_start, name_idx_end - name_idx_start));
3359 
3360  // Read SURFACE definition
3361  // Note that the orientation of the faces is embedded within the
3362  // definition of each "set" of faces that comprise the surface
3363  // These are either marked by an "S" or "E" in 3d or 2d
3364  // respectively.
3365  std::getline(input_stream, line);
3366  while (!input_stream.fail() && !input_stream.eof())
3367  {
3368  if (line[0] == '*')
3369  goto cont;
3370 
3371  // Change all characters to upper case
3372  std::transform(line.begin(),
3373  line.end(),
3374  line.begin(),
3375  ::toupper);
3376 
3377  // Surface can be created from ELSET, or directly from cells
3378  // If elsets_list contains a key with specific name - refers to
3379  // that ELSET, otherwise refers to cell
3380  std::istringstream iss(line);
3381  int el_idx;
3382  int face_number;
3383  char temp;
3384 
3385  // Get relevant faces, taking into account the element
3386  // orientation
3387  std::vector<double> quad_node_list;
3388  const std::string elset_name = line.substr(0, line.find(','));
3389  if (elsets_list.count(elset_name) != 0)
3390  {
3391  // Surface refers to ELSET
3392  std::string stmp;
3393  iss >> stmp >> temp >> face_number;
3394 
3395  const std::vector<int> cells = elsets_list[elset_name];
3396  for (unsigned int i = 0; i < cells.size(); ++i)
3397  {
3398  el_idx = cells[i];
3399  quad_node_list =
3400  get_global_node_numbers(el_idx, face_number);
3401  quad_node_list.insert(quad_node_list.begin(),
3402  b_indicator);
3403 
3404  face_list.push_back(quad_node_list);
3405  }
3406  }
3407  else
3408  {
3409  // Surface refers directly to elements
3410  char comma;
3411  iss >> el_idx >> comma >> temp >> face_number;
3412  quad_node_list =
3413  get_global_node_numbers(el_idx, face_number);
3414  quad_node_list.insert(quad_node_list.begin(), b_indicator);
3415 
3416  face_list.push_back(quad_node_list);
3417  }
3418 
3419  std::getline(input_stream, line);
3420  }
3421  }
3422  else if (line.compare(0, 6, "*ELSET") == 0)
3423  {
3424  // Get ELSET name.
3425  // Materials are attached to elsets with specific name
3426  std::string elset_name;
3427  {
3428  const std::string elset_key = "*ELSET, ELSET=";
3429  const std::size_t idx = line.find(elset_key);
3430  if (idx != std::string::npos)
3431  {
3432  const std::string comma = ",";
3433  const std::size_t first_comma = line.find(comma);
3434  const std::size_t second_comma =
3435  line.find(comma, first_comma + 1);
3436  const std::size_t elset_name_start =
3437  line.find(elset_key) + elset_key.size();
3438  elset_name = line.substr(elset_name_start,
3439  second_comma - elset_name_start);
3440  }
3441  }
3442 
3443  // There are two possibilities of storing cells numbers in ELSET:
3444  // 1. If the header contains the 'GENERATE' keyword, then the next
3445  // line describes range of cells as:
3446  // cell_id_start, cell_id_end, cell_step
3447  // 2. If the header does not contain the 'GENERATE' keyword, then
3448  // the next lines contain cells numbers
3449  std::vector<int> elements;
3450  const std::size_t generate_idx = line.find("GENERATE");
3451  if (generate_idx != std::string::npos)
3452  {
3453  // Option (1)
3454  std::getline(input_stream, line);
3455  std::istringstream iss(line);
3456  char comma;
3457  int elid_start;
3458  int elid_end;
3459  int elis_step =
3460  1; // Default value set in case stride not provided
3461  // Some files don't have the stride size
3462  // Compare mesh test cases ./grids/abaqus/3d/other_simple.inp to
3463  // ./grids/abaqus/2d/2d_test_abaqus.inp
3464  iss >> elid_start >> comma >> elid_end;
3465  // https://stackoverflow.com/questions/8046357/how-do-i-check-if-a-stringstream-variable-is-empty-null
3466  if (iss.rdbuf()->in_avail() != 0)
3467  iss >> comma >> elis_step;
3468  for (int i = elid_start; i <= elid_end; i += elis_step)
3469  {
3470  elements.push_back(i);
3471  }
3472  elsets_list[elset_name] = elements;
3473 
3474  std::getline(input_stream, line);
3475  }
3476  else
3477  {
3478  // Option (2)
3479  std::getline(input_stream, line);
3480  while (!input_stream.fail() && !input_stream.eof())
3481  {
3482  if (line[0] == '*')
3483  break;
3484 
3485  std::istringstream iss(line);
3486  char comma;
3487  int elid;
3488  while (!iss.eof())
3489  {
3490  iss >> elid >> comma;
3491  elements.push_back(elid);
3492  }
3493 
3494  std::getline(input_stream, line);
3495  }
3496 
3497  elsets_list[elset_name] = elements;
3498  }
3499 
3500  goto cont;
3501  }
3502  else if (line.compare(0, 5, "*NSET") == 0)
3503  {
3504  // Skip nodesets; we have no use for them
3505  while (!input_stream.fail() && !input_stream.eof())
3506  {
3507  std::getline(input_stream, line);
3508  if (line[0] == '*')
3509  goto cont;
3510  }
3511  }
3512  else if (line.compare(0, 14, "*SOLID SECTION") == 0)
3513  {
3514  // The ELSET name, which describes a section for particular material
3515  const std::string elset_key = "ELSET=";
3516  const std::size_t elset_start =
3517  line.find("ELSET=") + elset_key.size();
3518  const std::size_t elset_end = line.find(',', elset_start + 1);
3519  const std::string elset_name =
3520  line.substr(elset_start, elset_end - elset_start);
3521 
3522  // Solid material definition.
3523  // We assume that material id is taken from material name,
3524  // eg. "Material-1" -> ID=1
3525  const std::string material_key = "MATERIAL=";
3526  const std::size_t last_equal =
3527  line.find("MATERIAL=") + material_key.size();
3528  const std::size_t material_id_start = line.find('-', last_equal);
3529  int material_id = 0;
3530  from_string(material_id,
3531  line.substr(material_id_start + 1),
3532  std::dec);
3533 
3534  // Assign material id to cells
3535  const std::vector<int> &elset_cells = elsets_list[elset_name];
3536  for (unsigned int i = 0; i < elset_cells.size(); ++i)
3537  {
3538  const int cell_id = elset_cells[i] - 1;
3539  cell_list[cell_id][0] = material_id;
3540  }
3541  }
3542  // Note: All other lines / entries are ignored
3543 
3544  std::getline(input_stream, line);
3545 
3546  cont:
3547  (void)0;
3548  }
3549  }
3550 
3551  template <int dim>
3552  std::vector<double>
3553  Abaqus_to_UCD<dim>::get_global_node_numbers(const int face_cell_no,
3554  const int face_cell_face_no) const
3555  {
3556  std::vector<double> quad_node_list(GeometryInfo<dim>::vertices_per_face);
3557 
3558  // These orderings were reverse engineered by hand and may
3559  // conceivably be erroneous.
3560  // TODO: Currently one test (2d unstructured mesh) in the test
3561  // suite fails, presumably because of an ordering issue.
3562  if (dim == 2)
3563  {
3564  if (face_cell_face_no == 1)
3565  {
3566  quad_node_list[0] = cell_list[face_cell_no - 1][1];
3567  quad_node_list[1] = cell_list[face_cell_no - 1][2];
3568  }
3569  else if (face_cell_face_no == 2)
3570  {
3571  quad_node_list[0] = cell_list[face_cell_no - 1][2];
3572  quad_node_list[1] = cell_list[face_cell_no - 1][3];
3573  }
3574  else if (face_cell_face_no == 3)
3575  {
3576  quad_node_list[0] = cell_list[face_cell_no - 1][3];
3577  quad_node_list[1] = cell_list[face_cell_no - 1][4];
3578  }
3579  else if (face_cell_face_no == 4)
3580  {
3581  quad_node_list[0] = cell_list[face_cell_no - 1][4];
3582  quad_node_list[1] = cell_list[face_cell_no - 1][1];
3583  }
3584  else
3585  {
3586  AssertThrow(face_cell_face_no <= 4,
3587  ExcMessage("Invalid face number in 2d"));
3588  }
3589  }
3590  else if (dim == 3)
3591  {
3592  if (face_cell_face_no == 1)
3593  {
3594  quad_node_list[0] = cell_list[face_cell_no - 1][1];
3595  quad_node_list[1] = cell_list[face_cell_no - 1][4];
3596  quad_node_list[2] = cell_list[face_cell_no - 1][3];
3597  quad_node_list[3] = cell_list[face_cell_no - 1][2];
3598  }
3599  else if (face_cell_face_no == 2)
3600  {
3601  quad_node_list[0] = cell_list[face_cell_no - 1][5];
3602  quad_node_list[1] = cell_list[face_cell_no - 1][8];
3603  quad_node_list[2] = cell_list[face_cell_no - 1][7];
3604  quad_node_list[3] = cell_list[face_cell_no - 1][6];
3605  }
3606  else if (face_cell_face_no == 3)
3607  {
3608  quad_node_list[0] = cell_list[face_cell_no - 1][1];
3609  quad_node_list[1] = cell_list[face_cell_no - 1][2];
3610  quad_node_list[2] = cell_list[face_cell_no - 1][6];
3611  quad_node_list[3] = cell_list[face_cell_no - 1][5];
3612  }
3613  else if (face_cell_face_no == 4)
3614  {
3615  quad_node_list[0] = cell_list[face_cell_no - 1][2];
3616  quad_node_list[1] = cell_list[face_cell_no - 1][3];
3617  quad_node_list[2] = cell_list[face_cell_no - 1][7];
3618  quad_node_list[3] = cell_list[face_cell_no - 1][6];
3619  }
3620  else if (face_cell_face_no == 5)
3621  {
3622  quad_node_list[0] = cell_list[face_cell_no - 1][3];
3623  quad_node_list[1] = cell_list[face_cell_no - 1][4];
3624  quad_node_list[2] = cell_list[face_cell_no - 1][8];
3625  quad_node_list[3] = cell_list[face_cell_no - 1][7];
3626  }
3627  else if (face_cell_face_no == 6)
3628  {
3629  quad_node_list[0] = cell_list[face_cell_no - 1][1];
3630  quad_node_list[1] = cell_list[face_cell_no - 1][5];
3631  quad_node_list[2] = cell_list[face_cell_no - 1][8];
3632  quad_node_list[3] = cell_list[face_cell_no - 1][4];
3633  }
3634  else
3635  {
3636  AssertThrow(face_cell_no <= 6,
3637  ExcMessage("Invalid face number in 3d"));
3638  }
3639  }
3640  else
3641  {
3642  AssertThrow(dim == 2 || dim == 3, ExcNotImplemented());
3643  }
3644 
3645  return quad_node_list;
3646  }
3647 
3648  template <int dim>
3649  void
3650  Abaqus_to_UCD<dim>::write_out_avs_ucd(std::ostream &output) const
3651  {
3652  // References:
3653  // http://www.dealii.org/developer/doxygen/deal.II/structGeometryInfo.html
3654  // http://people.scs.fsu.edu/~burkardt/data/ucd/ucd.html
3655 
3656  AssertThrow(output, ExcIO());
3657 
3658  // save old formatting options
3659  const boost::io::ios_base_all_saver formatting_saver(output);
3660 
3661  // Write out title - Note: No other commented text can be inserted below the
3662  // title in a UCD file
3663  output << "# Abaqus to UCD mesh conversion" << std::endl;
3664  output << "# Mesh type: AVS UCD" << std::endl;
3665 
3666  // ========================================================
3667  // ASCII UCD File Format
3668  // The input file cannot contain blank lines or lines with leading blanks.
3669  // Comments, if present, must precede all data in the file.
3670  // Comments within the data will cause read errors.
3671  // The general order of the data is as follows:
3672  // 1. Numbers defining the overall structure, including the number of nodes,
3673  // the number of cells, and the length of the vector of data associated
3674  // with the nodes, cells, and the model.
3675  // e.g. 1:
3676  // <num_nodes> <num_cells> <num_ndata> <num_cdata> <num_mdata>
3677  // e.g. 2:
3678  // n_elements = n_hex_cells + n_bc_quads + n_quad_cells + n_bc_edges
3679  // outfile.write(str(n_nodes) + " " + str(n_elements) + " 0 0 0\n")
3680  // 2. For each node, its node id and the coordinates of that node in space.
3681  // Node-ids must be integers, but any number including non sequential
3682  // numbers can be used. Mid-edge nodes are treated like any other node.
3683  // 3. For each cell: its cell-id, material, cell type (hexahedral, pyramid,
3684  // etc.), and the list of node-ids that correspond to each of the cell's
3685  // vertices. The below table specifies the different cell types and the
3686  // keyword used to represent them in the file.
3687 
3688  // Write out header
3689  output << node_list.size() << "\t" << (cell_list.size() + face_list.size())
3690  << "\t0\t0\t0" << std::endl;
3691 
3692  output.width(16);
3693  output.precision(8);
3694 
3695  // Write out node numbers
3696  // Loop over all nodes
3697  for (unsigned int ii = 0; ii < node_list.size(); ++ii)
3698  {
3699  // Node number
3700  output << node_list[ii][0] << "\t";
3701 
3702  // Node coordinates
3703  output.setf(std::ios::scientific, std::ios::floatfield);
3704  for (unsigned int jj = 1; jj < dim + 1; ++jj)
3705  {
3706  // invoke tolerance -> set points close to zero equal to zero
3707  if (std::abs(node_list[ii][jj]) > tolerance)
3708  output << static_cast<double>(node_list[ii][jj]) << "\t";
3709  else
3710  output << 0.0 << "\t";
3711  }
3712  if (dim == 2)
3713  output << 0.0 << "\t";
3714 
3715  output << std::endl;
3716  output.unsetf(std::ios::floatfield);
3717  }
3718 
3719  // Write out cell node numbers
3720  for (unsigned int ii = 0; ii < cell_list.size(); ++ii)
3721  {
3722  output << ii + 1 << "\t" << cell_list[ii][0] << "\t"
3723  << (dim == 2 ? "quad" : "hex") << "\t";
3724  for (unsigned int jj = 1; jj < GeometryInfo<dim>::vertices_per_cell + 1;
3725  ++jj)
3726  output << cell_list[ii][jj] << "\t";
3727 
3728  output << std::endl;
3729  }
3730 
3731  // Write out quad node numbers
3732  for (unsigned int ii = 0; ii < face_list.size(); ++ii)
3733  {
3734  output << ii + 1 << "\t" << face_list[ii][0] << "\t"
3735  << (dim == 2 ? "line" : "quad") << "\t";
3736  for (unsigned int jj = 1; jj < GeometryInfo<dim>::vertices_per_face + 1;
3737  ++jj)
3738  output << face_list[ii][jj] << "\t";
3739 
3740  output << std::endl;
3741  }
3742  }
3743 } // namespace
3744 
3745 
3746 // explicit instantiations
3747 #include "grid_in.inst"
3748 
3749 DEAL_II_NAMESPACE_CLOSE
std::vector< CellData< 1 > > boundary_lines
Definition: tria.h:258
static std::string get_format_names()
Definition: grid_in.cc:3192
static void reorder_cells(std::vector< CellData< dim >> &original_cells, const bool use_new_style_ordering=false)
static const unsigned int invalid_unsigned_int
Definition: types.h:173
unsigned int manifold_id
Definition: types.h:123
cell_iterator end() const
Definition: tria.cc:12004
Use read_abaqus()
Definition: grid_in.h:320
static::ExceptionBase & ExcIO()
bool check_consistency(const unsigned int dim) const
Definition: tria.cc:48
Format
Definition: grid_in.h:311
std::pair< int, unsigned int > get_integer_at_position(const std::string &name, const unsigned int position)
Definition: utilities.cc:428
Use read_vtk()
Definition: grid_in.h:332
static::ExceptionBase & ExcUnknownElementType(int arg1)
Use read_unv()
Definition: grid_in.h:316
Use read_xda()
Definition: grid_in.h:324
unsigned int material_id
Definition: types.h:134
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
static::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
static Format parse_format(const std::string &format_name)
Definition: grid_in.cc:3135
static void skip_empty_lines(std::istream &in)
Definition: grid_in.cc:2802
void read_vtk(std::istream &in)
Definition: grid_in.cc:114
static::ExceptionBase & ExcDBMESHWrongDimension(int arg1)
void delete_unused_vertices(std::vector< Point< spacedim >> &vertices, std::vector< CellData< dim >> &cells, SubCellData &subcelldata)
Definition: grid_tools.cc:434
Use read_ucd()
Definition: grid_in.h:318
void read_dbmesh(std::istream &in)
Definition: grid_in.cc:978
void read_tecplot(std::istream &in)
Definition: grid_in.cc:2635
static::ExceptionBase & ExcInvalidState()
static::ExceptionBase & ExcMessage(std::string arg1)
static::ExceptionBase & ExcImpossibleInDim(int arg1)
static void parse_tecplot_header(std::string &header, std::vector< unsigned int > &tecplot2deal, unsigned int &n_vars, unsigned int &n_vertices, unsigned int &n_cells, std::vector< unsigned int > &IJK, bool &structured, bool &blocked)
Definition: grid_in.cc:2159
static::ExceptionBase & ExcNeedsNetCDF()
static::ExceptionBase & ExcInvalidVertexIndexGmsh(int arg1, int arg2, int arg3)
#define Assert(cond, exc)
Definition: exceptions.h:1227
SmartPointer< Triangulation< dim, spacedim >, GridIn< dim, spacedim > > tria
Definition: grid_in.h:635
Use read_msh()
Definition: grid_in.h:326
static void skip_comment_lines(std::istream &in, const char comment_start)
Definition: grid_in.cc:2834
bool match_at_string_start(const std::string &name, const std::string &pattern)
Definition: utilities.cc:413
void read_ucd(std::istream &in, const bool apply_all_indicators_to_manifolds=false)
Definition: grid_in.cc:669
static::ExceptionBase & ExcNeedsAssimp()
static::ExceptionBase & ExcInvalidDBMESHInput(std::string arg1)
GridIn()
Definition: grid_in.cc:97
static void debug_output_grid(const std::vector< CellData< dim >> &cells, const std::vector< Point< spacedim >> &vertices, std::ostream &out)
Definition: grid_in.cc:2860
Use read_tecplot()
Definition: grid_in.h:330
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:96
static::ExceptionBase & ExcUnknownIdentifier(std::string arg1)
std::string find(const std::string &filename, const char *open_mode="r")
Definition: path_search.cc:171
void read_xda(std::istream &in)
Definition: grid_in.cc:1145
void read_msh(std::istream &in)
Definition: grid_in.cc:1303
std::vector< std::string > break_text_into_lines(const std::string &original_text, const unsigned int width, const char delimiter= ' ')
Definition: utilities.cc:333
std::vector< CellData< 2 > > boundary_quads
Definition: tria.h:266
Use read_dbmesh()
Definition: grid_in.h:322
void read_netcdf(const std::string &filename)
static std::string default_suffix(const Format format)
Definition: grid_in.cc:3102
void read_unv(std::istream &in)
Definition: grid_in.cc:420
void read(std::istream &in, Format format=Default)
Definition: grid_in.cc:3039
static::ExceptionBase & ExcNoTriangulationSelected()
static::ExceptionBase & ExcNotImplemented()
static::ExceptionBase & ExcInvalidDBMeshFormat()
static void invert_all_cells_of_negative_grid(const std::vector< Point< spacedim >> &all_vertices, std::vector< CellData< dim >> &original_cells)
const types::boundary_id internal_face_boundary_id
Definition: types.h:223
void read_assimp(const std::string &filename, const unsigned int mesh_index=numbers::invalid_unsigned_int, const bool remove_duplicates=true, const double tol=1e-12, const bool ignore_unsupported_element_types=true)
Definition: grid_in.cc:2644
Use GridIn::default_format stored in this object.
Definition: grid_in.h:314
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: tria.cc:11935
void read_abaqus(std::istream &in, const bool apply_all_indicators_to_manifolds=false)
Definition: grid_in.cc:928
static::ExceptionBase & ExcInvalidGMSHInput(std::string arg1)
static::ExceptionBase & ExcGmshUnsupportedGeometry(int arg1)
const types::material_id invalid_material_id
Definition: types.h:196
static::ExceptionBase & ExcUnknownSectionType(int arg1)
void attach_triangulation(Triangulation< dim, spacedim > &tria)
Definition: grid_in.cc:105
Use read_netcdf()
Definition: grid_in.h:328
unsigned int boundary_id
Definition: types.h:111
static::ExceptionBase & ExcInvalidVertexIndex(int arg1, int arg2)
Use read_assimp()
Definition: grid_in.h:334
Format default_format
Definition: grid_in.h:700
static::ExceptionBase & ExcGmshNoCellInformation()
static::ExceptionBase & ExcInternalError()
void delete_duplicated_vertices(std::vector< Point< spacedim >> &all_vertices, std::vector< CellData< dim >> &cells, SubCellData &subcelldata, std::vector< unsigned int > &considered_vertices, const double tol=1e-12)
Definition: grid_tools.cc:533