$extrastylesheet
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