exodusII_io_helper.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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 00019 #include "libmesh/exodusII_io_helper.h" 00020 00021 00022 #ifdef LIBMESH_HAVE_EXODUS_API 00023 00024 #include <algorithm> 00025 #include <functional> 00026 00027 #include "libmesh/boundary_info.h" 00028 #include "libmesh/enum_elem_type.h" 00029 #include "libmesh/elem.h" 00030 #include "libmesh/system.h" 00031 #include "libmesh/numeric_vector.h" 00032 00033 #ifdef DEBUG 00034 #include "libmesh/mesh_tools.h" // for elem_types warning 00035 #endif 00036 00037 // This macro returns the length of the array a. Don't 00038 // try using it on empty arrays, since it accesses the 00039 // zero'th element. 00040 #define ARRAY_LENGTH(a) (sizeof((a))/sizeof((a)[0])) 00041 00042 // Anonymous namespace for file local data 00043 namespace 00044 { 00045 // Define equivalence classes of Cubit/Exodus element types that map to 00046 // libmesh ElemTypes 00047 std::map<std::string, libMeshEnums::ElemType> element_equivalence_map; 00048 00049 // This function initializes the element_equivalence_map the first time it 00050 // is called, and returns early all other times. 00051 void init_element_equivalence_map() 00052 { 00053 if (element_equivalence_map.empty()) 00054 { 00055 // EDGE2 equivalences 00056 element_equivalence_map["EDGE2"] = EDGE2; 00057 element_equivalence_map["TRUSS"] = EDGE2; 00058 element_equivalence_map["BEAM"] = EDGE2; 00059 element_equivalence_map["BAR"] = EDGE2; 00060 element_equivalence_map["TRUSS2"] = EDGE2; 00061 element_equivalence_map["BEAM2"] = EDGE2; 00062 element_equivalence_map["BAR2"] = EDGE2; 00063 00064 // EDGE3 equivalences 00065 element_equivalence_map["EDGE3"] = EDGE3; 00066 element_equivalence_map["TRUSS3"] = EDGE3; 00067 element_equivalence_map["BEAM3"] = EDGE3; 00068 element_equivalence_map["BAR3"] = EDGE3; 00069 00070 // QUAD4 equivalences 00071 element_equivalence_map["QUAD"] = QUAD4; 00072 element_equivalence_map["QUAD4"] = QUAD4; 00073 element_equivalence_map["SHELL"] = QUAD4; 00074 element_equivalence_map["SHELL4"] = QUAD4; 00075 00076 // QUAD8 equivalences 00077 element_equivalence_map["QUAD8"] = QUAD8; 00078 element_equivalence_map["SHELL8"] = QUAD8; 00079 00080 // QUAD9 equivalences 00081 element_equivalence_map["QUAD9"] = QUAD9; 00082 element_equivalence_map["SHELL9"] = QUAD9; 00083 00084 // TRI3 equivalences 00085 element_equivalence_map["TRI"] = TRI3; 00086 element_equivalence_map["TRI3"] = TRI3; 00087 element_equivalence_map["TRIANGLE"] = TRI3; 00088 element_equivalence_map["TRISHELL"] = TRI3; 00089 element_equivalence_map["TRISHELL3"] = TRI3; 00090 00091 // TRI6 equivalences 00092 element_equivalence_map["TRI6"] = TRI6; 00093 element_equivalence_map["TRISHELL6"] = TRI6; 00094 00095 // HEX8 equivalences 00096 element_equivalence_map["HEX"] = HEX8; 00097 element_equivalence_map["HEX8"] = HEX8; 00098 00099 // HEX20 equivalences 00100 element_equivalence_map["HEX20"] = HEX20; 00101 00102 // HEX27 equivalences 00103 element_equivalence_map["HEX27"] = HEX27; 00104 00105 // TET4 equivalences 00106 element_equivalence_map["TETRA"] = TET4; 00107 element_equivalence_map["TETRA4"] = TET4; 00108 00109 // TET10 equivalences 00110 element_equivalence_map["TETRA10"] = TET10; 00111 00112 // PRISM6 equivalences 00113 element_equivalence_map["WEDGE"] = PRISM6; 00114 00115 // PRISM15 equivalences 00116 element_equivalence_map["WEDGE15"] = PRISM15; 00117 00118 // PRISM18 equivalences 00119 element_equivalence_map["WEDGE18"] = PRISM18; 00120 00121 // PYRAMID5 equivalences 00122 element_equivalence_map["PYRAMID"] = PYRAMID5; 00123 element_equivalence_map["PYRAMID5"] = PYRAMID5; 00124 } 00125 } 00126 } 00127 00128 00129 00130 namespace libMesh 00131 { 00132 00133 // ------------------------------------------------------------ 00134 // ExodusII_IO_Helper::ElementMaps static data 00135 00136 // 1D node map definitions 00137 const int ExodusII_IO_Helper::ElementMaps::edge2_node_map[2] = {0, 1}; 00138 const int ExodusII_IO_Helper::ElementMaps::edge3_node_map[3] = {0, 1, 2}; 00139 00140 // 1D edge maps 00141 // FIXME: This notion may or may not be defined in ExodusII 00142 const int ExodusII_IO_Helper::ElementMaps::edge_edge_map[2] = {0, 1}; 00143 const int ExodusII_IO_Helper::ElementMaps::edge_inverse_edge_map[2] = {1, 2}; 00144 00145 // 2D node map definitions 00146 const int ExodusII_IO_Helper::ElementMaps::quad4_node_map[4] = {0, 1, 2, 3}; 00147 const int ExodusII_IO_Helper::ElementMaps::quad8_node_map[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 00148 const int ExodusII_IO_Helper::ElementMaps::quad9_node_map[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; 00149 const int ExodusII_IO_Helper::ElementMaps::tri3_node_map[3] = {0, 1, 2}; 00150 const int ExodusII_IO_Helper::ElementMaps::tri6_node_map[6] = {0, 1, 2, 3, 4, 5}; 00151 00152 // 2D edge map definitions 00153 const int ExodusII_IO_Helper::ElementMaps::tri_edge_map[3] = {0, 1, 2}; 00154 const int ExodusII_IO_Helper::ElementMaps::quad_edge_map[4] = {0, 1, 2, 3}; 00155 00156 //These take a libMesh ID and turn it into an Exodus ID 00157 const int ExodusII_IO_Helper::ElementMaps::tri_inverse_edge_map[3] = {1, 2, 3}; 00158 const int ExodusII_IO_Helper::ElementMaps::quad_inverse_edge_map[4] = {1, 2, 3, 4}; 00159 00160 // 3D node map definitions 00161 const int ExodusII_IO_Helper::ElementMaps::hex8_node_map[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 00162 const int ExodusII_IO_Helper::ElementMaps::hex20_node_map[20] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 00163 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; 00164 00165 // Perhaps an older Hex27 node numbering? This no longer works. 00166 //const int ExodusII_IO_Helper::ElementMaps::hex27_node_map[27] = { 1, 5, 6, 2, 0, 4, 7, 3, 13, 17, 14, 9, 8, 16, 00167 // 18, 10, 12, 19, 15, 11, 24, 25, 22, 26, 21, 23, 20}; 00168 00169 //DRG: Using the newest exodus documentation available on sourceforge and using Table 2 to see 00170 // where all of the nodes over 21 are supposed to go... we come up with: 00171 const int ExodusII_IO_Helper::ElementMaps::hex27_node_map[27] = { 00172 // Vertex and mid-edge nodes 00173 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 00174 // Mid-face nodes and centroid 00175 21, 25, 24, 26, 23, 22, 20}; 00176 //20 21 22 23 24 25 26 // LibMesh indices 00177 00178 // The hex27 appears to be the only element without a 1:1 map between its 00179 // node numbering and libmesh's. Therefore when writing out hex27's we need 00180 // to invert this map... 00181 const int ExodusII_IO_Helper::ElementMaps::hex27_inverse_node_map[27] = { 00182 // Vertex and mid-edge nodes 00183 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 00184 // Mid-face nodes and centroid 00185 26, 20, 25, 24, 22, 21, 23}; 00186 //20 21 22 23 24 25 26 00187 00188 00189 const int ExodusII_IO_Helper::ElementMaps::tet4_node_map[4] = {0, 1, 2, 3}; 00190 const int ExodusII_IO_Helper::ElementMaps::tet10_node_map[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 00191 00192 const int ExodusII_IO_Helper::ElementMaps::prism6_node_map[6] = {0, 1, 2, 3, 4, 5}; 00193 const int ExodusII_IO_Helper::ElementMaps::prism15_node_map[15] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 00194 10, 11, 12, 13, 14}; 00195 const int ExodusII_IO_Helper::ElementMaps::prism18_node_map[18] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 00196 10, 11, 12, 13, 14, 15, 16, 17}; 00197 const int ExodusII_IO_Helper::ElementMaps::pyramid5_node_map[5] = {0, 1, 2, 3, 4}; 00198 00199 // 3D face map definitions 00200 const int ExodusII_IO_Helper::ElementMaps::tet_face_map[4] = {1, 2, 3, 0}; 00201 00202 const int ExodusII_IO_Helper::ElementMaps::hex_face_map[6] = {1, 2, 3, 4, 0, 5}; 00203 const int ExodusII_IO_Helper::ElementMaps::hex27_face_map[6] = {1, 2, 3, 4, 0, 5}; 00204 //const int ExodusII_IO_Helper::ElementMaps::hex27_face_map[6] = {1, 0, 3, 5, 4, 2}; 00205 const int ExodusII_IO_Helper::ElementMaps::prism_face_map[5] = {1, 2, 3, 0, 4}; 00206 const int ExodusII_IO_Helper::ElementMaps::pyramid_face_map[5] = {-1,-1,-1,-1,-1}; // Not Implemented! 00207 00208 //These take a libMesh ID and turn it into an Exodus ID 00209 const int ExodusII_IO_Helper::ElementMaps::tet_inverse_face_map[4] = {4, 1, 2, 3}; 00210 const int ExodusII_IO_Helper::ElementMaps::hex_inverse_face_map[6] = {5, 1, 2, 3, 4, 6}; 00211 const int ExodusII_IO_Helper::ElementMaps::hex27_inverse_face_map[6] = {5, 1, 2, 3, 4, 6}; 00212 //const int ExodusII_IO_Helper::ElementMaps::hex27_inverse_face_map[6] = {2, 1, 6, 3, 5, 4}; 00213 const int ExodusII_IO_Helper::ElementMaps::prism_inverse_face_map[5] = {4, 1, 2, 3, 5}; 00214 const int ExodusII_IO_Helper::ElementMaps::pyramid_inverse_face_map[5] = {-1,-1,-1,-1,-1}; // Not Implemented! 00215 00216 00217 // ------------------------------------------------------------ 00218 // ExodusII_IO_Helper class members 00219 ExodusII_IO_Helper::~ExodusII_IO_Helper() 00220 { 00221 } 00222 00223 void ExodusII_IO_Helper::verbose (bool set_verbosity) 00224 { 00225 _verbose = set_verbosity; 00226 } 00227 00228 00229 00230 void ExodusII_IO_Helper::check_err(const int err_in, const std::string msg) 00231 { 00232 if (err_in < 0) 00233 { 00234 libMesh::err << msg << std::endl; 00235 libmesh_error(); 00236 } 00237 } 00238 00239 00240 00241 void ExodusII_IO_Helper::message(const std::string msg) 00242 { 00243 if (_verbose) libMesh::out << msg << std::endl; 00244 } 00245 00246 00247 00248 void ExodusII_IO_Helper::message(const std::string msg, int i) 00249 { 00250 if (_verbose) libMesh::out << msg << i << "." << std::endl; 00251 } 00252 00253 00254 00255 void ExodusII_IO_Helper::open(const char* filename) 00256 { 00257 ex_id = exII::ex_open(filename, 00258 EX_READ, 00259 &comp_ws, 00260 &io_ws, 00261 &ex_version); 00262 00263 std::string err_msg = std::string("Error opening ExodusII mesh file: ") + std::string(filename); 00264 check_err(ex_id, err_msg); 00265 if (_verbose) libMesh::out << "File opened successfully." << std::endl; 00266 } 00267 00268 00269 00270 void ExodusII_IO_Helper::read_header() 00271 { 00272 ex_err = exII::ex_get_init(ex_id, 00273 title.empty() ? NULL : &title[0], 00274 &num_dim, 00275 &num_nodes, 00276 &num_elem, 00277 &num_elem_blk, 00278 &num_node_sets, 00279 &num_side_sets); 00280 00281 check_err(ex_err, "Error retrieving header info."); 00282 00283 num_time_steps = inquire(exII::EX_INQ_TIME, "Error retrieving time steps"); 00284 00285 exII::ex_get_var_param(ex_id, "n", &num_nodal_vars); 00286 00287 message("Exodus header info retrieved successfully."); 00288 } 00289 00290 00291 00292 00293 void ExodusII_IO_Helper::print_header() 00294 { 00295 if (_verbose) 00296 libMesh::out << "Title: \t" << &title[0] << std::endl 00297 << "Mesh Dimension: \t" << num_dim << std::endl 00298 << "Number of Nodes: \t" << num_nodes << std::endl 00299 << "Number of elements: \t" << num_elem << std::endl 00300 << "Number of elt blocks: \t" << num_elem_blk << std::endl 00301 << "Number of node sets: \t" << num_node_sets << std::endl 00302 << "Number of side sets: \t" << num_side_sets << std::endl; 00303 } 00304 00305 00306 00307 void ExodusII_IO_Helper::read_nodes() 00308 { 00309 x.resize(num_nodes); 00310 y.resize(num_nodes); 00311 z.resize(num_nodes); 00312 00313 ex_err = exII::ex_get_coord(ex_id, 00314 static_cast<void*>(&x[0]), 00315 static_cast<void*>(&y[0]), 00316 static_cast<void*>(&z[0])); 00317 00318 check_err(ex_err, "Error retrieving nodal data."); 00319 message("Nodal data retrieved successfully."); 00320 } 00321 00322 00323 00324 void ExodusII_IO_Helper::read_node_num_map () 00325 { 00326 node_num_map.resize(num_nodes); 00327 00328 ex_err = exII::ex_get_node_num_map (ex_id, 00329 node_num_map.empty() ? NULL : &node_num_map[0]); 00330 00331 check_err(ex_err, "Error retrieving nodal number map."); 00332 message("Nodal numbering map retrieved successfully."); 00333 00334 if (_verbose) 00335 { 00336 libMesh::out << "[" << libMesh::processor_id() << "] node_num_map[i] = "; 00337 for (unsigned int i=0; i< static_cast<unsigned int>(std::min(10, num_nodes-1)); ++i) 00338 libMesh::out << node_num_map[i] << ", "; 00339 libMesh::out << "... " << node_num_map.back() << std::endl; 00340 } 00341 } 00342 00343 00344 void ExodusII_IO_Helper::print_nodes(std::ostream &out_stream) 00345 { 00346 for (int i=0; i<num_nodes; i++) 00347 out_stream << "(" << x[i] << ", " << y[i] << ", " << z[i] << ")" << std::endl; 00348 } 00349 00350 00351 00352 void ExodusII_IO_Helper::read_block_info() 00353 { 00354 block_ids.resize(num_elem_blk); 00355 // Get all element block IDs. 00356 ex_err = exII::ex_get_elem_blk_ids(ex_id, 00357 block_ids.empty() ? NULL : &block_ids[0]); 00358 // Usually, there is only one 00359 // block since there is only 00360 // one type of element. 00361 // However, there could be more. 00362 00363 check_err(ex_err, "Error getting block IDs."); 00364 message("All block IDs retrieved successfully."); 00365 00366 char name_buffer[MAX_STR_LENGTH+1]; 00367 for (int i=0; i<num_elem_blk; ++i) 00368 { 00369 ex_err = exII::ex_get_name(ex_id, exII::EX_ELEM_BLOCK, 00370 block_ids[i], name_buffer); 00371 check_err(ex_err, "Error getting block name."); 00372 id_to_block_names[block_ids[i]] = name_buffer; 00373 } 00374 message("All block mames retrieved successfully."); 00375 } 00376 00377 00378 00379 int ExodusII_IO_Helper::get_block_id(int index) 00380 { 00381 libmesh_assert_less (static_cast<unsigned int>(index), block_ids.size()); 00382 00383 return block_ids[index]; 00384 } 00385 00386 00387 00388 std::string ExodusII_IO_Helper::get_block_name(int index) 00389 { 00390 libmesh_assert_less (static_cast<unsigned int>(index), block_ids.size()); 00391 00392 return id_to_block_names[block_ids[index]]; 00393 } 00394 00395 00396 00397 int ExodusII_IO_Helper::get_side_set_id(int index) 00398 { 00399 libmesh_assert_less (static_cast<unsigned int>(index), ss_ids.size()); 00400 00401 return ss_ids[index]; 00402 } 00403 00404 00405 00406 std::string ExodusII_IO_Helper::get_side_set_name(int index) 00407 { 00408 libmesh_assert_less (static_cast<unsigned int>(index), ss_ids.size()); 00409 00410 return id_to_ss_names[ss_ids[index]]; 00411 } 00412 00413 00414 00415 int ExodusII_IO_Helper::get_node_set_id(int index) 00416 { 00417 libmesh_assert_less (static_cast<unsigned int>(index), nodeset_ids.size()); 00418 00419 return nodeset_ids[index]; 00420 } 00421 00422 00423 00424 std::string ExodusII_IO_Helper::get_node_set_name(int index) 00425 { 00426 libmesh_assert_less (static_cast<unsigned int>(index), nodeset_ids.size()); 00427 00428 return id_to_ns_names[nodeset_ids[index]]; 00429 } 00430 00431 00432 00433 00434 void ExodusII_IO_Helper::read_elem_in_block(int block) 00435 { 00436 libmesh_assert_less (static_cast<unsigned int>(block), block_ids.size()); 00437 00438 ex_err = exII::ex_get_elem_block(ex_id, 00439 block_ids[block], 00440 &elem_type[0], 00441 &num_elem_this_blk, 00442 &num_nodes_per_elem, 00443 &num_attr); 00444 if (_verbose) 00445 libMesh::out << "Reading a block of " << num_elem_this_blk 00446 << " " << &elem_type[0] << "(s)" 00447 << " having " << num_nodes_per_elem 00448 << " nodes per element." << std::endl; 00449 00450 check_err(ex_err, "Error getting block info."); 00451 message("Info retrieved successfully for block: ", block); 00452 00453 00454 00455 // Read in the connectivity of the elements of this block, 00456 // watching out for the case where we actually have no 00457 // elements in this block (possible with parallel files) 00458 connect.resize(num_nodes_per_elem*num_elem_this_blk); 00459 00460 if (!connect.empty()) 00461 { 00462 ex_err = exII::ex_get_elem_conn(ex_id, 00463 block_ids[block], 00464 &connect[0]); 00465 00466 check_err(ex_err, "Error reading block connectivity."); 00467 message("Connectivity retrieved successfully for block: ", block); 00468 } 00469 } 00470 00471 00472 00473 00474 void ExodusII_IO_Helper::read_elem_num_map () 00475 { 00476 elem_num_map.resize(num_elem); 00477 00478 ex_err = exII::ex_get_elem_num_map (ex_id, 00479 elem_num_map.empty() ? NULL : &elem_num_map[0]); 00480 00481 check_err(ex_err, "Error retrieving element number map."); 00482 message("Element numbering map retrieved successfully."); 00483 00484 00485 if (_verbose) 00486 { 00487 libMesh::out << "[" << libMesh::processor_id() << "] elem_num_map[i] = "; 00488 for (unsigned int i=0; i< static_cast<unsigned int>(std::min(10, num_elem-1)); ++i) 00489 libMesh::out << elem_num_map[i] << ", "; 00490 libMesh::out << "... " << elem_num_map.back() << std::endl; 00491 } 00492 } 00493 00494 00495 00496 void ExodusII_IO_Helper::read_sideset_info() 00497 { 00498 ss_ids.resize(num_side_sets); 00499 if (num_side_sets > 0) 00500 { 00501 ex_err = exII::ex_get_side_set_ids(ex_id, 00502 &ss_ids[0]); 00503 check_err(ex_err, "Error retrieving sideset information."); 00504 message("All sideset information retrieved successfully."); 00505 00506 // Resize appropriate data structures -- only do this once outside the loop 00507 num_sides_per_set.resize(num_side_sets); 00508 num_df_per_set.resize(num_side_sets); 00509 00510 // Inquire about the length of the 00511 // concatenated side sets element list 00512 req_info = exII::EX_INQ_SS_ELEM_LEN; 00513 ex_err = exII::ex_inquire(ex_id, 00514 req_info, 00515 &ret_int, 00516 &ret_float, 00517 &ret_char); 00518 check_err(ex_err, "Error inquiring about side set element list length."); 00519 00520 //libMesh::out << "Value returned by ex_inquire was: " << ret_int << std::endl; 00521 num_elem_all_sidesets = ret_int; 00522 elem_list.resize (num_elem_all_sidesets); 00523 side_list.resize (num_elem_all_sidesets); 00524 id_list.resize (num_elem_all_sidesets); 00525 } 00526 00527 char name_buffer[MAX_STR_LENGTH+1]; 00528 for (int i=0; i<num_side_sets; ++i) 00529 { 00530 ex_err = exII::ex_get_name(ex_id, exII::EX_SIDE_SET, 00531 ss_ids[i], name_buffer); 00532 check_err(ex_err, "Error getting side set name."); 00533 id_to_ss_names[ss_ids[i]] = name_buffer; 00534 } 00535 message("All side set mames retrieved successfully."); 00536 } 00537 00538 void ExodusII_IO_Helper::read_nodeset_info() 00539 { 00540 nodeset_ids.resize(num_node_sets); 00541 if (num_node_sets > 0) 00542 { 00543 ex_err = exII::ex_get_node_set_ids(ex_id, 00544 &nodeset_ids[0]); 00545 check_err(ex_err, "Error retrieving nodeset information."); 00546 message("All nodeset information retrieved successfully."); 00547 00548 // Resize appropriate data structures -- only do this once outnode the loop 00549 num_nodes_per_set.resize(num_node_sets); 00550 num_node_df_per_set.resize(num_node_sets); 00551 } 00552 00553 char name_buffer[MAX_STR_LENGTH+1]; 00554 for (int i=0; i<num_node_sets; ++i) 00555 { 00556 ex_err = exII::ex_get_name(ex_id, exII::EX_NODE_SET, 00557 nodeset_ids[i], name_buffer); 00558 check_err(ex_err, "Error getting node set name."); 00559 id_to_ns_names[nodeset_ids[i]] = name_buffer; 00560 } 00561 message("All node set mames retrieved successfully."); 00562 } 00563 00564 00565 00566 void ExodusII_IO_Helper::read_sideset(int id, int offset) 00567 { 00568 libmesh_assert_less (static_cast<unsigned int>(id), ss_ids.size()); 00569 libmesh_assert_less (static_cast<unsigned int>(id), num_sides_per_set.size()); 00570 libmesh_assert_less (static_cast<unsigned int>(id), num_df_per_set.size()); 00571 libmesh_assert_less_equal (static_cast<unsigned int>(offset), elem_list.size()); 00572 libmesh_assert_less_equal (static_cast<unsigned int>(offset), side_list.size()); 00573 00574 ex_err = exII::ex_get_side_set_param(ex_id, 00575 ss_ids[id], 00576 &num_sides_per_set[id], 00577 &num_df_per_set[id]); 00578 check_err(ex_err, "Error retrieving sideset parameters."); 00579 message("Parameters retrieved successfully for sideset: ", id); 00580 00581 00582 // It's OK for offset==elem_list.size() as long as num_sides_per_set[id]==0 00583 // because in that case we don't actually read anything... 00584 #ifdef DEBUG 00585 if (static_cast<unsigned int>(offset) == elem_list.size() || 00586 static_cast<unsigned int>(offset) == side_list.size() ) 00587 libmesh_assert_equal_to (num_sides_per_set[id], 0); 00588 #endif 00589 00590 00591 // Don't call ex_get_side_set unless there are actually sides there to get. 00592 // Exodus prints an annoying warning in DEBUG mode otherwise... 00593 if (num_sides_per_set[id] > 0) 00594 { 00595 ex_err = exII::ex_get_side_set(ex_id, 00596 ss_ids[id], 00597 &elem_list[offset], 00598 &side_list[offset]); 00599 check_err(ex_err, "Error retrieving sideset data."); 00600 message("Data retrieved successfully for sideset: ", id); 00601 00602 for (int i=0; i<num_sides_per_set[id]; i++) 00603 id_list[i+offset] = ss_ids[id]; 00604 } 00605 } 00606 00607 00608 00609 void ExodusII_IO_Helper::read_nodeset(int id) 00610 { 00611 libmesh_assert_less (static_cast<unsigned int>(id), nodeset_ids.size()); 00612 libmesh_assert_less (static_cast<unsigned int>(id), num_nodes_per_set.size()); 00613 libmesh_assert_less (static_cast<unsigned int>(id), num_node_df_per_set.size()); 00614 00615 ex_err = exII::ex_get_node_set_param(ex_id, 00616 nodeset_ids[id], 00617 &num_nodes_per_set[id], 00618 &num_node_df_per_set[id]); 00619 check_err(ex_err, "Error retrieving nodeset parameters."); 00620 message("Parameters retrieved successfully for nodeset: ", id); 00621 00622 node_list.resize(num_nodes_per_set[id]); 00623 00624 // Don't call ex_get_node_set unless there are actually nodes there to get. 00625 // Exodus prints an annoying warning message in DEBUG mode otherwise... 00626 if (num_nodes_per_set[id] > 0) 00627 { 00628 ex_err = exII::ex_get_node_set(ex_id, 00629 nodeset_ids[id], 00630 &node_list[0]); 00631 00632 check_err(ex_err, "Error retrieving nodeset data."); 00633 message("Data retrieved successfully for nodeset: ", id); 00634 } 00635 } 00636 00637 00638 00639 void ExodusII_IO_Helper::print_sideset_info() 00640 { 00641 for (int i=0; i<num_elem_all_sidesets; i++) 00642 { 00643 libMesh::out << elem_list[i] << " " << side_list[i] << std::endl; 00644 } 00645 } 00646 00647 00648 00649 void ExodusII_IO_Helper::close() 00650 { 00651 // Always call close on processor 0. 00652 // If we're running on multiple processors, i.e. as one of several Nemesis files, 00653 // we call close on all processors... 00654 if ((libMesh::processor_id() == 0) || (!_run_only_on_proc0)) 00655 { 00656 ex_err = exII::ex_close(ex_id); 00657 check_err(ex_err, "Error closing Exodus file."); 00658 message("Exodus file closed successfully."); 00659 } 00660 } 00661 00662 00663 00664 int ExodusII_IO_Helper::inquire(int req_info_in, std::string error_msg) 00665 { 00666 ex_err = exII::ex_inquire(ex_id, 00667 req_info_in, 00668 &ret_int, 00669 &ret_float, 00670 &ret_char); 00671 00672 check_err(ex_err, error_msg); 00673 00674 return ret_int; 00675 } 00676 00677 00678 00679 const std::vector<Real>& ExodusII_IO_Helper::get_time_steps() 00680 { 00681 time_steps.resize(num_time_steps); 00682 exII::ex_get_all_times(ex_id, time_steps.empty() ? NULL : &time_steps[0]); 00683 return time_steps; 00684 } 00685 00686 00687 00688 const std::vector<std::string>& ExodusII_IO_Helper::get_nodal_var_names() 00689 { 00690 // Allocate enough space for our variable name strings. 00691 nodal_var_names.resize(num_nodal_vars); 00692 00693 // Use the vvc and strings objects to emulate the behavior of 00694 // a char** object. 00695 vvc.resize(num_nodal_vars); 00696 strings.resize(num_nodal_vars); 00697 for (int i=0;i<num_nodal_vars;i++) 00698 vvc[i].resize(MAX_STR_LENGTH+1); 00699 00700 for (int i=0;i<num_nodal_vars;i++) 00701 strings[i]=&(vvc[i][0]); // set pointer into vvc only *after* all resizing is complete 00702 00703 exII::ex_get_var_names(ex_id, 00704 "n", 00705 num_nodal_vars, 00706 &strings[0]//var_names 00707 ); 00708 00709 if (_verbose) 00710 { 00711 libMesh::out << "Read the variable(s) from the file:" << std::endl; 00712 for (int i=0; i<num_nodal_vars; i++) 00713 libMesh::out << "strings[" << i << "]=" << strings[i] << std::endl; 00714 } 00715 00716 00717 // Copy the char buffers into strings. 00718 for (int i=0;i<num_nodal_vars;i++) 00719 nodal_var_names[i]=strings[i]; // calls string::op=(const char*) 00720 00721 00722 return nodal_var_names; 00723 } 00724 00725 00726 00727 00728 const std::vector<Real>& ExodusII_IO_Helper::get_nodal_var_values(std::string nodal_var_name, int time_step) 00729 { 00730 nodal_var_values.resize(num_nodes); 00731 00732 this->get_nodal_var_names(); 00733 00734 // See if we can find the variable we are looking for 00735 unsigned int var_index = 0; 00736 bool found = false; 00737 00738 // Do a linear search for nodal_var_name in nodal_var_names 00739 for (; var_index<nodal_var_names.size(); ++var_index) 00740 { 00741 found = (nodal_var_names[var_index] == nodal_var_name); 00742 if (found) 00743 break; 00744 } 00745 00746 if (!found) 00747 { 00748 libMesh::err << "Unable to locate variable named: " << nodal_var_name << std::endl; 00749 libMesh::err << "Available variables: " << std::endl; 00750 for (unsigned int i=0; i<nodal_var_names.size(); ++i) 00751 libMesh::err << nodal_var_names[i] << std::endl; 00752 00753 libmesh_error(); 00754 } 00755 00756 exII::ex_get_nodal_var(ex_id, time_step, var_index+1, num_nodes, &nodal_var_values[0]); 00757 00758 return nodal_var_values; 00759 } 00760 00761 00762 00763 00764 // For Writing Solutions 00765 00766 void ExodusII_IO_Helper::create(std::string filename) 00767 { 00768 // If we're processor 0, always create the file. 00769 // If we running on all procs, e.g. as one of several Nemesis files, also 00770 // call create there. 00771 if ((libMesh::processor_id() == 0) || (!_run_only_on_proc0)) 00772 { 00773 //Fall back on double precision when necessary since ExodusII 00774 //doesn't seem to support long double 00775 comp_ws = std::min(sizeof(Real),sizeof(double)); 00776 io_ws = std::min(sizeof(Real),sizeof(double)); 00777 00778 ex_id = exII::ex_create(filename.c_str(), EX_CLOBBER, &comp_ws, &io_ws); 00779 00780 check_err(ex_id, "Error creating ExodusII mesh file."); 00781 00782 if (_verbose) 00783 libMesh::out << "File created successfully." << std::endl; 00784 } 00785 00786 _created = true; 00787 } 00788 00789 00790 00791 00792 void ExodusII_IO_Helper::initialize_discontinuous(std::string str_title, const MeshBase & mesh) 00793 { 00794 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 00795 return; 00796 00797 if (_use_mesh_dimension_instead_of_spatial_dimension) 00798 num_dim = mesh.mesh_dimension(); 00799 else 00800 num_dim = mesh.spatial_dimension(); 00801 00802 MeshBase::const_element_iterator it = mesh.active_elements_begin(); 00803 const MeshBase::const_element_iterator end = mesh.active_elements_end(); 00804 for ( ; it != end; ++it) 00805 num_nodes += (*it)->n_nodes(); 00806 00807 num_elem = mesh.n_elem(); 00808 00809 std::vector<boundary_id_type> unique_side_boundaries; 00810 std::vector<boundary_id_type> unique_node_boundaries; 00811 00812 mesh.boundary_info->build_side_boundary_ids(unique_side_boundaries); 00813 mesh.boundary_info->build_node_boundary_ids(unique_node_boundaries); 00814 00815 num_side_sets = unique_side_boundaries.size(); 00816 num_node_sets = unique_node_boundaries.size(); 00817 00818 //loop through element and map between block and element vector 00819 std::map<subdomain_id_type, std::vector<unsigned int> > subdomain_map; 00820 00821 for(it = mesh.active_elements_begin(); it != end; ++it) 00822 { 00823 const Elem * elem = *it; 00824 subdomain_id_type cur_subdomain = elem->subdomain_id(); 00825 00826 subdomain_map[cur_subdomain].push_back(elem->id()); 00827 } 00828 num_elem_blk = subdomain_map.size(); 00829 00830 if (str_title.size() > MAX_LINE_LENGTH) 00831 { 00832 libMesh::err << "Warning, Exodus files cannot have titles longer than " 00833 << MAX_LINE_LENGTH 00834 << " characters. Your title will be truncated." 00835 << std::endl; 00836 str_title.resize(MAX_LINE_LENGTH); 00837 } 00838 00839 ex_err = exII::ex_put_init(ex_id, 00840 str_title.c_str(), 00841 num_dim, 00842 num_nodes, 00843 num_elem, 00844 num_elem_blk, 00845 num_node_sets, 00846 num_side_sets); 00847 00848 check_err(ex_err, "Error initializing new Exodus file."); 00849 } 00850 00851 00852 00853 void ExodusII_IO_Helper::initialize(std::string str_title, const MeshBase & mesh) 00854 { 00855 // n_active_elem() is a parallel_only function 00856 unsigned int n_active_elem = mesh.n_active_elem(); 00857 00858 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 00859 return; 00860 00861 if (_use_mesh_dimension_instead_of_spatial_dimension) 00862 num_dim = mesh.mesh_dimension(); 00863 else 00864 num_dim = mesh.spatial_dimension(); 00865 00866 num_nodes = mesh.n_nodes(); 00867 num_elem = mesh.n_elem(); 00868 00869 std::vector<boundary_id_type> unique_side_boundaries; 00870 std::vector<boundary_id_type> unique_node_boundaries; 00871 00872 mesh.boundary_info->build_side_boundary_ids(unique_side_boundaries); 00873 mesh.boundary_info->build_node_boundary_ids(unique_node_boundaries); 00874 00875 num_side_sets = unique_side_boundaries.size(); 00876 num_node_sets = unique_node_boundaries.size(); 00877 00878 //loop through element and map between block and element vector 00879 std::map<subdomain_id_type, std::vector<unsigned int> > subdomain_map; 00880 00881 MeshBase::const_element_iterator it = mesh.active_elements_begin(); 00882 const MeshBase::const_element_iterator end = mesh.active_elements_end(); 00883 for (; it != end; ++it) 00884 { 00885 const Elem * elem = *it; 00886 subdomain_id_type cur_subdomain = elem->subdomain_id(); 00887 00888 subdomain_map[cur_subdomain].push_back(elem->id()); 00889 } 00890 num_elem_blk = subdomain_map.size(); 00891 00892 if (str_title.size() > MAX_LINE_LENGTH) 00893 { 00894 libMesh::err << "Warning, Exodus files cannot have titles longer than " 00895 << MAX_LINE_LENGTH 00896 << " characters. Your title will be truncated." 00897 << std::endl; 00898 str_title.resize(MAX_LINE_LENGTH); 00899 } 00900 00901 ex_err = exII::ex_put_init(ex_id, 00902 str_title.c_str(), 00903 num_dim, 00904 num_nodes, 00905 n_active_elem, 00906 num_elem_blk, 00907 num_node_sets, 00908 num_side_sets); 00909 00910 check_err(ex_err, "Error initializing new Exodus file."); 00911 } 00912 00913 00914 00915 void ExodusII_IO_Helper::write_nodal_coordinates(const MeshBase & mesh) 00916 { 00917 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 00918 return; 00919 00920 x.resize(num_nodes); 00921 y.resize(num_nodes); 00922 z.resize(num_nodes); 00923 00924 // Use a node iterator instead of looping over i! 00925 { 00926 unsigned i = 0; 00927 MeshBase::const_node_iterator it = mesh.nodes_begin(); 00928 const MeshBase::const_node_iterator end = mesh.nodes_end(); 00929 for ( ; it != end; ++it, ++i) 00930 { 00931 const Node* node = *it; 00932 00933 x[i] = (*node)(0); 00934 00935 #if LIBMESH_DIM > 1 00936 y[i]=(*node)(1); 00937 #else 00938 y[i]=0.; 00939 #endif 00940 #if LIBMESH_DIM > 2 00941 z[i]=(*node)(2); 00942 #else 00943 z[i]=0.; 00944 #endif 00945 } 00946 } 00947 00948 ex_err = exII::ex_put_coord(ex_id, 00949 x.empty() ? NULL : &x[0], 00950 y.empty() ? NULL : &y[0], 00951 z.empty() ? NULL : &z[0]); 00952 00953 check_err(ex_err, "Error writing coordinates to Exodus file."); 00954 } 00955 00956 00957 00958 void ExodusII_IO_Helper::write_nodal_coordinates_discontinuous(const MeshBase & mesh) 00959 { 00960 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 00961 return; 00962 00963 x.resize(num_nodes); 00964 y.resize(num_nodes); 00965 z.resize(num_nodes); 00966 00967 MeshBase::const_element_iterator it = mesh.active_elements_begin(); 00968 const MeshBase::const_element_iterator end = mesh.active_elements_end(); 00969 00970 unsigned int i = 0; 00971 for ( ; it != end; ++it) 00972 for (unsigned int n=0; n<(*it)->n_nodes(); n++) 00973 { 00974 x[i]=(*it)->point(n)(0); 00975 #if LIBMESH_DIM > 1 00976 y[i]=(*it)->point(n)(1); 00977 #else 00978 y[i]=0.; 00979 #endif 00980 #if LIBMESH_DIM > 2 00981 z[i]=(*it)->point(n)(2); 00982 #else 00983 z[i]=0.; 00984 #endif 00985 i++; 00986 } 00987 00988 ex_err = exII::ex_put_coord(ex_id, 00989 x.empty() ? NULL : &x[0], 00990 y.empty() ? NULL : &y[0], 00991 z.empty() ? NULL : &z[0]); 00992 00993 check_err(ex_err, "Error writing coordinates to Exodus file."); 00994 } 00995 00996 00997 00998 void ExodusII_IO_Helper::write_elements(const MeshBase & mesh) 00999 { 01000 // n_active_elem() is a parallel_only function 01001 unsigned int n_active_elem = mesh.n_active_elem(); 01002 01003 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01004 return; 01005 01006 std::map<unsigned int, std::vector<unsigned int> > subdomain_map; 01007 01008 MeshBase::const_element_iterator mesh_it = mesh.active_elements_begin(); 01009 const MeshBase::const_element_iterator end = mesh.active_elements_end(); 01010 //loop through element and map between block and element vector 01011 for (; mesh_it != end; ++mesh_it) 01012 { 01013 const Elem * elem = *mesh_it; 01014 01015 unsigned int cur_subdomain = elem->subdomain_id(); 01016 01017 subdomain_map[cur_subdomain].push_back(elem->id()); 01018 } 01019 01020 std::vector<int> elem_num_map_out; 01021 01022 std::map<unsigned int, std::vector<unsigned int> >::iterator it; 01023 01024 // element map vector 01025 num_elem_blk = subdomain_map.size(); 01026 block_ids.resize(num_elem_blk); 01027 std::vector<unsigned int> elem_map(n_active_elem); 01028 std::vector<unsigned int>::iterator curr_elem_map_end = elem_map.begin(); 01029 01030 // Note: It appears that there is a bug in exodusII::ex_put_name where 01031 // the index returned from the ex_id_lkup is erronously used. For now 01032 // the work around is to use the alternative function ex_put_names, but 01033 // this function requires a char** datastructure. 01034 NamesData names_table(num_elem_blk); 01035 01036 unsigned int counter=0; 01037 for(it = subdomain_map.begin() ; it != subdomain_map.end(); it++) 01038 { 01039 block_ids[counter] = (*it).first; 01040 names_table.push_back_entry(mesh.subdomain_name((*it).first)); 01041 01042 std::vector<unsigned int> & tmp_vec = (*it).second; 01043 01044 ExodusII_IO_Helper::ElementMaps em; 01045 01046 //Use the first element in this block to get representative information. 01047 //Note that Exodus assumes all elements in a block are of the same type! 01048 //We are using that same assumption here! 01049 const ExodusII_IO_Helper::Conversion conv = em.assign_conversion(mesh.elem(tmp_vec[0])->type()); 01050 num_nodes_per_elem = mesh.elem(tmp_vec[0])->n_nodes(); 01051 01052 ex_err = exII::ex_put_elem_block(ex_id, (*it).first, conv.exodus_elem_type().c_str(), tmp_vec.size(),num_nodes_per_elem,0); 01053 01054 check_err(ex_err, "Error writing element block."); 01055 01056 connect.resize(tmp_vec.size()*num_nodes_per_elem); 01057 01058 for (unsigned int i=0; i<tmp_vec.size(); i++) 01059 { 01060 unsigned int elem_id = tmp_vec[i]; 01061 elem_num_map_out.push_back(elem_id); 01062 libmesh_elem_num_to_exodus[elem_id] = elem_num_map_out.size(); 01063 01064 const Elem* elem = mesh.elem(elem_id); 01065 01066 // Exodus/Nemesis want every block to have the same element type 01067 // libmesh_assert_equal_to (elem->type(), conv.get_canonical_type()); 01068 01069 // But we can get away with writing e.g. HEX8 and INFHEX8 in 01070 // the same block... 01071 libmesh_assert_equal_to (elem->n_nodes(), Elem::build(conv.get_canonical_type(), NULL)->n_nodes()); 01072 01073 for (unsigned int j=0; j < static_cast<unsigned int>(num_nodes_per_elem); j++) 01074 { 01075 const unsigned int connect_index = (i*num_nodes_per_elem)+j; 01076 const unsigned int elem_node_index = conv.get_inverse_node_map(j); // inverse node map is for writing. 01077 if (_verbose) 01078 { 01079 libMesh::out << "Exodus node index: " << j 01080 << "=LibMesh node index " << elem_node_index << std::endl; 01081 } 01082 connect[connect_index] = elem->node(elem_node_index)+1; 01083 } 01084 } 01085 ex_err = exII::ex_put_elem_conn(ex_id, (*it).first, &connect[0]); 01086 check_err(ex_err, "Error writing element connectivities"); 01087 01088 // write out the element number map 01089 curr_elem_map_end = std::transform(tmp_vec.begin(), tmp_vec.end(), curr_elem_map_end, 01090 std::bind2nd(std::plus<unsigned int>(), 1)); // Add one to each id for exodus! 01091 ex_err = exII::ex_put_elem_num_map(ex_id, (int *)&elem_map[0]); 01092 check_err(ex_err, "Error writing element map"); 01093 01094 counter++; 01095 } 01096 // ex_err = exII::ex_put_elem_num_map(ex_id, &elem_num_map_out[0]); 01097 check_err(ex_err, "Error writing element connectivities"); 01098 01099 // Write out the block names 01100 ex_err = names_table.write_to_exodus(ex_id, exII::EX_ELEM_BLOCK); 01101 check_err(ex_err, "Error writing element names"); 01102 } 01103 01104 01105 01106 01107 void ExodusII_IO_Helper::write_elements_discontinuous(const MeshBase & mesh) 01108 { 01109 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01110 return; 01111 01112 std::map<unsigned int, std::vector<unsigned int> > subdomain_map; 01113 01114 MeshBase::const_element_iterator mesh_it = mesh.active_elements_begin(); 01115 const MeshBase::const_element_iterator end = mesh.active_elements_end(); 01116 //loop through element and map between block and element vector 01117 for(; mesh_it != end; ++mesh_it) 01118 { 01119 const Elem * elem = *mesh_it; 01120 01121 //Only write out the active elements 01122 if(elem->active()) 01123 { 01124 unsigned int cur_subdomain = elem->subdomain_id(); 01125 01126 subdomain_map[cur_subdomain].push_back(elem->id()); 01127 } 01128 } 01129 01130 std::vector<int> elem_num_map_out; 01131 01132 std::map<unsigned int, std::vector<unsigned int> >::iterator it; 01133 01134 for(it = subdomain_map.begin() ; it != subdomain_map.end(); it++) 01135 { 01136 std::vector<unsigned int> & tmp_vec = (*it).second; 01137 01138 ExodusII_IO_Helper::ElementMaps em; 01139 01140 //Use the first element in this block to get representative information. 01141 //Note that Exodus assumes all elements in a block are of the same type! 01142 //We are using that same assumption here! 01143 const ExodusII_IO_Helper::Conversion conv = em.assign_conversion(mesh.elem(tmp_vec[0])->type()); 01144 num_nodes_per_elem = mesh.elem(tmp_vec[0])->n_nodes(); 01145 01146 ex_err = exII::ex_put_elem_block(ex_id, (*it).first, conv.exodus_elem_type().c_str(), tmp_vec.size(),num_nodes_per_elem,0); 01147 01148 check_err(ex_err, "Error writing element block."); 01149 01150 connect.resize(tmp_vec.size()*num_nodes_per_elem); 01151 01152 for (unsigned int i=0; i<tmp_vec.size(); i++) 01153 { 01154 unsigned int elem_id = tmp_vec[i]; 01155 elem_num_map_out.push_back(elem_id); 01156 libmesh_elem_num_to_exodus[elem_id] = elem_num_map_out.size(); 01157 01158 for (unsigned int j=0; j < static_cast<unsigned int>(num_nodes_per_elem); j++) 01159 { 01160 const unsigned int connect_index = (i*num_nodes_per_elem)+j; 01161 const unsigned int elem_node_index = conv.get_inverse_node_map(j); // Inverse node map is for writing 01162 if (_verbose) 01163 { 01164 libMesh::out << "Exodus node index: " << j 01165 << "=LibMesh node index " << elem_node_index << std::endl; 01166 } 01167 connect[connect_index] = i*num_nodes_per_elem+elem_node_index+1; 01168 } 01169 } 01170 ex_err = exII::ex_put_elem_conn(ex_id, (*it).first, &connect[0]); 01171 check_err(ex_err, "Error writing element connectivities"); 01172 01173 // write out the element number map 01174 std::vector<unsigned int> elem_map(tmp_vec.size()); 01175 std::transform(tmp_vec.begin(), tmp_vec.end(), elem_map.begin(), 01176 std::bind2nd(std::plus<unsigned int>(), 1)); // Add one to each id for exodus! 01177 ex_err = exII::ex_put_elem_num_map(ex_id, (int *)&elem_map[0]); 01178 check_err(ex_err, "Error writing element map"); 01179 } 01180 01181 // ex_err = exII::ex_put_elem_num_map(ex_id, &elem_num_map_out[0]); 01182 check_err(ex_err, "Error writing element connectivities"); 01183 01184 ex_err = exII::ex_update(ex_id); 01185 check_err(ex_err, "Error flushing buffers to file."); 01186 } 01187 01188 01189 01190 void ExodusII_IO_Helper::write_sidesets(const MeshBase & mesh) 01191 { 01192 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01193 return; 01194 01195 ExodusII_IO_Helper::ElementMaps em; 01196 01197 std::vector< dof_id_type > el; 01198 std::vector< unsigned short int > sl; 01199 std::vector< boundary_id_type > il; 01200 01201 mesh.boundary_info->build_side_list(el, sl, il); 01202 01203 //Maps from sideset id to the element and sides 01204 std::map<int, std::vector<int> > elem; 01205 std::map<int, std::vector<int> > side; 01206 01207 //Accumulate the vectors to pass into ex_put_side_set 01208 for(unsigned int i = 0; i < el.size(); i++) 01209 { 01210 std::vector<const Elem *> family; 01211 #ifdef LIBMESH_ENABLE_AMR 01212 01216 mesh.elem(el[i])->active_family_tree_by_side(family, sl[i], false); 01217 #else 01218 family.push_back(mesh.elem(el[i])); 01219 #endif 01220 01221 for(unsigned int j = 0; j < family.size(); ++j) 01222 { 01223 const ExodusII_IO_Helper::Conversion conv = em.assign_conversion(mesh.elem(family[j]->id())->type()); 01224 01225 // Use the libmesh to exodus datastructure map to get the proper sideset IDs 01226 // The datastructure contains the "collapsed" contiguous ids 01227 elem[il[i]].push_back(libmesh_elem_num_to_exodus[family[j]->id()]); 01228 side[il[i]].push_back(conv.get_inverse_side_map(sl[i])); 01229 } 01230 } 01231 01232 std::vector<boundary_id_type> side_boundary_ids; 01233 mesh.boundary_info->build_side_boundary_ids(side_boundary_ids); 01234 NamesData names_table(side_boundary_ids.size()); 01235 01236 for(unsigned int i = 0; i < side_boundary_ids.size(); i++) 01237 { 01238 int ss_id = side_boundary_ids[i]; 01239 01240 int actual_id = ss_id; 01241 01242 names_table.push_back_entry(mesh.boundary_info->sideset_name(ss_id)); 01243 01244 ex_err = exII::ex_put_side_set_param(ex_id, actual_id, elem[ss_id].size(), 0); 01245 check_err(ex_err, "Error writing sideset parameters"); 01246 01247 ex_err = exII::ex_put_side_set(ex_id, actual_id, &elem[ss_id][0], &side[ss_id][0]); 01248 check_err(ex_err, "Error writing sidesets"); 01249 } 01250 01251 // Write out the sideset names 01252 ex_err = names_table.write_to_exodus(ex_id, exII::EX_SIDE_SET); 01253 check_err(ex_err, "Error writing sideset names"); 01254 } 01255 01256 01257 01258 void ExodusII_IO_Helper::write_nodesets(const MeshBase & mesh) 01259 { 01260 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01261 return; 01262 01263 // FIXME: This is not used, should it be? 01264 ExodusII_IO_Helper::ElementMaps em; 01265 01266 std::vector< dof_id_type > nl; 01267 std::vector< boundary_id_type > il; 01268 01269 mesh.boundary_info->build_node_list(nl, il); 01270 01271 //Maps from nodeset id to the nodes 01272 std::map<boundary_id_type, std::vector<int> > node; 01273 01274 //Accumulate the vectors to pass into ex_put_node_set 01275 for(unsigned int i = 0; i < nl.size(); i++) 01276 node[il[i]].push_back(nl[i]+1); 01277 01278 std::vector<boundary_id_type> node_boundary_ids; 01279 mesh.boundary_info->build_node_boundary_ids(node_boundary_ids); 01280 NamesData names_table(node_boundary_ids.size()); 01281 01282 for(unsigned int i = 0; i < node_boundary_ids.size(); i++) 01283 { 01284 int nodeset_id = node_boundary_ids[i]; 01285 01286 int actual_id = nodeset_id; 01287 01288 names_table.push_back_entry(mesh.boundary_info->nodeset_name(nodeset_id)); 01289 01290 ex_err = exII::ex_put_node_set_param(ex_id, actual_id, node[nodeset_id].size(), 0); 01291 check_err(ex_err, "Error writing nodeset parameters"); 01292 01293 ex_err = exII::ex_put_node_set(ex_id, actual_id, &node[nodeset_id][0]); 01294 check_err(ex_err, "Error writing nodesets"); 01295 } 01296 01297 // Write out the nodeset names 01298 ex_err = names_table.write_to_exodus(ex_id, exII::EX_NODE_SET); 01299 check_err(ex_err, "Error writing nodeset names"); 01300 } 01301 01302 01303 01304 void ExodusII_IO_Helper::initialize_element_variables(const MeshBase & /* mesh */, 01305 std::vector<std::string> names) 01306 { 01307 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01308 return; 01309 01310 num_elem_vars = names.size(); 01311 01312 if ( num_elem_vars == 0 ) 01313 return; 01314 01315 if (_elem_vars_initialized) 01316 return; 01317 _elem_vars_initialized = true; 01318 01319 ex_err = exII::ex_put_var_param(ex_id, "e", num_elem_vars); 01320 check_err(ex_err, "Error setting number of element vars."); 01321 01322 // Form the element variable truth table and send to Exodus. 01323 // This tells which variables are written to which blocks, 01324 // and can dramatically speed up writing element variables 01325 01326 // We really should initialize all entries in the truth table to 0 01327 // and then loop over all subdomains, setting their entries to 1 01328 // if a given variable exists on that subdomain. However, 01329 // we don't have that information, and the element variables 01330 // passed to us are padded with zeroes for the blocks where 01331 // they aren't defined. To be consistent with that, fill 01332 // the truth table with ones. 01333 01334 std::vector<int> truth_tab(num_elem_blk*num_elem_vars,1); 01335 ex_err = exII::ex_put_elem_var_tab(ex_id, num_elem_blk, num_elem_vars, &truth_tab[0]); 01336 check_err(ex_err, "Error writing element truth table."); 01337 01338 // Use the vvc and strings objects to emulate the behavior of 01339 // a char** object. 01340 vvc.resize(num_elem_vars); 01341 strings.resize(num_elem_vars); 01342 01343 // For each string in names, allocate enough space in vvc and copy from 01344 // the C++ string into vvc for passing to the C interface. 01345 for (int i=0; i<num_elem_vars; ++i) 01346 { 01347 // Note: the one additional character is to hold the trailing '\0' 01348 vvc[i].resize(names[i].size() + 1); 01349 //std::strcpy(&(vvc[i][0]), names[i].c_str()); 01350 vvc[i][ names[i].copy(&vvc[i][0], vvc[i].size()-1) ] = '\0'; 01351 } 01352 01353 for (int i=0; i<num_elem_vars; ++i) 01354 strings[i] = &(vvc[i][0]); // set pointer into vvc only *after* all resizing is complete 01355 01356 if (_verbose) 01357 { 01358 libMesh::out << "Writing variable name(s) to file: " << std::endl; 01359 for (int i=0; i < num_elem_vars; ++i) 01360 libMesh::out << "strings[" << i << "]=" << strings[i] << std::endl; 01361 } 01362 01363 ex_err = exII::ex_put_var_names(ex_id, 01364 "e", 01365 num_elem_vars, 01366 &strings[0]//var_names 01367 ); 01368 01369 check_err(ex_err, "Error setting element variable names."); 01370 } 01371 01372 01373 01374 void ExodusII_IO_Helper::initialize_nodal_variables(std::vector<std::string> names) 01375 { 01376 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01377 return; 01378 01379 num_nodal_vars = names.size(); 01380 01381 ex_err = exII::ex_put_var_param(ex_id, "n", num_nodal_vars); 01382 check_err(ex_err, "Error setting number of nodal vars."); 01383 01384 // Use the vvc and strings objects to emulate the behavior of 01385 // a char** object. 01386 vvc.resize(num_nodal_vars); 01387 strings.resize(num_nodal_vars); 01388 01389 // For each string in names, allocate enough space in vvc and copy from 01390 // the C++ string into vvc for passing to the C interface. 01391 for (int i=0; i<num_nodal_vars; i++) 01392 { 01393 vvc[i].resize(names[i].size()+1); 01394 //std::strcpy(&(vvc[i][0]), names[i].c_str()); 01395 vvc[i][ names[i].copy(&vvc[i][0], vvc[i].size()-1) ] = '\0'; 01396 } 01397 01398 for (int i=0; i<num_nodal_vars; i++) 01399 strings[i] = &(vvc[i][0]); // set pointer into vvc only *after* all resizing is complete 01400 01401 if (_verbose) 01402 { 01403 libMesh::out << "Writing variable name(s) to file: " << std::endl; 01404 for (int i=0;i<num_nodal_vars;i++) 01405 libMesh::out << "strings[" << i << "]=" << strings[i] << std::endl; 01406 } 01407 01408 ex_err = exII::ex_put_var_names(ex_id, 01409 "n", 01410 num_nodal_vars, 01411 strings.empty() ? NULL : &strings[0]//var_names 01412 ); 01413 01414 check_err(ex_err, "Error setting nodal variable names."); 01415 } 01416 01417 01418 01419 void ExodusII_IO_Helper::initialize_global_variables(const std::vector<std::string> & names) 01420 { 01421 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01422 return; 01423 01424 if (_global_vars_initialized) 01425 { 01426 return; 01427 } 01428 _global_vars_initialized = true; 01429 01430 num_globals = names.size(); 01431 01432 ex_err = exII::ex_put_var_param(ex_id, "g", num_globals); 01433 check_err(ex_err, "Error setting number of global vars."); 01434 01435 // Use the vvc and strings objects to emulate the behavior of 01436 // a char** object. 01437 vvc.resize(num_globals); 01438 strings.resize(num_globals); 01439 01440 // For each string in names, allocate enough space in vvc and copy from 01441 // the C++ string into vvc for passing to the C interface. 01442 for (int i=0; i<num_globals; i++) 01443 { 01444 vvc[i].resize(names[i].size()+1); 01445 // std::strcpy(&(vvc[i][0]), names[i].c_str()); 01446 vvc[i][ names[i].copy(&vvc[i][0], vvc[i].size()-1) ] = '\0'; 01447 } 01448 01449 for (int i=0; i<num_globals; i++) 01450 strings[i] = &(vvc[i][0]); // set pointer into vvc only *after* all resizing is complete 01451 01452 if (_verbose) 01453 { 01454 libMesh::out << "Writing variable name(s) to file: " << std::endl; 01455 for (int i=0; i < num_globals; ++i) 01456 libMesh::out << "strings[" << i << "]=" << strings[i] << std::endl; 01457 } 01458 01459 ex_err = exII::ex_put_var_names(ex_id, 01460 "g", 01461 num_globals, 01462 &strings[0] 01463 ); 01464 01465 check_err(ex_err, "Error setting global variable names."); 01466 } 01467 01468 01469 01470 void ExodusII_IO_Helper::write_timestep(int timestep, Real time) 01471 { 01472 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01473 return; 01474 01475 ex_err = exII::ex_put_time(ex_id, timestep, &time); 01476 check_err(ex_err, "Error writing timestep."); 01477 01478 ex_err = exII::ex_update(ex_id); 01479 check_err(ex_err, "Error flushing buffers to file."); 01480 } 01481 01482 01483 01484 void ExodusII_IO_Helper::write_element_values(const MeshBase & mesh, const std::vector<Number> & values, int timestep) 01485 { 01486 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01487 return; 01488 01489 // Loop over the element blocks and write the data one block at a time 01490 std::map<unsigned int, std::vector<unsigned int> > subdomain_map; 01491 01492 const unsigned int num_vars = values.size() / num_elem; 01493 01494 MeshBase::const_element_iterator mesh_it = mesh.active_elements_begin(); 01495 const MeshBase::const_element_iterator end = mesh.active_elements_end(); 01496 //loop through element and map between block and element vector 01497 for( ; mesh_it != end; ++mesh_it) 01498 { 01499 const Elem * elem = *mesh_it; 01500 01501 //Only write out the active elements 01502 if(elem->active()) 01503 { 01504 unsigned int cur_subdomain = elem->subdomain_id(); 01505 01506 subdomain_map[cur_subdomain].push_back(elem->id()); 01507 } 01508 } 01509 01510 for (unsigned int l=0; l < num_vars; ++l) 01511 { 01512 // The size of the subdomain map is the number of blocks. 01513 std::map<unsigned int, std::vector<unsigned int> >::iterator it( subdomain_map.begin() ); 01514 01515 for(unsigned int j=0; it != subdomain_map.end(); ++it, ++j) 01516 { 01517 const std::vector<unsigned int> & elem_nums = (*it).second; 01518 const unsigned int num_elems_this_block = elem_nums.size(); 01519 std::vector<Number> data( num_elems_this_block ); 01520 for (unsigned int k=0; k < num_elems_this_block; ++k) 01521 { 01522 data[k] = values[l*num_elem+elem_nums[k]]; 01523 } 01524 01525 ex_err = exII::ex_put_elem_var(ex_id, timestep, l+1, get_block_id(j), num_elems_this_block, &data[0]); 01526 check_err(ex_err, "Error writing element values."); 01527 01528 } 01529 } 01530 01531 ex_err = exII::ex_update(ex_id); 01532 check_err(ex_err, "Error flushing buffers to file."); 01533 } 01534 01535 01536 01537 void ExodusII_IO_Helper::write_nodal_values(int var_id, const std::vector<Number> & values, int timestep) 01538 { 01539 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01540 return; 01541 01542 ex_err = exII::ex_put_nodal_var(ex_id, timestep, var_id, num_nodes, &values[0]); 01543 check_err(ex_err, "Error writing nodal values."); 01544 01545 ex_err = exII::ex_update(ex_id); 01546 check_err(ex_err, "Error flushing buffers to file."); 01547 } 01548 01549 01550 01551 void ExodusII_IO_Helper::write_information_records(const std::vector<std::string>& records) 01552 { 01553 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01554 return; 01555 01556 int num_records = records.size(); 01557 std::vector<char*> info(num_records); 01558 01559 // This is an abuse of the const char* returned by std::string, we trust that Exodus won't 01560 // modify these when it's writing them out... 01561 for (unsigned i=0; i<records.size(); ++i) 01562 { 01563 // Records cannot be longer than MAX_LINE_LENGTH, as defined in exodusII.h 01564 if (records[i].size() > MAX_LINE_LENGTH) 01565 { 01566 libMesh::err << "Error, cannot write records longer than " << MAX_LINE_LENGTH << " characters!" << std::endl; 01567 libmesh_error(); 01568 } 01569 01570 info[i] = const_cast<char*>(records[i].c_str()); 01571 } 01572 01573 ex_err = exII::ex_put_info(ex_id, num_records, &info[0]); 01574 check_err(ex_err, "Error writing global values."); 01575 01576 ex_err = exII::ex_update(ex_id); 01577 check_err(ex_err, "Error flushing buffers to file."); 01578 } 01579 01580 01581 01582 void ExodusII_IO_Helper::write_global_values(const std::vector<Number> & values, int timestep) 01583 { 01584 if ((_run_only_on_proc0) && (libMesh::processor_id() != 0)) 01585 return; 01586 01587 ex_err = exII::ex_put_glob_vars(ex_id, timestep, num_globals, &values[0]); 01588 check_err(ex_err, "Error writing global values."); 01589 01590 ex_err = exII::ex_update(ex_id); 01591 check_err(ex_err, "Error flushing buffers to file."); 01592 } 01593 01594 01595 01596 void ExodusII_IO_Helper::use_mesh_dimension_instead_of_spatial_dimension(bool val) 01597 { 01598 _use_mesh_dimension_instead_of_spatial_dimension = val; 01599 } 01600 01601 01602 01603 01604 bool ExodusII_IO_Helper::created() 01605 { 01606 return _created; 01607 } 01608 01609 01610 01611 // ------------------------------------------------------------ 01612 // ExodusII_IO_Helper::Conversion class members 01613 ExodusII_IO_Helper::Conversion ExodusII_IO_Helper::ElementMaps::assign_conversion(std::string type_str) 01614 { 01615 init_element_equivalence_map(); 01616 01617 // Do only upper-case comparisons 01618 std::transform(type_str.begin(), type_str.end(), type_str.begin(), ::toupper); 01619 01620 std::map<std::string, libMeshEnums::ElemType>::iterator it = 01621 element_equivalence_map.find(type_str); 01622 01623 if (it != element_equivalence_map.end()) 01624 return assign_conversion( it->second ); 01625 else 01626 { 01627 libMesh::err << "ERROR! Unrecognized element type_str: " << type_str << std::endl; 01628 libmesh_error(); 01629 } 01630 01631 libmesh_error(); 01632 01633 // dummy return value, we won't get here 01634 return assign_conversion (EDGE2); 01635 } 01636 01637 01638 01639 ExodusII_IO_Helper::Conversion ExodusII_IO_Helper::ElementMaps::assign_conversion(const ElemType type) 01640 { 01641 switch (type) 01642 { 01643 case EDGE2: 01644 { 01645 const Conversion conv(edge2_node_map, 01646 ARRAY_LENGTH(edge2_node_map), 01647 edge2_node_map, // inverse node map same as forward node map 01648 ARRAY_LENGTH(edge2_node_map), 01649 edge_edge_map, 01650 ARRAY_LENGTH(edge_edge_map), 01651 edge_inverse_edge_map, 01652 ARRAY_LENGTH(edge_inverse_edge_map), 01653 EDGE2, "EDGE2"); 01654 return conv; 01655 } 01656 case EDGE3: 01657 { 01658 const Conversion conv(edge3_node_map, 01659 ARRAY_LENGTH(edge3_node_map), 01660 edge3_node_map, // inverse node map same as forward node map 01661 ARRAY_LENGTH(edge3_node_map), 01662 edge_edge_map, 01663 ARRAY_LENGTH(edge_edge_map), 01664 edge_inverse_edge_map, 01665 ARRAY_LENGTH(edge_inverse_edge_map), 01666 EDGE3, "EDGE3"); 01667 return conv; 01668 } 01669 case QUAD4: 01670 { 01671 const Conversion conv(quad4_node_map, 01672 ARRAY_LENGTH(quad4_node_map), 01673 quad4_node_map, // inverse node map same as forward node map 01674 ARRAY_LENGTH(quad4_node_map), 01675 quad_edge_map, 01676 ARRAY_LENGTH(quad_edge_map), 01677 quad_inverse_edge_map, 01678 ARRAY_LENGTH(quad_inverse_edge_map), 01679 QUAD4, 01680 "QUAD4"); 01681 return conv; 01682 } 01683 01684 case QUAD8: 01685 { 01686 const Conversion conv(quad8_node_map, 01687 ARRAY_LENGTH(quad8_node_map), 01688 quad8_node_map, // inverse node map same as forward node map 01689 ARRAY_LENGTH(quad8_node_map), 01690 quad_edge_map, 01691 ARRAY_LENGTH(quad_edge_map), 01692 quad_inverse_edge_map, 01693 ARRAY_LENGTH(quad_inverse_edge_map), 01694 QUAD8, 01695 "QUAD8"); 01696 return conv; 01697 } 01698 01699 case QUAD9: 01700 { 01701 const Conversion conv(quad9_node_map, 01702 ARRAY_LENGTH(quad9_node_map), 01703 quad9_node_map, // inverse node map same as forward node map 01704 ARRAY_LENGTH(quad9_node_map), 01705 quad_edge_map, 01706 ARRAY_LENGTH(quad_edge_map), 01707 quad_inverse_edge_map, 01708 ARRAY_LENGTH(quad_inverse_edge_map), 01709 QUAD9, 01710 "QUAD9"); 01711 return conv; 01712 } 01713 01714 case TRI3: 01715 { 01716 const Conversion conv(tri3_node_map, 01717 ARRAY_LENGTH(tri3_node_map), 01718 tri3_node_map, // inverse node map same as forward node map 01719 ARRAY_LENGTH(tri3_node_map), 01720 tri_edge_map, 01721 ARRAY_LENGTH(tri_edge_map), 01722 tri_inverse_edge_map, 01723 ARRAY_LENGTH(tri_inverse_edge_map), 01724 TRI3, 01725 "TRI3"); 01726 return conv; 01727 } 01728 01729 case TRI6: 01730 { 01731 const Conversion conv(tri6_node_map, 01732 ARRAY_LENGTH(tri6_node_map), 01733 tri6_node_map, // inverse node map same as forward node map 01734 ARRAY_LENGTH(tri6_node_map), 01735 tri_edge_map, 01736 ARRAY_LENGTH(tri_edge_map), 01737 tri_inverse_edge_map, 01738 ARRAY_LENGTH(tri_inverse_edge_map), 01739 TRI6, 01740 "TRI6"); 01741 return conv; 01742 } 01743 01744 case HEX8: 01745 { 01746 const Conversion conv(hex8_node_map, 01747 ARRAY_LENGTH(hex8_node_map), 01748 hex8_node_map, // inverse node map same as forward node map 01749 ARRAY_LENGTH(hex8_node_map), 01750 hex_face_map, 01751 ARRAY_LENGTH(hex_face_map), 01752 hex_inverse_face_map, 01753 ARRAY_LENGTH(hex_inverse_face_map), 01754 HEX8, 01755 "HEX8"); 01756 return conv; 01757 } 01758 01759 case HEX20: 01760 { 01761 const Conversion conv(hex20_node_map, 01762 ARRAY_LENGTH(hex20_node_map), 01763 hex20_node_map, // inverse node map same as forward node map 01764 ARRAY_LENGTH(hex20_node_map), 01765 hex_face_map, 01766 ARRAY_LENGTH(hex_face_map), 01767 hex_inverse_face_map, 01768 ARRAY_LENGTH(hex_inverse_face_map), 01769 HEX20, 01770 "HEX20"); 01771 return conv; 01772 } 01773 01774 case HEX27: 01775 { 01776 const Conversion conv(hex27_node_map, 01777 ARRAY_LENGTH(hex27_node_map), 01778 hex27_inverse_node_map, // different inverse node map for Hex27! 01779 ARRAY_LENGTH(hex27_inverse_node_map), 01780 hex27_face_map, 01781 ARRAY_LENGTH(hex27_face_map), 01782 hex27_inverse_face_map, 01783 ARRAY_LENGTH(hex27_inverse_face_map), 01784 HEX27, 01785 "HEX27"); 01786 return conv; 01787 } 01788 01789 case TET4: 01790 { 01791 const Conversion conv(tet4_node_map, 01792 ARRAY_LENGTH(tet4_node_map), 01793 tet4_node_map, // inverse node map same as forward node map 01794 ARRAY_LENGTH(tet4_node_map), 01795 tet_face_map, 01796 ARRAY_LENGTH(tet_face_map), 01797 tet_inverse_face_map, 01798 ARRAY_LENGTH(tet_inverse_face_map), 01799 TET4, 01800 "TETRA4"); 01801 return conv; 01802 } 01803 01804 case TET10: 01805 { 01806 const Conversion conv(tet10_node_map, 01807 ARRAY_LENGTH(tet10_node_map), 01808 tet10_node_map, // inverse node map same as forward node map 01809 ARRAY_LENGTH(tet10_node_map), 01810 tet_face_map, 01811 ARRAY_LENGTH(tet_face_map), 01812 tet_inverse_face_map, 01813 ARRAY_LENGTH(tet_inverse_face_map), 01814 TET10, 01815 "TETRA10"); 01816 return conv; 01817 } 01818 01819 case PRISM6: 01820 { 01821 const Conversion conv(prism6_node_map, 01822 ARRAY_LENGTH(prism6_node_map), 01823 prism6_node_map, // inverse node map same as forward node map 01824 ARRAY_LENGTH(prism6_node_map), 01825 prism_face_map, 01826 ARRAY_LENGTH(prism_face_map), 01827 prism_inverse_face_map, 01828 ARRAY_LENGTH(prism_inverse_face_map), 01829 PRISM6, 01830 "WEDGE"); 01831 return conv; 01832 } 01833 01834 case PRISM15: 01835 { 01836 const Conversion conv(prism15_node_map, 01837 ARRAY_LENGTH(prism15_node_map), 01838 prism15_node_map, // inverse node map same as forward node map 01839 ARRAY_LENGTH(prism15_node_map), 01840 prism_face_map, 01841 ARRAY_LENGTH(prism_face_map), 01842 prism_inverse_face_map, 01843 ARRAY_LENGTH(prism_inverse_face_map), 01844 PRISM15, 01845 "WEDGE15"); 01846 return conv; 01847 } 01848 01849 case PRISM18: 01850 { 01851 const Conversion conv(prism18_node_map, 01852 ARRAY_LENGTH(prism18_node_map), 01853 prism18_node_map, // inverse node map same as forward node map 01854 ARRAY_LENGTH(prism18_node_map), 01855 prism_face_map, 01856 ARRAY_LENGTH(prism_face_map), 01857 prism_inverse_face_map, 01858 ARRAY_LENGTH(prism_inverse_face_map), 01859 PRISM18, 01860 "WEDGE18"); 01861 return conv; 01862 } 01863 01864 case PYRAMID5: 01865 { 01866 const Conversion conv(pyramid5_node_map, 01867 ARRAY_LENGTH(pyramid5_node_map), 01868 pyramid5_node_map, // inverse node map same as forward node map 01869 ARRAY_LENGTH(pyramid5_node_map), 01870 pyramid_face_map, 01871 ARRAY_LENGTH(pyramid_face_map), 01872 pyramid_inverse_face_map, 01873 ARRAY_LENGTH(pyramid_inverse_face_map), 01874 PYRAMID5, 01875 "PYRAMID5"); 01876 return conv; 01877 } 01878 01879 default: 01880 libmesh_error(); 01881 } 01882 01883 libmesh_error(); 01884 01885 // dummy return value, we will never get here 01886 const Conversion conv(tri3_node_map, 01887 ARRAY_LENGTH(tri3_node_map), 01888 tri3_node_map, // inverse node map same as forward node map 01889 ARRAY_LENGTH(tri3_node_map), 01890 tri_edge_map, 01891 ARRAY_LENGTH(tri_edge_map), 01892 tri_inverse_edge_map, 01893 ARRAY_LENGTH(tri_inverse_edge_map), 01894 TRI3, 01895 "TRI3"); 01896 return conv; 01897 } 01898 01899 01900 01901 ExodusII_IO_Helper::NamesData::NamesData(size_t size) : 01902 data_table(new char *[size]), 01903 counter(0), 01904 table_size(size) 01905 { 01906 for (size_t i=0; i<size; ++i) 01907 data_table[i] = new char[MAX_STR_LENGTH]; 01908 } 01909 01910 01911 01912 ExodusII_IO_Helper::NamesData::~NamesData() 01913 { 01914 for (size_t i=0; i<table_size; ++i) 01915 delete [] data_table[i]; 01916 delete [] data_table; 01917 } 01918 01919 01920 01921 void ExodusII_IO_Helper::NamesData::push_back_entry(const std::string & name) 01922 { 01923 libmesh_assert_less (counter, table_size); 01924 01925 data_table[counter][ name.copy(data_table[counter], name.length()) ] = '\0'; 01926 ++counter; 01927 } 01928 01929 01930 01931 int ExodusII_IO_Helper::NamesData::write_to_exodus(int ex_id, exII::ex_entity_type type) 01932 { 01933 if (table_size) 01934 return exII::ex_put_names(ex_id, type, data_table); 01935 return 0; // EX_NOERR 01936 } 01937 01938 } // namespace libMesh 01939 01940 01941 01942 #endif // #ifdef LIBMESH_HAVE_EXODUS_API
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:46 UTC
Hosted By: