libMesh
exodusII_io_helper.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2017 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 #ifndef LIBMESH_EXODUSII_IO_HELPER_H
19 #define LIBMESH_EXODUSII_IO_HELPER_H
20 
21 #include "libmesh/libmesh_config.h"
22 
23 #ifdef LIBMESH_HAVE_EXODUS_API
24 
25 // Local includes
26 #include "libmesh/parallel_object.h"
27 #include "libmesh/point.h"
28 #include "libmesh/enum_elem_type.h"
29 
30 // C++ includes
31 #include <iostream>
32 #include <string>
33 #include <vector>
34 #include <map>
35 
36 // Macros to simplify checking Exodus error codes
37 #define EX_CHECK_ERR(code, msg) \
38  do { \
39  if ((code) < 0) { \
40  libmesh_error_msg((msg)); \
41  } } while (0)
42 
43 #define EX_EXCEPTIONLESS_CHECK_ERR(code, msg) \
44  do { \
45  if ((code) < 0) { \
46  libMesh::err << (msg) << std::endl; \
47  libmesh_exceptionless_error(); \
48  } } while (0)
49 
50 
51 
52 // Through several subsequent levels of includes, the exodusII.h
53 // header includes <errno.h>. On very specific system/compiler combinations
54 // (currently GCC 5.2.0+ OSX Yosemite, El Capitan, possibly others) errno.h
55 // cannot be included while wrapped in a namespace (as we do with the exII
56 // namespace below). A workaround for this is to simply include errno.h
57 // not in any namespace prior to including exodusII.h.
58 //
59 // The same is also true for string.h.
60 #ifdef LIBMESH_COMPILER_HAS_BROKEN_ERRNO_T
61 #include <errno.h>
62 #include <string.h>
63 #endif
64 
65 
66 namespace exII {
67 extern "C" {
68 #include "exodusII.h" // defines MAX_LINE_LENGTH, MAX_STR_LENGTH used later
69 }
70 }
71 
72 namespace libMesh
73 {
74 
75 // Forward declarations
76 class MeshBase;
77 
87 {
88 public:
96  ExodusII_IO_Helper(const ParallelObject & parent,
97  bool v=false,
98  bool run_only_on_proc0=true,
99  bool single_precision=false);
103  virtual ~ExodusII_IO_Helper();
104 
111  const char * get_elem_type() const;
112 
118  void open(const char * filename, bool read_only);
119 
123  void read_header();
124 
130  void read_qa_records();
131 
137  void print_header();
138 
143  void read_nodes();
144 
149  void read_node_num_map();
150 
154  void print_nodes(std::ostream & out = libMesh::out);
155 
160  void read_block_info();
161 
165  int get_block_id(int index);
166 
171  std::string get_block_name(int index);
172 
176  int get_side_set_id(int index);
177 
182  std::string get_side_set_name(int index);
183 
187  int get_node_set_id(int index);
188 
193  std::string get_node_set_name(int index);
194 
199  void read_elem_in_block(int block);
200 
205  void read_elem_num_map();
206 
211  void read_sideset_info();
212 
217  void read_nodeset_info();
218 
223  void read_sideset(int id, int offset);
224 
229  void read_nodeset(int id);
230 
234  void close();
235 
239  int inquire(int req_info, std::string error_msg="");
240 
244  void read_time_steps();
245 
250  void read_num_time_steps();
251 
256  void read_nodal_var_values(std::string nodal_var_name, int time_step);
257 
262  void read_elemental_var_values(std::string elemental_var_name,
263  int time_step,
264  std::map<dof_id_type, Real> & elem_var_value_map);
265 
269  virtual void create(std::string filename);
270 
274  virtual void initialize(std::string title, const MeshBase & mesh, bool use_discontinuous=false);
275 
279  virtual void write_nodal_coordinates(const MeshBase & mesh, bool use_discontinuous=false);
280 
285  virtual void write_elements(const MeshBase & mesh, bool use_discontinuous=false);
286 
290  virtual void write_sidesets(const MeshBase & mesh);
291 
295  virtual void write_nodesets(const MeshBase & mesh);
296 
300  void initialize_element_variables(std::vector<std::string> names);
301 
305  void initialize_nodal_variables(std::vector<std::string> names);
306 
310  void initialize_global_variables(std::vector<std::string> names);
311 
315  void write_timestep(int timestep, Real time);
316 
320  void write_element_values(const MeshBase & mesh, const std::vector<Real> & values, int timestep);
321 
325  void write_nodal_values(int var_id, const std::vector<Real> & values, int timestep);
326 
330  void write_information_records(const std::vector<std::string> & records);
331 
335  void write_global_values(const std::vector<Real> & values, int timestep);
336 
345  void use_mesh_dimension_instead_of_spatial_dimension(bool val);
346 
359  void write_as_dimension(unsigned dim);
360 
365  void set_coordinate_offset(Point p);
366 
371  std::vector<std::string> get_complex_names(const std::vector<std::string> & names) const;
372 
378  class Conversion;
379 
386  class ElementMaps;
387 
393  class NamesData;
394 
399  void message(const std::string & msg);
400 
406  void message(const std::string & msg, int i);
407 
408  // File identification flag
409  int ex_id;
410 
411  // General error flag
412  int ex_err;
413 
414  // Number of dimensions in the mesh
415  int num_dim;
416 
417  // Number of global variables
419 
420  // Total number of nodes in the mesh
422 
423  // Total number of elements in the mesh
424  int num_elem;
425 
426  // Total number of element blocks
428 
429  // Total number of node sets
431 
432  // Total number of element sets
434 
435  // Number of elements in this block
437 
438  // Number of nodes in each element
440 
441  // Number of attributes for a given block
442  int num_attr;
443 
444  // Total number of elements in all side sets
446 
447  // Vector of the block identification numbers
448  std::vector<int> block_ids;
449 
450  // Vector of nodes in an element
451  std::vector<int> connect;
452 
453  // Vector of the sideset IDs
454  std::vector<int> ss_ids;
455 
456  // Vector of the nodeset IDs
457  std::vector<int> nodeset_ids;
458 
459  // Number of sides (edges/faces) in current set
460  std::vector<int> num_sides_per_set;
461 
462  // Number of nodes in current set
463  std::vector<int> num_nodes_per_set;
464 
465  // Number of distribution factors per set
466  std::vector<int> num_df_per_set;
467 
468  // Number of distribution factors per set
469  std::vector<int> num_node_df_per_set;
470 
471  // List of element numbers in all sidesets
472  std::vector<int> elem_list;
473 
474  // Side (face/edge) number actually on the boundary
475  std::vector<int> side_list;
476 
477  // Node number actually on the boundary
478  std::vector<int> node_list;
479 
480  // Side (face/edge) id number
481  std::vector<int> id_list;
482 
483  // Optional mapping from internal [0,num_nodes) to arbitrary indices
484  std::vector<int> node_num_map;
485 
486  // Optional mapping from internal [0,num_elem) to arbitrary indices
487  std::vector<int> elem_num_map;
488 
489  // x locations of node points
490  std::vector<Real> x;
491 
492  // y locations of node points
493  std::vector<Real> y;
494 
495  // z locations of node points
496  std::vector<Real> z;
497 
498  // Problem title (Use vector<char> to emulate a char *)
499  std::vector<char> title;
500 
501  // Type of element in a given block
502  std::vector<char> elem_type;
503 
504  // Maps libMesh element numbers to Exodus element numbers
505  // gets filled in when write_elements gets called
506  std::map<int, int> libmesh_elem_num_to_exodus;
507  std::vector<int> exodus_elem_num_to_libmesh;
508 
509  // Map of all node numbers connected to local node numbers to their exodus numbering.
510  // The exodus numbers are stored in here starting with 1
511  std::map<int, int> libmesh_node_num_to_exodus;
512  std::vector<int> exodus_node_num_to_libmesh;
513 
514  // The number of timesteps in the file, as returned by ex_inquire
516 
517  // The timesteps stored in the solution file, filled by read_time_steps()
518  std::vector<Real> time_steps;
519 
520  // The number of nodal variables in the Exodus file
522 
523  // The names of the nodal variables stored in the Exodus file
524  std::vector<std::string> nodal_var_names;
525 
526  // Holds the nodal variable values for a given variable, one value per node
527  std::vector<Real> nodal_var_values;
528 
529  // The number of elemental variables in the Exodus file
531 
532  // The names of the elemental variables stored in the Exodus file
533  std::vector<std::string> elem_var_names;
534 
535  // Holds the elemental variable values for a given variable, one value per element
536  std::vector<Real> elem_var_values;
537 
538  // The names of the global variables stored in the Exodus file
539  std::vector<std::string> global_var_names;
540 
541  // Maps of Ids to named entities
542  std::map<int, std::string> id_to_block_names;
543  std::map<int, std::string> id_to_ss_names;
544  std::map<int, std::string> id_to_ns_names;
545 
546  // On/Off message flag
547  bool verbose;
548 
549  // This flag gets set after the Exodus file has been successfully opened for writing.
550  // Both the create() and open() (if called with EX_WRITE) functions may set this flag.
552 
553  // This flag gets set after the open() function has been successfully called.
554  // We call open() to open an ExodusII file for reading.
556 
557  // When either create() or open() is called, the Helper stores the
558  // name of the opened file as current_filename. This way, the
559  // ExodusII_IO object can check to see if, on subsequent writes, the
560  // user is asking to write to a *different* filename from the one
561  // that is currently open, and signal an error. The current
562  // ExodusII_IO implementation is designed to work with a single file
563  // only, so if you want to write to multiple Exodus files, use a
564  // different ExodusII_IO object for each one.
565  std::string current_filename;
566 
575  enum ExodusVarType {NODAL=0, ELEMENTAL=1, GLOBAL=2};
576  void read_var_names(ExodusVarType type);
577 
578 protected:
579  // If true, whenever there is an I/O operation, only perform if if we are on processor 0.
581 
582  // True once the elem vars are initialized
584 
585  // True once the global vars are initialized
587 
588  // True once the nodal vars are initialized
590 
591  // If true, use the Mesh's dimension (as determined by the dimension
592  // of the elements comprising the mesh) instead of the mesh's
593  // spatial dimension, when writing. By default this is false.
595 
596  // Use this for num_dim when writing the Exodus file. If non-zero, supersedes
597  // any value set in _use_mesh_dimension_instead_of_spatial_dimension.
599 
600  // On output, shift every point by _coordinate_offset
602 
603  // If true, forces single precision I/O
605 
606 private:
607 
613  void write_var_names(ExodusVarType type, std::vector<std::string> & names);
614 
619  void check_existing_vars(ExodusVarType type, std::vector<std::string> & names, std::vector<std::string> & names_from_file);
620 
624  void read_var_names_impl(const char * var_type,
625  int & count,
626  std::vector<std::string> & result);
627 
631  void write_var_names_impl(const char * var_type,
632  int & count,
633  std::vector<std::string> & names);
634 };
635 
636 
637 
638 
639 
640 
641 
642 
644 {
645 public:
646 
651  Conversion(const int * nm, // node_map
652  size_t nm_size,
653  const int * inm, // inverse_node_map
654  size_t inm_size,
655  const int * sm, // side_map
656  size_t sm_size,
657  const int * ism, // inverse_side_map
658  size_t ism_size,
659  const ElemType ct, // "canonical" aka libmesh element type
660  std::string ex_type) // string representing the Exodus element type
661  : node_map(nm),
662  node_map_size(nm_size),
663  inverse_node_map(inm),
664  inverse_node_map_size(inm_size),
665  side_map(sm),
666  side_map_size(sm_size),
667  inverse_side_map(ism),
668  inverse_side_map_size(ism_size),
669  shellface_map(libmesh_nullptr),
670  shellface_map_size(0),
671  inverse_shellface_map(libmesh_nullptr),
672  inverse_shellface_map_size(0),
673  shellface_index_offset(0),
674  canonical_type(ct),
675  exodus_type(ex_type)
676  {}
677 
682  Conversion(const int * nm, // node_map
683  size_t nm_size,
684  const int * inm, // inverse_node_map
685  size_t inm_size,
686  const int * sm, // side_map
687  size_t sm_size,
688  const int * ism, // inverse_side_map
689  size_t ism_size,
690  const int * sfm, // shellface_map
691  size_t sfm_size,
692  const int * isfm, // inverse_shellface_map
693  size_t isfm_size,
694  size_t sfi_offset,
695  const ElemType ct, // "canonical" aka libmesh element type
696  std::string ex_type) // string representing the Exodus element type
697  : node_map(nm),
698  node_map_size(nm_size),
699  inverse_node_map(inm),
700  inverse_node_map_size(inm_size),
701  side_map(sm),
702  side_map_size(sm_size),
703  inverse_side_map(ism),
704  inverse_side_map_size(ism_size),
705  shellface_map(sfm),
706  shellface_map_size(sfm_size),
707  inverse_shellface_map(isfm),
708  inverse_shellface_map_size(isfm_size),
709  shellface_index_offset(sfi_offset),
710  canonical_type(ct),
711  exodus_type(ex_type)
712  {}
713 
720  int get_node_map(int i) const
721  {
722  libmesh_assert_less (static_cast<size_t>(i), node_map_size);
723  return node_map[i];
724  }
725 
736  int get_inverse_node_map(int i) const
737  {
738  libmesh_assert_less (static_cast<size_t>(i), inverse_node_map_size);
739  return inverse_node_map[i];
740  }
741 
748  int get_side_map(int i) const;
749 
756  int get_inverse_side_map(int i) const
757  {
758  libmesh_assert_less (static_cast<size_t>(i), inverse_side_map_size);
759  return inverse_side_map[i];
760  }
761 
765  int get_inverse_shellface_map(int i) const
766  {
767  libmesh_assert_less (static_cast<size_t>(i), inverse_shellface_map_size);
768  return inverse_shellface_map[i];
769  }
770 
777  ElemType get_canonical_type() const { return canonical_type; }
778 
782  std::string exodus_elem_type() const { return exodus_type; }
783 
787  int get_shellface_index_offset() const { return shellface_index_offset; }
788 
793  static const int invalid_id;
794 
795 private:
799  const int * node_map;
800 
805 
811  const int * inverse_node_map;
812 
817 
821  const int * side_map;
822 
827 
831  const int * inverse_side_map;
832 
837 
841  const int * shellface_map;
842 
847 
852 
857 
864 
870 
874  const std::string exodus_type;
875 };
876 
877 
878 
879 
880 
881 
883 {
884 public:
885 
893 
894 public:
895 
904  static const int nodeelem_node_map[1];
905 
914  static const int edge2_node_map[2];
915 
919  static const int edge3_node_map[3];
920 
924  // FIXME: This notion may or may not be defined in ExodusII
925 
930  static const int edge_edge_map[2];
931 
936  static const int edge_inverse_edge_map[2];
937 
947  static const int quad4_node_map[4];
948 
953  static const int quad8_node_map[8];
954 
959  static const int quad9_node_map[9];
960 
964  static const int tri3_node_map[3];
965 
970  static const int tri6_node_map[6];
971 
980  static const int tri_edge_map[3];
981 
988  static const int trishell3_edge_map[3];
989  static const int trishell3_inverse_edge_map[3];
990 
995  static const int quad_edge_map[4];
996 
1003  static const int quadshell4_edge_map[4];
1004  static const int quadshell4_inverse_edge_map[4];
1005 
1010  static const int tri_inverse_edge_map[3];
1011 
1016  static const int quad_inverse_edge_map[4];
1017 
1027  static const int hex8_node_map[8];
1028 
1033  static const int hex20_node_map[20];
1034 
1039  static const int hex27_node_map[27];
1040 
1045  static const int hex27_inverse_node_map[27];
1046 
1051  static const int tet4_node_map[4];
1052 
1057  static const int tet10_node_map[10];
1058 
1062  static const int prism6_node_map[6];
1063 
1068  static const int prism15_node_map[15];
1069 
1073  static const int prism18_node_map[18];
1074 
1079  static const int pyramid5_node_map[5];
1080 
1085  static const int pyramid13_node_map[13];
1086 
1091  static const int pyramid14_node_map[14];
1092 
1093 
1102  static const int trishell3_shellface_map[2];
1103  static const int trishell3_inverse_shellface_map[2];
1104 
1109  static const int quadshell4_shellface_map[2];
1110  static const int quadshell4_inverse_shellface_map[2];
1111 
1120  static const int hex_face_map[6];
1121 
1126  static const int hex27_face_map[6];
1127 
1132  static const int tet_face_map[4];
1133 
1138  static const int prism_face_map[5];
1139 
1144  static const int pyramid_face_map[5];
1145 
1150  static const int hex_inverse_face_map[6];
1151 
1156  static const int hex27_inverse_face_map[6];
1157 
1162  static const int tet_inverse_face_map[4];
1163 
1168  static const int prism_inverse_face_map[5];
1169 
1174  static const int pyramid_inverse_face_map[5];
1175 
1179  ExodusII_IO_Helper::Conversion assign_conversion(std::string type_str);
1180 
1184  ExodusII_IO_Helper::Conversion assign_conversion(const ElemType type);
1185 };
1186 
1187 
1188 
1195 {
1196 public:
1202  explicit
1203  NamesData(size_t n_strings, size_t string_length);
1204 
1208  void push_back_entry(const std::string & name);
1209 
1213  char ** get_char_star_star();
1214 
1218  char * get_char_star(int i);
1219 
1220 private:
1221  // C++ data structures for managing string memory
1222  std::vector<std::vector<char>> data_table;
1223  std::vector<char *> data_table_pointers;
1224 
1225  size_t counter;
1226  size_t table_size;
1227 };
1228 
1229 
1230 } // namespace libMesh
1231 
1232 #endif // LIBMESH_HAVE_EXODUS_API
1233 
1234 #endif // LIBMESH_EXODUSII_IO_HELPER_H
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
Definition: elem_quality.C:39
std::vector< Real > nodal_var_values
std::vector< int > num_sides_per_set
std::vector< std::string > elem_var_names
size_t inverse_node_map_size
The size of the inverse node map array, this helps with bounds checking...
size_t shellface_map_size
The size of the shellface map array, this helps with bounds checking...
std::map< int, std::string > id_to_ss_names
unsigned int dim
static const int invalid_id
An invalid_id that can be returned to signal failure in case something goes wrong.
std::vector< int > exodus_elem_num_to_libmesh
ElemType
Defines an enum for geometric element types.
MeshBase & mesh
const class libmesh_nullptr_t libmesh_nullptr
std::vector< Real > time_steps
The libMesh namespace provides an interface to certain functionality in the library.
std::vector< std::vector< char > > data_table
const std::string exodus_type
The string corresponding to the Exodus type for this element.
const int * inverse_node_map
Pointer to the inverse node map for this element.
void initialize(EquationSystems &es, const std::string &system_name)
Definition: main.C:52
Conversion(const int *nm, size_t nm_size, const int *inm, size_t inm_size, const int *sm, size_t sm_size, const int *ism, size_t ism_size, const ElemType ct, std::string ex_type)
Constructor.
This is the MeshBase class.
Definition: mesh_base.h:68
std::map< int, int > libmesh_elem_num_to_exodus
size_t node_map_size
The size of the node map array, this helps with bounds checking...
const int * inverse_side_map
Pointer to the inverse side map for this element.
std::vector< std::string > global_var_names
Conversion(const int *nm, size_t nm_size, const int *inm, size_t inm_size, const int *sm, size_t sm_size, const int *ism, size_t ism_size, const int *sfm, size_t sfm_size, const int *isfm, size_t isfm_size, size_t sfi_offset, const ElemType ct, std::string ex_type)
Constructor.
This is the ExodusII_IO_Helper class.
size_t inverse_shellface_map_size
The size of the inverse shellface map array, this helps with bounds checking...
This class forms the base class for all other classes that are expected to be implemented in parallel...
std::map< int, int > libmesh_node_num_to_exodus
const int * node_map
Pointer to the node map for this element.
size_t side_map_size
The size of the side map array, this helps with bounds checking...
std::vector< Real > elem_var_values
std::vector< int > num_node_df_per_set
ExodusVarType
Wraps calls to exII::ex_get_var_names() and exII::ex_get_var_param().
const int * shellface_map
Pointer to the shellface map for this element.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
OStreamProxy out
size_t shellface_index_offset
The shellface index offset defines the offset due to a difference between libMesh and Exodus in index...
std::map< int, std::string > id_to_block_names
std::vector< int > exodus_node_num_to_libmesh
std::map< int, std::string > id_to_ns_names
std::vector< int > num_nodes_per_set
const int * side_map
Pointer to the side map for this element.
std::vector< std::string > nodal_var_names
const ElemType canonical_type
The canonical (i.e.
This class is useful for managing anything that requires a char ** input/output in ExodusII file...
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
std::vector< int > num_df_per_set
const int * inverse_shellface_map
Pointer to the inverse shellface map for this element.
size_t inverse_side_map_size
The size of the inverse side map array, this helps with bounds checking...