exodusII_io_helper.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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
27 #include "libmesh/point.h"
28 
29 #ifdef LIBMESH_FORWARD_DECLARE_ENUMS
30 namespace libMesh
31 {
32 enum ElemType : int;
33 }
34 #else
35 #include "libmesh/enum_elem_type.h"
36 #endif
37 
38 // C++ includes
39 #include <iostream>
40 #include <string>
41 #include <vector>
42 #include <map>
43 
44 // Macros to simplify checking Exodus error codes
45 #define EX_CHECK_ERR(code, msg) \
46  do { \
47  if ((code) < 0) { \
48  libmesh_error_msg((msg)); \
49  } } while (0)
50 
51 #define EX_EXCEPTIONLESS_CHECK_ERR(code, msg) \
52  do { \
53  if ((code) < 0) { \
54  libMesh::err << (msg) << std::endl; \
55  libmesh_exceptionless_error(); \
56  } } while (0)
57 
58 
59 
60 // Through several subsequent levels of includes, the exodusII.h
61 // header includes <errno.h>. On very specific system/compiler combinations
62 // (currently GCC 5.2.0+ OSX Yosemite, El Capitan, possibly others) errno.h
63 // cannot be included while wrapped in a namespace (as we do with the exII
64 // namespace below). A workaround for this is to simply include errno.h
65 // not in any namespace prior to including exodusII.h.
66 //
67 // The same is also true for string.h.
68 #ifdef LIBMESH_COMPILER_HAS_BROKEN_ERRNO_T
69 #include <errno.h>
70 #include <string.h>
71 #endif
72 
73 
75 namespace exII {
76 extern "C" {
77 #include "exodusII.h" // defines MAX_LINE_LENGTH, MAX_STR_LENGTH used later
78 }
79 }
81 
82 namespace libMesh
83 {
84 
85 // Forward declarations
86 class MeshBase;
87 
97 {
98 public:
106  ExodusII_IO_Helper(const ParallelObject & parent,
107  bool v=false,
108  bool run_only_on_proc0=true,
109  bool single_precision=false);
113  virtual ~ExodusII_IO_Helper();
114 
121  const char * get_elem_type() const;
122 
128  void open(const char * filename, bool read_only);
129 
133  void read_header();
134 
140  void read_qa_records();
141 
147  void print_header();
148 
153  void read_nodes();
154 
159  void read_node_num_map();
160 
164  void print_nodes(std::ostream & out = libMesh::out);
165 
170  void read_block_info();
171 
175  int get_block_id(int index);
176 
181  std::string get_block_name(int index);
182 
186  int get_side_set_id(int index);
187 
192  std::string get_side_set_name(int index);
193 
197  int get_node_set_id(int index);
198 
203  std::string get_node_set_name(int index);
204 
209  void read_elem_in_block(int block);
210 
215  void read_elem_num_map();
216 
221  void read_sideset_info();
222 
227  void read_nodeset_info();
228 
233  void read_sideset(int id, int offset);
234 
239  void read_nodeset(int id);
240 
244  void close();
245 
249  int inquire(int req_info, std::string error_msg="");
250 
254  void read_time_steps();
255 
260  void read_num_time_steps();
261 
266  void read_nodal_var_values(std::string nodal_var_name, int time_step);
267 
272  void read_elemental_var_values(std::string elemental_var_name,
273  int time_step,
274  std::map<dof_id_type, Real> & elem_var_value_map);
275 
279  virtual void create(std::string filename);
280 
284  virtual void initialize(std::string title, const MeshBase & mesh, bool use_discontinuous=false);
285 
289  virtual void write_nodal_coordinates(const MeshBase & mesh, bool use_discontinuous=false);
290 
295  virtual void write_elements(const MeshBase & mesh, bool use_discontinuous=false);
296 
300  virtual void write_sidesets(const MeshBase & mesh);
301 
305  virtual void write_nodesets(const MeshBase & mesh);
306 
310  virtual void initialize_element_variables(std::vector<std::string> names,
311  const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains);
312 
316  void initialize_nodal_variables(std::vector<std::string> names);
317 
321  void initialize_global_variables(std::vector<std::string> names);
322 
326  void write_timestep(int timestep, Real time);
327 
331  void write_element_values(const MeshBase & mesh,
332  const std::vector<Real> & values,
333  int timestep,
334  const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains);
335 
339  void write_nodal_values(int var_id, const std::vector<Real> & values, int timestep);
340 
344  void write_information_records(const std::vector<std::string> & records);
345 
349  void write_global_values(const std::vector<Real> & values, int timestep);
350 
354  void read_global_values(std::vector<Real> & values, int timestep);
355 
365 
378  void write_as_dimension(unsigned dim);
379 
385 
390  std::vector<std::string> get_complex_names(const std::vector<std::string> & names) const;
391 
396  std::vector<std::set<subdomain_id_type>> get_complex_vars_active_subdomains(
397  const std::vector<std::set<subdomain_id_type>> & vars_active_subdomains) const;
398 
404  class Conversion;
405 
412  class ElementMaps;
413 
419  class NamesData;
420 
425  void message(const std::string & msg);
426 
432  void message(const std::string & msg, int i);
433 
434  // File identification flag
435  int ex_id;
436 
437  // General error flag
438  int ex_err;
439 
440  // Number of dimensions in the mesh
441  int num_dim;
442 
443  // Number of global variables
445 
446  // Total number of nodes in the mesh
448 
449  // Total number of elements in the mesh
450  int num_elem;
451 
452  // Total number of element blocks
454 
455  // Total number of node sets
457 
458  // Total number of element sets
460 
461  // Number of elements in this block
463 
464  // Number of nodes in each element
466 
467  // Number of attributes for a given block
468  int num_attr;
469 
470  // Total number of elements in all side sets
472 
473  // Vector of the block identification numbers
474  std::vector<int> block_ids;
475 
476  // Vector of nodes in an element
477  std::vector<int> connect;
478 
479  // Vector of the sideset IDs
480  std::vector<int> ss_ids;
481 
482  // Vector of the nodeset IDs
483  std::vector<int> nodeset_ids;
484 
485  // Number of sides (edges/faces) in current set
486  std::vector<int> num_sides_per_set;
487 
488  // Number of nodes in current set
489  std::vector<int> num_nodes_per_set;
490 
491  // Number of distribution factors per set
492  std::vector<int> num_df_per_set;
493 
494  // Number of distribution factors per set
495  std::vector<int> num_node_df_per_set;
496 
497  // List of element numbers in all sidesets
498  std::vector<int> elem_list;
499 
500  // Side (face/edge) number actually on the boundary
501  std::vector<int> side_list;
502 
503  // Node number actually on the boundary
504  std::vector<int> node_list;
505 
506  // Side (face/edge) id number
507  std::vector<int> id_list;
508 
509  // Optional mapping from internal [0,num_nodes) to arbitrary indices
510  std::vector<int> node_num_map;
511 
512  // Optional mapping from internal [0,num_elem) to arbitrary indices
513  std::vector<int> elem_num_map;
514 
515  // x locations of node points
516  std::vector<Real> x;
517 
518  // y locations of node points
519  std::vector<Real> y;
520 
521  // z locations of node points
522  std::vector<Real> z;
523 
524  // Problem title (Use vector<char> to emulate a char *)
525  std::vector<char> title;
526 
527  // Type of element in a given block
528  std::vector<char> elem_type;
529 
530  // Maps libMesh element numbers to Exodus element numbers
531  // gets filled in when write_elements gets called
532  std::map<int, int> libmesh_elem_num_to_exodus;
533  std::vector<int> exodus_elem_num_to_libmesh;
534 
535  // Map of all node numbers connected to local node numbers to their exodus numbering.
536  // The exodus numbers are stored in here starting with 1
537  std::map<int, int> libmesh_node_num_to_exodus;
538  std::vector<int> exodus_node_num_to_libmesh;
539 
540  // The number of timesteps in the file, as returned by ex_inquire
542 
543  // The timesteps stored in the solution file, filled by read_time_steps()
544  std::vector<Real> time_steps;
545 
546  // The number of nodal variables in the Exodus file
548 
549  // The names of the nodal variables stored in the Exodus file
550  std::vector<std::string> nodal_var_names;
551 
552  // Holds the nodal variable values for a given variable, one value per node
553  std::vector<Real> nodal_var_values;
554 
555  // The number of elemental variables in the Exodus file
557 
558  // The names of the elemental variables stored in the Exodus file
559  std::vector<std::string> elem_var_names;
560 
561  // Holds the elemental variable values for a given variable, one value per element
562  std::vector<Real> elem_var_values;
563 
564  // The names of the global variables stored in the Exodus file
565  std::vector<std::string> global_var_names;
566 
567  // Maps of Ids to named entities
568  std::map<int, std::string> id_to_block_names;
569  std::map<int, std::string> id_to_ss_names;
570  std::map<int, std::string> id_to_ns_names;
571 
572  // On/Off message flag
573  bool verbose;
574 
575  // This flag gets set after the Exodus file has been successfully opened for writing.
576  // Both the create() and open() (if called with EX_WRITE) functions may set this flag.
578 
579  // This flag gets set after the open() function has been successfully called.
580  // We call open() to open an ExodusII file for reading.
582 
583  // When either create() or open() is called, the Helper stores the
584  // name of the opened file as current_filename. This way, the
585  // ExodusII_IO object can check to see if, on subsequent writes, the
586  // user is asking to write to a *different* filename from the one
587  // that is currently open, and signal an error. The current
588  // ExodusII_IO implementation is designed to work with a single file
589  // only, so if you want to write to multiple Exodus files, use a
590  // different ExodusII_IO object for each one.
591  std::string current_filename;
592 
602  void read_var_names(ExodusVarType type);
603 
604 protected:
609  void check_existing_vars(ExodusVarType type, std::vector<std::string> & names, std::vector<std::string> & names_from_file);
610 
616  void write_var_names(ExodusVarType type, std::vector<std::string> & names);
617 
618  // If true, whenever there is an I/O operation, only perform if if we are on processor 0.
620 
621  // True once the elem vars are initialized
623 
624  // True once the global vars are initialized
626 
627  // True once the nodal vars are initialized
629 
630  // If true, use the Mesh's dimension (as determined by the dimension
631  // of the elements comprising the mesh) instead of the mesh's
632  // spatial dimension, when writing. By default this is false.
634 
635  // Use this for num_dim when writing the Exodus file. If non-zero, supersedes
636  // any value set in _use_mesh_dimension_instead_of_spatial_dimension.
638 
639  // On output, shift every point by _coordinate_offset
641 
642  // If true, forces single precision I/O
644 
645 private:
646 
650  void read_var_names_impl(const char * var_type,
651  int & count,
652  std::vector<std::string> & result);
653 
657  void write_var_names_impl(const char * var_type,
658  int & count,
659  std::vector<std::string> & names);
660 };
661 
662 
663 
664 
665 
666 
667 
668 
670 {
671 public:
672 
677  Conversion(const int * nm, // node_map
678  size_t nm_size,
679  const int * inm, // inverse_node_map
680  size_t inm_size,
681  const int * sm, // side_map
682  size_t sm_size,
683  const int * ism, // inverse_side_map
684  size_t ism_size,
685  const ElemType ct, // "canonical" aka libmesh element type
686  std::string ex_type) // string representing the Exodus element type
687  : node_map(nm),
688  node_map_size(nm_size),
689  inverse_node_map(inm),
690  inverse_node_map_size(inm_size),
691  side_map(sm),
692  side_map_size(sm_size),
693  inverse_side_map(ism),
694  inverse_side_map_size(ism_size),
695  shellface_map(nullptr),
697  inverse_shellface_map(nullptr),
700  canonical_type(ct),
701  exodus_type(ex_type)
702  {}
703 
708  Conversion(const int * nm, // node_map
709  size_t nm_size,
710  const int * inm, // inverse_node_map
711  size_t inm_size,
712  const int * sm, // side_map
713  size_t sm_size,
714  const int * ism, // inverse_side_map
715  size_t ism_size,
716  const int * sfm, // shellface_map
717  size_t sfm_size,
718  const int * isfm, // inverse_shellface_map
719  size_t isfm_size,
720  size_t sfi_offset,
721  const ElemType ct, // "canonical" aka libmesh element type
722  std::string ex_type) // string representing the Exodus element type
723  : node_map(nm),
724  node_map_size(nm_size),
725  inverse_node_map(inm),
726  inverse_node_map_size(inm_size),
727  side_map(sm),
728  side_map_size(sm_size),
729  inverse_side_map(ism),
730  inverse_side_map_size(ism_size),
731  shellface_map(sfm),
732  shellface_map_size(sfm_size),
733  inverse_shellface_map(isfm),
734  inverse_shellface_map_size(isfm_size),
735  shellface_index_offset(sfi_offset),
736  canonical_type(ct),
737  exodus_type(ex_type)
738  {
739  // libmesh_ignore variables that are only used in asserts to avoid
740  // compiler warnings.
746  }
747 
754  int get_node_map(int i) const
755  {
756  libmesh_assert_less (static_cast<size_t>(i), node_map_size);
757  return node_map[i];
758  }
759 
770  int get_inverse_node_map(int i) const
771  {
772  libmesh_assert_less (static_cast<size_t>(i), inverse_node_map_size);
773  return inverse_node_map[i];
774  }
775 
782  int get_side_map(int i) const;
783 
790  int get_inverse_side_map(int i) const
791  {
792  libmesh_assert_less (static_cast<size_t>(i), inverse_side_map_size);
793  return inverse_side_map[i];
794  }
795 
800  int get_shellface_map(int i) const
801  {
802  libmesh_assert_less (static_cast<size_t>(i), shellface_map_size);
803  return shellface_map[i];
804  }
805 
809  int get_inverse_shellface_map(int i) const
810  {
811  libmesh_assert_less (static_cast<size_t>(i), inverse_shellface_map_size);
812  return inverse_shellface_map[i];
813  }
814 
822 
826  std::string exodus_elem_type() const { return exodus_type; }
827 
831  std::size_t get_shellface_index_offset() const { return shellface_index_offset; }
832 
837  static const int invalid_id;
838 
839 private:
843  const int * node_map;
844 
850 
856  const int * inverse_node_map;
857 
863 
867  const int * side_map;
868 
873 
877  const int * inverse_side_map;
878 
884 
890  const int * shellface_map;
891 
897 
902 
908 
915 
921 
925  const std::string exodus_type;
926 };
927 
928 
929 
930 
931 
932 
934 {
935 public:
936 
944 
945 public:
946 
955  static const int nodeelem_node_map[1];
956 
965  static const int edge2_node_map[2];
966 
970  static const int edge3_node_map[3];
971 
975  // FIXME: This notion may or may not be defined in ExodusII
976 
981  static const int edge_edge_map[2];
982 
987  static const int edge_inverse_edge_map[2];
988 
998  static const int quad4_node_map[4];
999 
1004  static const int quad8_node_map[8];
1005 
1010  static const int quad9_node_map[9];
1011 
1015  static const int tri3_node_map[3];
1016 
1021  static const int tri6_node_map[6];
1022 
1031  static const int tri_edge_map[3];
1032 
1039  static const int trishell3_edge_map[3];
1040  static const int trishell3_inverse_edge_map[3];
1041 
1046  static const int quad_edge_map[4];
1047 
1054  static const int quadshell4_edge_map[4];
1055  static const int quadshell4_inverse_edge_map[4];
1056 
1061  static const int tri_inverse_edge_map[3];
1062 
1067  static const int quad_inverse_edge_map[4];
1068 
1078  static const int hex8_node_map[8];
1079 
1084  static const int hex20_node_map[20];
1085 
1090  static const int hex27_node_map[27];
1091 
1096  static const int hex27_inverse_node_map[27];
1097 
1102  static const int tet4_node_map[4];
1103 
1108  static const int tet10_node_map[10];
1109 
1113  static const int prism6_node_map[6];
1114 
1119  static const int prism15_node_map[15];
1120 
1124  static const int prism18_node_map[18];
1125 
1130  static const int pyramid5_node_map[5];
1131 
1136  static const int pyramid13_node_map[13];
1137 
1142  static const int pyramid14_node_map[14];
1143 
1144 
1153  static const int trishell3_shellface_map[2];
1154  static const int trishell3_inverse_shellface_map[2];
1155 
1160  static const int quadshell4_shellface_map[2];
1162 
1171  static const int hex_face_map[6];
1172 
1177  static const int hex27_face_map[6];
1178 
1183  static const int tet_face_map[4];
1184 
1189  static const int prism_face_map[5];
1190 
1195  static const int pyramid_face_map[5];
1196 
1201  static const int hex_inverse_face_map[6];
1202 
1207  static const int hex27_inverse_face_map[6];
1208 
1213  static const int tet_inverse_face_map[4];
1214 
1219  static const int prism_inverse_face_map[5];
1220 
1225  static const int pyramid_inverse_face_map[5];
1226 
1230  ExodusII_IO_Helper::Conversion assign_conversion(std::string type_str);
1231 
1236 };
1237 
1238 
1239 
1246 {
1247 public:
1253  explicit
1254  NamesData(size_t n_strings, size_t string_length);
1255 
1259  void push_back_entry(const std::string & name);
1260 
1264  char ** get_char_star_star();
1265 
1269  char * get_char_star(int i);
1270 
1271 private:
1272  // C++ data structures for managing string memory
1273  std::vector<std::vector<char>> data_table;
1274  std::vector<char *> data_table_pointers;
1275 
1276  size_t counter;
1277  size_t table_size;
1278 };
1279 
1280 
1281 } // namespace libMesh
1282 
1283 #endif // LIBMESH_HAVE_EXODUS_API
1284 
1285 #endif // LIBMESH_EXODUSII_IO_HELPER_H
std::string name(const ElemQuality q)
Definition: elem_quality.C:42
virtual void write_sidesets(const MeshBase &mesh)
void use_mesh_dimension_instead_of_spatial_dimension(bool val)
std::vector< Real > nodal_var_values
std::vector< std::string > get_complex_names(const std::vector< std::string > &names) const
std::vector< int > num_sides_per_set
const char * get_elem_type() const
std::vector< std::string > elem_var_names
void write_var_names_impl(const char *var_type, int &count, std::vector< std::string > &names)
void write_var_names(ExodusVarType type, std::vector< std::string > &names)
std::map< int, std::string > id_to_ss_names
std::string get_block_name(int index)
void read_nodal_var_values(std::string nodal_var_name, int time_step)
ExodusII_IO_Helper(const ParallelObject &parent, bool v=false, bool run_only_on_proc0=true, bool single_precision=false)
void write_information_records(const std::vector< std::string > &records)
void read_var_names_impl(const char *var_type, int &count, std::vector< std::string > &result)
void write_as_dimension(unsigned dim)
std::vector< int > exodus_elem_num_to_libmesh
void print_nodes(std::ostream &out=libMesh::out)
std::string get_side_set_name(int index)
MeshBase & mesh
ExodusII_IO_Helper::Conversion assign_conversion(std::string type_str)
int inquire(int req_info, std::string error_msg="")
virtual void write_nodesets(const MeshBase &mesh)
std::vector< Real > time_steps
virtual void write_elements(const MeshBase &mesh, bool use_discontinuous=false)
std::vector< std::vector< char > > data_table
void write_nodal_values(int var_id, const std::vector< Real > &values, int timestep)
void check_existing_vars(ExodusVarType type, std::vector< std::string > &names, std::vector< std::string > &names_from_file)
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)
Base class for Mesh.
Definition: mesh_base.h:77
void write_element_values(const MeshBase &mesh, const std::vector< Real > &values, int timestep, const std::vector< std::set< subdomain_id_type >> &vars_active_subdomains)
void write_timestep(int timestep, Real time)
std::map< int, int > libmesh_elem_num_to_exodus
virtual void initialize_element_variables(std::vector< std::string > names, const std::vector< std::set< subdomain_id_type >> &vars_active_subdomains)
void open(const char *filename, bool read_only)
void libmesh_ignore(const Args &...)
void push_back_entry(const std::string &name)
void read_global_values(std::vector< Real > &values, int timestep)
std::vector< std::string > global_var_names
void read_var_names(ExodusVarType type)
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)
void write_global_values(const std::vector< Real > &values, int timestep)
An object whose state is distributed along a set of processors.
std::map< int, int > libmesh_node_num_to_exodus
void initialize_global_variables(std::vector< std::string > names)
std::vector< Real > elem_var_values
std::vector< int > num_node_df_per_set
void message(const std::string &msg)
virtual void initialize(std::string title, const MeshBase &mesh, bool use_discontinuous=false)
virtual void create(std::string filename)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void read_sideset(int id, int offset)
NamesData(size_t n_strings, size_t string_length)
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
void initialize_nodal_variables(std::vector< std::string > names)
std::vector< int > num_nodes_per_set
std::vector< std::string > nodal_var_names
std::string get_node_set_name(int index)
OStreamProxy out(std::cout)
void read_elemental_var_values(std::string elemental_var_name, int time_step, std::map< dof_id_type, Real > &elem_var_value_map)
A geometric point in (x,y,z) space.
Definition: point.h:38
std::vector< int > num_df_per_set
virtual void write_nodal_coordinates(const MeshBase &mesh, bool use_discontinuous=false)
std::vector< std::set< subdomain_id_type > > get_complex_vars_active_subdomains(const std::vector< std::set< subdomain_id_type >> &vars_active_subdomains) const