$extrastylesheet
exodusII_io_helper.h
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 #ifndef LIBMESH_EXODUSII_IO_HELPER_H
00019 #define LIBMESH_EXODUSII_IO_HELPER_H
00020 
00021 #include "libmesh/libmesh_config.h"
00022 
00023 #ifdef LIBMESH_HAVE_EXODUS_API
00024 
00025 // Local includes
00026 #include "libmesh/mesh_base.h"
00027 #include "libmesh/parallel_object.h"
00028 #include "libmesh/point.h"
00029 
00030 // C++ includes
00031 #include <iostream>
00032 #include <string>
00033 #include <vector>
00034 #include <map>
00035 
00036 // Macros to simplify checking Exodus error codes
00037 #define EX_CHECK_ERR(code, msg)                 \
00038   do {                                          \
00039     if ((code) < 0) {                           \
00040       libmesh_error_msg((msg));                 \
00041     } } while(0)
00042 
00043 #define EX_EXCEPTIONLESS_CHECK_ERR(code, msg)   \
00044   do {                                          \
00045     if ((code) < 0) {                           \
00046       libMesh::err << (msg) << std::endl;       \
00047       libmesh_exceptionless_error();            \
00048     } } while(0)
00049 
00050 
00051 
00052 namespace libMesh
00053 {
00054 
00055 
00056 namespace exII {
00057 extern "C" {
00058 #include "exodusII.h" // defines MAX_LINE_LENGTH, MAX_STR_LENGTH used later
00059 }
00060 }
00061 
00068 class ExodusII_IO_Helper : public ParallelObject
00069 {
00070 public:
00071 
00079   ExodusII_IO_Helper(const ParallelObject &parent,
00080                      bool v=false,
00081                      bool run_only_on_proc0=true,
00082                      bool single_precision=false);
00086   virtual ~ExodusII_IO_Helper();
00087 
00092   const char* get_elem_type() const;
00093 
00099   void open(const char* filename, bool read_only);
00100 
00104   void read_header();
00105 
00111   void print_header();
00112 
00117   void read_nodes();
00118 
00123   void read_node_num_map();
00124 
00128   void print_nodes(std::ostream &out = libMesh::out);
00129 
00134   void read_block_info();
00135 
00139   int get_block_id(int index);
00140 
00145   std::string get_block_name(int index);
00146 
00150   int get_side_set_id(int index);
00151 
00156   std::string get_side_set_name(int index);
00157 
00161   int get_node_set_id(int index);
00162 
00167   std::string get_node_set_name(int index);
00168 
00173   void read_elem_in_block(int block);
00174 
00179   void read_elem_num_map();
00180 
00185   void read_sideset_info();
00186 
00191   void read_nodeset_info();
00192 
00197   void read_sideset(int id, int offset);
00198 
00203   void read_nodeset(int id);
00204 
00208   void close();
00209 
00213   int inquire(int req_info, std::string error_msg="");
00214 
00218   void read_time_steps();
00219 
00224   void read_num_time_steps();
00225 
00230   void read_nodal_var_values(std::string nodal_var_name, int time_step);
00231 
00236   void read_elemental_var_values(std::string elemental_var_name, int time_step);
00237 
00241   virtual void create(std::string filename);
00242 
00246   virtual void initialize(std::string title, const MeshBase & mesh, bool use_discontinuous=false);
00247 
00251   virtual void write_nodal_coordinates(const MeshBase & mesh, bool use_discontinuous=false);
00252 
00257   virtual void write_elements(const MeshBase & mesh, bool use_discontinuous=false);
00258 
00262   virtual void write_sidesets(const MeshBase & mesh);
00263 
00267   virtual void write_nodesets(const MeshBase & mesh);
00268 
00272   void initialize_element_variables(std::vector<std::string> names);
00273 
00277   void initialize_nodal_variables(std::vector<std::string> names);
00278 
00282   void initialize_global_variables(std::vector<std::string> names);
00283 
00287   void write_timestep(int timestep, Real time);
00288 
00292   void write_element_values(const MeshBase & mesh, const std::vector<Real> & values, int timestep);
00293 
00297   void write_nodal_values(int var_id, const std::vector<Real> & values, int timestep);
00298 
00302   void write_information_records(const std::vector<std::string> & records);
00303 
00307   void write_global_values(const std::vector<Real> & values, int timestep);
00308 
00317   void use_mesh_dimension_instead_of_spatial_dimension(bool val);
00318 
00323   void set_coordinate_offset(Point p);
00324 
00329   std::vector<std::string> get_complex_names(const std::vector<std::string>& names) const;
00330 
00336   class Conversion;
00337 
00344   class ElementMaps;
00345 
00351   class NamesData;
00352 
00357   void message(const std::string& msg);
00358 
00364   void message(const std::string& msg, int i);
00365 
00366   // File identification flag
00367   int ex_id;
00368 
00369   // General error flag
00370   int ex_err;
00371 
00372   // Number of dimensions in the mesh
00373   int num_dim;
00374 
00375   // Number of global variables
00376   int num_global_vars;
00377 
00378   // Total number of nodes in the mesh
00379   int num_nodes;
00380 
00381   // Total number of elements in the mesh
00382   int num_elem;
00383 
00384   // Total number of element blocks
00385   int num_elem_blk;
00386 
00387   // Total number of node sets
00388   int num_node_sets;
00389 
00390   // Total number of element sets
00391   int num_side_sets;
00392 
00393   // Number of elements in this block
00394   int num_elem_this_blk;
00395 
00396   // Number of nodes in each element
00397   int num_nodes_per_elem;
00398 
00399   // Number of attributes for a given block
00400   int num_attr;
00401 
00402   // Total number of elements in all side sets
00403   int num_elem_all_sidesets;
00404 
00405   // Vector of the block identification numbers
00406   std::vector<int> block_ids;
00407 
00408   // Vector of nodes in an element
00409   std::vector<int> connect;
00410 
00411   // Vector of the sideset IDs
00412   std::vector<int> ss_ids;
00413 
00414   // Vector of the nodeset IDs
00415   std::vector<int> nodeset_ids;
00416 
00417   // Number of sides (edges/faces) in current set
00418   std::vector<int> num_sides_per_set;
00419 
00420   // Number of nodes in current set
00421   std::vector<int> num_nodes_per_set;
00422 
00423   // Number of distribution factors per set
00424   std::vector<int> num_df_per_set;
00425 
00426   // Number of distribution factors per set
00427   std::vector<int> num_node_df_per_set;
00428 
00429   // List of element numbers in all sidesets
00430   std::vector<int> elem_list;
00431 
00432   // Side (face/edge) number actually on the boundary
00433   std::vector<int> side_list;
00434 
00435   // Node number actually on the boundary
00436   std::vector<int> node_list;
00437 
00438   // Side (face/edge) id number
00439   std::vector<int> id_list;
00440 
00441   // Optional mapping from internal [0,num_nodes) to arbitrary indices
00442   std::vector<int> node_num_map;
00443 
00444   // Optional mapping from internal [0,num_elem) to arbitrary indices
00445   std::vector<int> elem_num_map;
00446 
00447   // x locations of node points
00448   std::vector<Real> x;
00449 
00450   // y locations of node points
00451   std::vector<Real> y;
00452 
00453   // z locations of node points
00454   std::vector<Real> z;
00455 
00456   //  Problem title (Use vector<char> to emulate a char*)
00457   std::vector<char> title;
00458 
00459   // Type of element in a given block
00460   std::vector<char> elem_type;
00461 
00462   // Maps libMesh element numbers to Exodus element numbers
00463   // gets filled in when write_elements gets called
00464   std::map<int, int> libmesh_elem_num_to_exodus;
00465   std::vector<int> exodus_elem_num_to_libmesh;
00466 
00467   // Map of all node numbers connected to local node numbers to their exodus numbering.
00468   // The exodus numbers are stored in here starting with 1
00469   std::map<int, int> libmesh_node_num_to_exodus;
00470   std::vector<int> exodus_node_num_to_libmesh;
00471 
00472   // The number of timesteps in the file, as returned by ex_inquire
00473   int num_time_steps;
00474 
00475   // The timesteps stored in the solution file, filled by read_time_steps()
00476   std::vector<Real> time_steps;
00477 
00478   // The number of nodal variables in the Exodus file
00479   int num_nodal_vars;
00480 
00481   // The names of the nodal variables stored in the Exodus file
00482   std::vector<std::string> nodal_var_names;
00483 
00484   // Holds the nodal variable values for a given variable, one value per node
00485   std::vector<Real> nodal_var_values;
00486 
00487   // The number of elemental variables in the Exodus file
00488   int num_elem_vars;
00489 
00490   // The names of the elemental variables stored in the Exodus file
00491   std::vector<std::string> elem_var_names;
00492 
00493   // Holds the elemental variable values for a given variable, one value per element
00494   std::vector<Real> elem_var_values;
00495 
00496   // The names of the global variables stored in the Exodus file
00497   std::vector<std::string> global_var_names;
00498 
00499   // Maps of Ids to named entities
00500   std::map<int, std::string> id_to_block_names;
00501   std::map<int, std::string> id_to_ss_names;
00502   std::map<int, std::string> id_to_ns_names;
00503 
00504   // On/Off message flag
00505   bool verbose;
00506 
00507   // This flag gets set after the Exodus file has been successfully opened for writing.
00508   // Both the create() and open() (if called with EX_WRITE) functions may set this flag.
00509   bool opened_for_writing;
00510 
00511   // This flag gets set after the open() function has been successfully called.
00512   // We call open() to open an ExodusII file for reading.
00513   bool opened_for_reading;
00514 
00515   // When either create() or open() is called, the Helper stores the
00516   // name of the opened file as current_filename.  This way, the
00517   // ExodusII_IO object can check to see if, on subsequent writes, the
00518   // user is asking to write to a *different* filename from the one
00519   // that is currently open, and signal an error.  The current
00520   // ExodusII_IO implementation is designed to work with a single file
00521   // only, so if you want to write to multiple Exodus files, use a
00522   // different ExodusII_IO object for each one.
00523   std::string current_filename;
00524 
00533   enum ExodusVarType {NODAL=0, ELEMENTAL=1, GLOBAL=2};
00534   void read_var_names(ExodusVarType type);
00535 
00536 protected:
00537   // If true, whenever there is an I/O operation, only perform if if we are on processor 0.
00538   bool _run_only_on_proc0;
00539 
00540   // True once the elem vars are initialized
00541   bool _elem_vars_initialized;
00542 
00543   // True once the global vars are initialized
00544   bool _global_vars_initialized;
00545 
00546   // True once the nodal vars are initialized
00547   bool _nodal_vars_initialized;
00548 
00549   // If true, use the Mesh's dimension (as determined by the dimension
00550   // of the elements comprising the mesh) instead of the mesh's
00551   // spatial dimension, when writing.  By default this is false.
00552   bool _use_mesh_dimension_instead_of_spatial_dimension;
00553 
00554   // On output, shift every point by _coordinate_offset
00555   Point _coordinate_offset;
00556 
00557   // If true, forces single precision I/O
00558   bool _single_precision;
00559 
00560 private:
00561 
00567   void write_var_names(ExodusVarType type, std::vector<std::string>& names);
00568 
00573   void check_existing_vars(ExodusVarType type, std::vector<std::string>& names, std::vector<std::string>& names_from_file);
00574 
00578   void read_var_names_impl(const char* var_type, int& count, std::vector<std::string>& result);
00579 
00583   void write_var_names_impl(const char* var_type, int& count, std::vector<std::string>& names);
00584 };
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00592 
00593 class ExodusII_IO_Helper::Conversion
00594 {
00595 public:
00596 
00601   Conversion(const int* nm,       // node_map
00602              size_t nm_size,
00603              const int* inm,      // inverse_node_map
00604              size_t inm_size,
00605              const int* sm,       // side_map
00606              size_t sm_size,
00607              const int* ism,      // inverse_side_map
00608              size_t ism_size,
00609              const ElemType ct,   // "canonical" aka libmesh element type
00610              std::string ex_type) // string representing the Exodus element type
00611     : node_map(nm),
00612       node_map_size(nm_size),
00613       inverse_node_map(inm),
00614       inverse_node_map_size(inm_size),
00615       side_map(sm),
00616       side_map_size(sm_size),
00617       inverse_side_map(ism),
00618       inverse_side_map_size(ism_size),
00619       canonical_type(ct),
00620       exodus_type(ex_type)
00621   {}
00622 
00628   int get_node_map(int i) const
00629   {
00630     libmesh_assert_less (static_cast<size_t>(i), node_map_size);
00631     return node_map[i];
00632   }
00633 
00640   int get_inverse_node_map(int i) const
00641   {
00642     libmesh_assert_less (static_cast<size_t>(i), inverse_node_map_size);
00643     return inverse_node_map[i];
00644   }
00645 
00651   int get_side_map(int i) const
00652   {
00653     libmesh_assert_less (static_cast<size_t>(i), side_map_size);
00654     return side_map[i];
00655   }
00656 
00662   int get_inverse_side_map(int i) const
00663   {
00664     libmesh_assert_less (static_cast<size_t>(i), inverse_side_map_size);
00665     return inverse_side_map[i];
00666   }
00667 
00673   ElemType get_canonical_type()    const { return canonical_type; }
00674 
00678   std::string exodus_elem_type() const { return exodus_type; }
00679 
00680 
00681 private:
00685   const int* node_map;
00686 
00690   size_t node_map_size;
00691 
00697   const int* inverse_node_map;
00698 
00702   size_t inverse_node_map_size;
00703 
00707   const int* side_map;
00708 
00712   size_t side_map_size;
00713 
00717   const int* inverse_side_map;
00718 
00722   size_t inverse_side_map_size;
00723 
00728   const ElemType canonical_type;
00729 
00733   const std::string exodus_type;
00734 };
00735 
00736 
00737 
00738 
00739 
00740 
00741 class ExodusII_IO_Helper::ElementMaps
00742 {
00743 public:
00744 
00748   ElementMaps() {}
00749 
00758   static const int edge2_node_map[2];
00759 
00763   static const int edge3_node_map[3];
00764 
00768   // FIXME: This notion may or may not be defined in ExodusII
00769 
00774   static const int edge_edge_map[2];
00775 
00780   static const int edge_inverse_edge_map[2];
00781 
00791   static const int quad4_node_map[4];
00792 
00797   static const int quad8_node_map[8];
00798 
00803   static const int quad9_node_map[9];
00804 
00808   static const int tri3_node_map[3];
00809 
00814   static const int tri6_node_map[6];
00815 
00824   static const int tri_edge_map[3];
00825 
00830   static const int quad_edge_map[4];
00831 
00836   static const int tri_inverse_edge_map[3];
00837 
00842   static const int quad_inverse_edge_map[4];
00843 
00853   static const int hex8_node_map[8];
00854 
00859   static const int hex20_node_map[20];
00860 
00865   static const int hex27_node_map[27];
00866 
00871   static const int hex27_inverse_node_map[27];
00872 
00877   static const int tet4_node_map[4];
00878 
00883   static const int tet10_node_map[10];
00884 
00888   static const int prism6_node_map[6];
00889 
00894   static const int prism15_node_map[15];
00895 
00899   static const int prism18_node_map[18];
00900 
00905   static const int pyramid5_node_map[5];
00906 
00911   static const int pyramid13_node_map[13];
00912 
00917   static const int pyramid14_node_map[14];
00918 
00919 
00928   static const int hex_face_map[6];
00929 
00934   static const int hex27_face_map[6];
00935 
00940   static const int tet_face_map[4];
00941 
00946   static const int prism_face_map[5];
00947 
00952   static const int pyramid_face_map[5];
00953 
00958   static const int hex_inverse_face_map[6];
00959 
00964   static const int hex27_inverse_face_map[6];
00965 
00970   static const int tet_inverse_face_map[4];
00971 
00976   static const int prism_inverse_face_map[5];
00977 
00982   static const int pyramid_inverse_face_map[5];
00983 
00987   ExodusII_IO_Helper::Conversion assign_conversion(std::string type_str);
00988 
00992   ExodusII_IO_Helper::Conversion assign_conversion(const ElemType type);
00993 };
00994 
00995 
00996 
01002 class ExodusII_IO_Helper::NamesData
01003 {
01004 public:
01010   explicit
01011   NamesData(size_t n_strings, size_t string_length);
01012 
01016   void push_back_entry(const std::string & name);
01017 
01021   char** get_char_star_star();
01022 
01026   char* get_char_star(int i);
01027 
01028 private:
01029   // C++ data structures for managing string memory
01030   std::vector<std::vector<char> > data_table;
01031   std::vector<char*> data_table_pointers;
01032 
01033   size_t counter;
01034   size_t table_size;
01035 };
01036 
01037 
01038 } // namespace libMesh
01039 
01040 #endif // LIBMESH_HAVE_EXODUS_API
01041 
01042 #endif // LIBMESH_EXODUSII_IO_HELPER_H