unv_io.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 // C++ includes 00020 #include <iomanip> 00021 #include <cstdio> // for std::sprintf 00022 #include <algorithm> // for std::sort 00023 #include <fstream> 00024 00025 // Local includes 00026 #include "libmesh/libmesh_config.h" 00027 #include "libmesh/libmesh_logging.h" 00028 #include "libmesh/unv_io.h" 00029 #include "libmesh/mesh_data.h" 00030 #include "libmesh/mesh_base.h" 00031 #include "libmesh/face_quad4.h" 00032 #include "libmesh/face_tri3.h" 00033 #include "libmesh/face_tri6.h" 00034 #include "libmesh/face_quad8.h" 00035 #include "libmesh/face_quad9.h" 00036 #include "libmesh/cell_tet4.h" 00037 #include "libmesh/cell_hex8.h" 00038 #include "libmesh/cell_hex20.h" 00039 #include "libmesh/cell_tet10.h" 00040 #include "libmesh/cell_prism6.h" 00041 00042 #ifdef LIBMESH_HAVE_GZSTREAM 00043 # include "gzstream.h" // For reading/writing compressed streams 00044 #endif 00045 00046 00047 00048 namespace libMesh 00049 { 00050 00051 00052 00053 //----------------------------------------------------------------------------- 00054 // UNVIO class static members 00055 const std::string UNVIO::_label_dataset_nodes = "2411"; 00056 const std::string UNVIO::_label_dataset_elements = "2412"; 00057 00058 00059 00060 // ------------------------------------------------------------ 00061 // UNVIO class members 00062 void UNVIO::clear () 00063 { 00064 /* 00065 * Initialize these to dummy values 00066 */ 00067 this->_n_nodes = 0; 00068 this->_n_elements = 0; 00069 this->_need_D_to_e = true; 00070 00071 this->_assign_nodes.clear(); 00072 this->_ds_position.clear(); 00073 } 00074 00075 00076 00077 00078 00079 void UNVIO::read (const std::string& file_name) 00080 { 00081 if (file_name.rfind(".gz") < file_name.size()) 00082 { 00083 #ifdef LIBMESH_HAVE_GZSTREAM 00084 00085 igzstream in_stream (file_name.c_str()); 00086 this->read_implementation (in_stream); 00087 00088 #else 00089 00090 libMesh::err << "ERROR: You must have the zlib.h header " 00091 << "files and libraries to read and write " 00092 << "compressed streams." 00093 << std::endl; 00094 libmesh_error(); 00095 00096 #endif 00097 return; 00098 } 00099 00100 else 00101 { 00102 std::ifstream in_stream (file_name.c_str()); 00103 this->read_implementation (in_stream); 00104 return; 00105 } 00106 } 00107 00108 00109 void UNVIO::read_implementation (std::istream& in_stream) 00110 { 00111 // clear everything, so that 00112 // we can start from scratch 00113 this->clear (); 00114 00115 // Keep track of what kinds of elements this file contains 00116 elems_of_dimension.clear(); 00117 elems_of_dimension.resize(4, false); 00118 00119 // Note that we read this file 00120 // @e twice. First time to 00121 // detect the number of nodes 00122 // and elements (and possible 00123 // conversion tasks like D_to_e) 00124 // and the order of datasets 00125 // (nodes first, then elements, 00126 // or the other way around), 00127 // and second to do the actual 00128 // read. 00129 std::vector<std::string> order_of_datasets; 00130 order_of_datasets.reserve(2); 00131 00132 { 00133 // the first time we read the file, 00134 // merely to obtain overall info 00135 if ( !in_stream.good() ) 00136 { 00137 libMesh::err << "ERROR: Input file not good." 00138 << std::endl; 00139 libmesh_error(); 00140 } 00141 00142 00143 // Count nodes and elements, then let 00144 // other methods read the element and 00145 // node data. Also remember which 00146 // dataset comes first: nodes or elements 00147 if (this->verbose()) 00148 libMesh::out << " Counting nodes and elements" << std::endl; 00149 00150 00151 // bool reached_eof = false; 00152 bool found_node = false; 00153 bool found_elem = false; 00154 00155 00156 std::string olds, news; 00157 00158 while (in_stream.good()) 00159 { 00160 in_stream >> olds >> news; 00161 00162 // a "-1" followed by a number means the beginning of a dataset 00163 // stop combing at the end of the file 00164 while ( ((olds != "-1") || (news == "-1") ) && !in_stream.eof() ) 00165 { 00166 olds = news; 00167 in_stream >> news; 00168 } 00169 00170 // if (in_stream.eof()) 00171 // { 00172 // reached_eof = true; 00173 // break; 00174 // } 00175 00176 00177 // if beginning of dataset, buffer it in 00178 // temp_buffer, if desired 00179 if (news == _label_dataset_nodes) 00180 { 00181 found_node = true; 00182 order_of_datasets.push_back (_label_dataset_nodes); 00183 this->count_nodes (in_stream); 00184 00185 // we can save some time scanning the file 00186 // when we know we already have everything 00187 // we want 00188 if (found_elem) 00189 break; 00190 } 00191 00192 else if (news == _label_dataset_elements) 00193 { 00194 found_elem = true; 00195 order_of_datasets.push_back (_label_dataset_elements); 00196 this->count_elements (in_stream); 00197 00198 // we can save some time scanning the file 00199 // when we know we already have everything 00200 // we want 00201 if (found_node) 00202 break; 00203 } 00204 } 00205 00206 00207 // Here we should better have found 00208 // the datasets for nodes and elements, 00209 // otherwise the unv files is bad! 00210 if (!found_elem) 00211 { 00212 libMesh::err << "ERROR: Could not find elements!" << std::endl; 00213 libmesh_error(); 00214 } 00215 00216 if (!found_node) 00217 { 00218 libMesh::err << "ERROR: Could not find nodes!" << std::endl; 00219 libmesh_error(); 00220 } 00221 00222 00223 // Don't close, just seek to the beginning 00224 in_stream.seekg(0, std::ios::beg); 00225 00226 if (!in_stream.good() ) 00227 { 00228 libMesh::err << "ERROR: Cannot re-read input file." 00229 << std::endl; 00230 libmesh_error(); 00231 } 00232 } 00233 00234 00235 00236 00237 00238 // We finished scanning the file, 00239 // and our member data 00240 // \p this->_n_nodes, 00241 // \p this->_n_elements, 00242 // \p this->_need_D_to_e 00243 // should be properly initialized. 00244 { 00245 // Read the datasets in the order that 00246 // we already know 00247 libmesh_assert_equal_to (order_of_datasets.size(), 2); 00248 00249 for (unsigned int ds=0; ds < order_of_datasets.size(); ds++) 00250 { 00251 if (order_of_datasets[ds] == _label_dataset_nodes) 00252 this->node_in (in_stream); 00253 00254 else if (order_of_datasets[ds] == _label_dataset_elements) 00255 this->element_in (in_stream); 00256 00257 else 00258 libmesh_error(); 00259 } 00260 00261 // Set the mesh dimension to the largest encountered for an element 00262 for (unsigned int i=0; i!=4; ++i) 00263 if (elems_of_dimension[i]) 00264 MeshInput<MeshBase>::mesh().set_mesh_dimension(i); 00265 00266 #if LIBMESH_DIM < 3 00267 if (MeshInput<MeshBase>::mesh().mesh_dimension() > LIBMESH_DIM) 00268 { 00269 libMesh::err << "Cannot open dimension " << 00270 MeshInput<MeshBase>::mesh().mesh_dimension() << 00271 " mesh file when configured without " << 00272 MeshInput<MeshBase>::mesh().mesh_dimension() << "D support." << 00273 std::endl; 00274 libmesh_error(); 00275 } 00276 #endif 00277 00278 // tell the MeshData object that we are finished 00279 // reading data 00280 this->_mesh_data.close_foreign_id_maps (); 00281 00282 if (this->verbose()) 00283 libMesh::out << " Finished." << std::endl << std::endl; 00284 } 00285 00286 // save memory 00287 this->_assign_nodes.clear(); 00288 this->_ds_position.clear(); 00289 } 00290 00291 00292 00293 00294 00295 void UNVIO::write (const std::string& file_name) 00296 { 00297 if (file_name.rfind(".gz") < file_name.size()) 00298 { 00299 #ifdef LIBMESH_HAVE_GZSTREAM 00300 00301 ogzstream out_stream(file_name.c_str()); 00302 this->write_implementation (out_stream); 00303 00304 #else 00305 00306 libMesh::err << "ERROR: You must have the zlib.h header " 00307 << "files and libraries to read and write " 00308 << "compressed streams." 00309 << std::endl; 00310 libmesh_error(); 00311 00312 #endif 00313 00314 return; 00315 } 00316 00317 else 00318 { 00319 std::ofstream out_stream (file_name.c_str()); 00320 this->write_implementation (out_stream); 00321 return; 00322 } 00323 } 00324 00325 00326 00327 00328 void UNVIO::write_implementation (std::ostream& out_file) 00329 { 00330 if ( !out_file.good() ) 00331 { 00332 libMesh::err << "ERROR: Output file not good." 00333 << std::endl; 00334 libmesh_error(); 00335 } 00336 00337 00338 MeshBase& mesh = MeshInput<MeshBase>::mesh(); 00339 00340 // already know these data, so initialize 00341 // them. Does not hurt. 00342 this->_n_nodes = mesh.n_nodes(); 00343 this->_n_elements = mesh.n_elem(); 00344 this->_need_D_to_e = false; 00345 00346 00347 00348 // we need the MeshData, otherwise we do not 00349 // know the foreign node id 00350 if (!this->_mesh_data.active()) 00351 if (!this->_mesh_data.compatibility_mode()) 00352 { 00353 libMesh::err << std::endl 00354 << "*************************************************************************" << std::endl 00355 << "* WARNING: MeshData neither active nor in compatibility mode. *" << std::endl 00356 << "* Enable compatibility mode for MeshData. Use this Universal *" << std::endl 00357 << "* file with caution: libMesh node and element ids are used. *" << std::endl 00358 << "*************************************************************************" << std::endl 00359 << std::endl; 00360 this->_mesh_data.enable_compatibility_mode(); 00361 } 00362 00363 00364 00365 // write the nodes, then the elements 00366 this->node_out (out_file); 00367 this->element_out (out_file); 00368 } 00369 00370 00371 00372 00373 00374 void UNVIO::count_nodes (std::istream& in_file) 00375 { 00376 START_LOG("count_nodes()","UNVIO"); 00377 00378 // if this->_n_nodes is not 0 the dataset 00379 // has already been scanned 00380 if (this->_n_nodes != 0) 00381 { 00382 libMesh::err << "Error: Trying to scan nodes twice!" 00383 << std::endl; 00384 libmesh_error(); 00385 } 00386 00387 00388 // Read from file, count nodes, 00389 // check if floats have to be converted 00390 std::string data; 00391 00392 in_file >> data; // read the first node label 00393 00394 00395 if (data == "-1") 00396 { 00397 libMesh::err << "ERROR: Bad, already reached end of dataset before even starting to read nodes!" 00398 << std::endl; 00399 libmesh_error(); 00400 } 00401 00402 00403 // ignore the misc data for this node 00404 in_file.ignore(256,'\n'); 00405 00406 00407 00408 // Now we are there to verify whether we need 00409 // to convert from D to e or not 00410 in_file >> data; 00411 00412 // When this "data" contains a "D", then 00413 // we have to convert each and every float... 00414 // But also assume when _this_ specific 00415 // line does not contain a "D", then the 00416 // other lines won't, too. 00417 { 00418 // #ifdef __HP_aCC 00419 // // Use an "int" instead of unsigned int, 00420 // // otherwise HP aCC may crash! 00421 // const int position = data.find("D",6); 00422 // #else 00423 // const unsigned int position = data.find("D",6); 00424 // #endif 00425 std::string::size_type position = data.find("D",6); 00426 00427 if (position!=std::string::npos) // npos means no position 00428 { 00429 this->_need_D_to_e = true; 00430 00431 if (this->verbose()) 00432 libMesh::out << " Convert from \"D\" to \"e\"" << std::endl; 00433 } 00434 else 00435 this->_need_D_to_e = false; 00436 } 00437 00438 // read the remaining two coordinates 00439 in_file >> data; 00440 in_file >> data; 00441 00442 00443 // this was our first node 00444 this->_n_nodes++; 00445 00446 00447 00448 // proceed _counting_ the remaining 00449 // nodes. 00450 while (in_file.good()) 00451 { 00452 // read the node label 00453 in_file >> data; 00454 00455 if (data == "-1") 00456 // end of dataset is reached 00457 break; 00458 00459 // ignore the remaining data (coord_sys_label, color etc) 00460 in_file.ignore (256, '\n'); 00461 // ignore the coordinates 00462 in_file.ignore (256, '\n'); 00463 00464 this->_n_nodes++; 00465 } 00466 00467 00468 if (in_file.eof()) 00469 { 00470 libMesh::err << "ERROR: File ended before end of node dataset!" 00471 << std::endl; 00472 libmesh_error(); 00473 } 00474 00475 if (this->verbose()) 00476 libMesh::out << " Nodes : " << this->_n_nodes << std::endl; 00477 00478 STOP_LOG("count_nodes()","UNVIO"); 00479 } 00480 00481 00482 00483 00484 00485 00486 void UNVIO::count_elements (std::istream& in_file) 00487 { 00488 START_LOG("count_elements()","UNVIO"); 00489 00490 if (this->_n_elements != 0) 00491 { 00492 libMesh::err << "Error: Trying to scan elements twice!" 00493 << std::endl; 00494 libmesh_error(); 00495 } 00496 00497 00498 // Simply read the element 00499 // dataset for the @e only 00500 // purpose to count nodes! 00501 00502 std::string data; 00503 unsigned int fe_id; 00504 00505 while (!in_file.eof()) 00506 { 00507 // read element label 00508 in_file >> data; 00509 00510 // end of dataset? 00511 if (data == "-1") 00512 break; 00513 00514 // read fe_id 00515 in_file >> fe_id; 00516 00517 // Skip related data, 00518 // and node number list 00519 in_file.ignore (256,'\n'); 00520 in_file.ignore (256,'\n'); 00521 00522 // For some elements the node numbers 00523 // are given more than one record 00524 00525 // TET10 or QUAD9 00526 if (fe_id == 118 || fe_id == 300) 00527 in_file.ignore (256,'\n'); 00528 00529 // HEX20 00530 if (fe_id == 116) 00531 { 00532 in_file.ignore (256,'\n'); 00533 in_file.ignore (256,'\n'); 00534 } 00535 00536 this->_n_elements++; 00537 } 00538 00539 00540 if (in_file.eof()) 00541 { 00542 libMesh::err << "ERROR: File ended before end of element dataset!" 00543 << std::endl; 00544 libmesh_error(); 00545 } 00546 00547 if (this->verbose()) 00548 libMesh::out << " Elements: " << this->_n_elements << std::endl; 00549 00550 STOP_LOG("count_elements()","UNVIO"); 00551 } 00552 00553 00554 00555 void UNVIO::node_in (std::istream& in_file) 00556 { 00557 START_LOG("node_in()","UNVIO"); 00558 00559 if (this->verbose()) 00560 libMesh::out << " Reading nodes" << std::endl; 00561 00562 // adjust the \p istream to our position 00563 const bool ok = this->beginning_of_dataset(in_file, _label_dataset_nodes); 00564 00565 if (!ok) 00566 { 00567 libMesh::err << "ERROR: Could not find node dataset!" << std::endl; 00568 libmesh_error(); 00569 } 00570 00571 MeshBase& mesh = MeshInput<MeshBase>::mesh(); 00572 00573 unsigned int node_lab; // label of the node 00574 unsigned int exp_coord_sys_num, // export coordinate system number (not supported yet) 00575 disp_coord_sys_num, // displacement coordinate system number (not supported yet) 00576 color; // color (not supported yet) 00577 00578 // allocate the correct amount 00579 // of memory for the node vector 00580 this->_assign_nodes.reserve (this->_n_nodes); 00581 00582 00583 // always 3 coordinates in the UNV file, no matter 00584 // which dimensionality libMesh is in 00585 //std::vector<Real> xyz (3); 00586 Point xyz; 00587 00588 // depending on whether we have to convert each 00589 // coordinate (float), we offer two versions. 00590 // Note that \p count_nodes() already verified 00591 // whether this file uses "D" of "e" 00592 if (this->_need_D_to_e) 00593 { 00594 // ok, convert... 00595 std::string num_buf; 00596 00597 for(dof_id_type i=0; i<this->_n_nodes; i++) 00598 { 00599 libmesh_assert (!in_file.eof()); 00600 00601 in_file >> node_lab // read the node label 00602 >> exp_coord_sys_num // (not supported yet) 00603 >> disp_coord_sys_num // (not supported yet) 00604 >> color; // (not supported yet) 00605 00606 // take care of the 00607 // floating-point data 00608 for (unsigned int d=0; d<3; d++) 00609 { 00610 in_file >> num_buf; 00611 xyz(d) = this->D_to_e (num_buf); 00612 } 00613 00614 // set up the id map 00615 this->_assign_nodes.push_back (node_lab); 00616 00617 // add node to the Mesh & 00618 // tell the MeshData object the foreign node id 00619 // (note that mesh.add_point() returns a pointer to the new node) 00620 this->_mesh_data.add_foreign_node_id (mesh.add_point(xyz,i), node_lab); 00621 } 00622 } 00623 00624 else 00625 { 00626 // very well, no need to convert anything, 00627 // just plain import. 00628 for (unsigned int i=0;i<this->_n_nodes;i++) 00629 { 00630 libmesh_assert (!in_file.eof()); 00631 00632 in_file >> node_lab // read the node label 00633 >> exp_coord_sys_num // (not supported yet) 00634 >> disp_coord_sys_num // (not supported yet) 00635 >> color // (not supported yet) 00636 >> xyz(0) // read x-coordinate 00637 >> xyz(1) // read y-coordinate 00638 >> xyz(2); // read z-coordinate 00639 00640 // set up the id map 00641 this->_assign_nodes.push_back (node_lab); 00642 00643 // add node to the Mesh & 00644 // tell the MeshData object the foreign node id 00645 // (note that mesh.add_point() returns a pointer to the new node) 00646 this->_mesh_data.add_foreign_node_id (mesh.add_point(xyz,i), node_lab); 00647 } 00648 } 00649 00650 // now we need to sort the _assign_nodes vector so we can 00651 // search it efficiently like a map 00652 std::sort (this->_assign_nodes.begin(), 00653 this->_assign_nodes.end()); 00654 00655 STOP_LOG("node_in()","UNVIO"); 00656 } 00657 00658 00659 00660 00661 00662 void UNVIO::element_in (std::istream& in_file) 00663 { 00664 START_LOG("element_in()","UNVIO"); 00665 00666 if (this->verbose()) 00667 libMesh::out << " Reading elements" << std::endl; 00668 00669 MeshBase& mesh = MeshInput<MeshBase>::mesh(); 00670 00671 // adjust the \p istream to our 00672 // position 00673 const bool ok = this->beginning_of_dataset(in_file, _label_dataset_elements); 00674 00675 if (!ok) 00676 { 00677 libMesh::err << "ERROR: Could not find element dataset!" << std::endl; 00678 libmesh_error(); 00679 } 00680 00681 00682 unsigned int element_lab, // element label (not supported yet) 00683 n_nodes; // number of nodes on element 00684 unsigned long int fe_descriptor_id, // FE descriptor id 00685 phys_prop_tab_num, // physical property table number (not supported yet) 00686 mat_prop_tab_num, // material property table number (not supported yet) 00687 color; // color (not supported yet) 00688 00689 00690 // vector that temporarily holds the node labels defining element 00691 std::vector<unsigned int> node_labels (21); 00692 00693 00694 // vector that assigns element nodes to their correct position 00695 // for example: 00696 // 44:plane stress | QUAD4 00697 // linear quadrilateral | 00698 // position in UNV-file | position in libmesh 00699 // assign_elem_node[1] = 0 00700 // assign_elem_node[2] = 3 00701 // assign_elem_node[3] = 2 00702 // assign_elem_node[4] = 1 00703 // 00704 // UNV is 1-based, we leave the 0th element of the vectors unused in order 00705 // to prevent confusion, this way we can store elements with up to 20 nodes 00706 unsigned int assign_elem_nodes[21]; 00707 00708 00709 // Get the beginning and end of the _assign_nodes vector 00710 // to eliminate repeated function calls 00711 const std::vector<dof_id_type>::const_iterator it_begin = 00712 this->_assign_nodes.begin(); 00713 00714 const std::vector<dof_id_type>::const_iterator it_end = 00715 this->_assign_nodes.end(); 00716 00717 00718 00719 // read from the virtual file 00720 for (dof_id_type i=0; i<this->_n_elements; i++) 00721 { 00722 in_file >> element_lab // read element label 00723 >> fe_descriptor_id // read FE descriptor id 00724 >> phys_prop_tab_num // (not supported yet) 00725 >> mat_prop_tab_num // (not supported yet) 00726 >> color // (not supported yet) 00727 >> n_nodes; // read number of nodes on element 00728 00729 for (unsigned int j=1; j<=n_nodes; j++) 00730 in_file >> node_labels[j]; // read node labels 00731 00732 Elem* elem = NULL; // element pointer 00733 00734 switch (fe_descriptor_id) 00735 { 00736 00737 case 41: // Plane Stress Linear Triangle 00738 case 91: // Thin Shell Linear Triangle 00739 { 00740 elem = new Tri3; // create new element 00741 00742 assign_elem_nodes[1]=0; 00743 assign_elem_nodes[2]=2; 00744 assign_elem_nodes[3]=1; 00745 break; 00746 } 00747 00748 case 42: // Plane Stress Quadratic Triangle 00749 case 92: // Thin Shell Quadratic Triangle 00750 { 00751 elem = new Tri6; // create new element 00752 00753 assign_elem_nodes[1]=0; 00754 assign_elem_nodes[2]=5; 00755 assign_elem_nodes[3]=2; 00756 assign_elem_nodes[4]=4; 00757 assign_elem_nodes[5]=1; 00758 assign_elem_nodes[6]=3; 00759 break; 00760 } 00761 00762 case 43: // Plane Stress Cubic Triangle 00763 { 00764 libMesh::err << "ERROR: UNV-element type 43: Plane Stress Cubic Triangle" 00765 << " not supported." 00766 << std::endl; 00767 libmesh_error(); 00768 break; 00769 } 00770 00771 case 44: // Plane Stress Linear Quadrilateral 00772 case 94: // Thin Shell Linear Quadrilateral 00773 { 00774 elem = new Quad4; // create new element 00775 00776 assign_elem_nodes[1]=0; 00777 assign_elem_nodes[2]=3; 00778 assign_elem_nodes[3]=2; 00779 assign_elem_nodes[4]=1; 00780 break; 00781 } 00782 00783 case 45: // Plane Stress Quadratic Quadrilateral 00784 case 95: // Thin Shell Quadratic Quadrilateral 00785 { 00786 elem = new Quad8; // create new element 00787 00788 assign_elem_nodes[1]=0; 00789 assign_elem_nodes[2]=7; 00790 assign_elem_nodes[3]=3; 00791 assign_elem_nodes[4]=6; 00792 assign_elem_nodes[5]=2; 00793 assign_elem_nodes[6]=5; 00794 assign_elem_nodes[7]=1; 00795 assign_elem_nodes[8]=4; 00796 break; 00797 } 00798 00799 case 300: // Thin Shell Quadratic Quadrilateral (nine nodes) 00800 { 00801 elem = new Quad9; // create new element 00802 00803 assign_elem_nodes[1]=0; 00804 assign_elem_nodes[2]=7; 00805 assign_elem_nodes[3]=3; 00806 assign_elem_nodes[4]=6; 00807 assign_elem_nodes[5]=2; 00808 assign_elem_nodes[6]=5; 00809 assign_elem_nodes[7]=1; 00810 assign_elem_nodes[8]=4; 00811 assign_elem_nodes[9]=8; 00812 break; 00813 } 00814 00815 case 46: // Plane Stress Cubic Quadrilateral 00816 { 00817 libMesh::err << "ERROR: UNV-element type 46: Plane Stress Cubic Quadrilateral" 00818 << " not supported." 00819 << std::endl; 00820 libmesh_error(); 00821 break; 00822 } 00823 00824 case 111: // Solid Linear Tetrahedron 00825 { 00826 elem = new Tet4; // create new element 00827 00828 assign_elem_nodes[1]=0; 00829 assign_elem_nodes[2]=1; 00830 assign_elem_nodes[3]=2; 00831 assign_elem_nodes[4]=3; 00832 break; 00833 } 00834 00835 case 112: // Solid Linear Prism 00836 { 00837 elem = new Prism6; // create new element 00838 00839 assign_elem_nodes[1]=0; 00840 assign_elem_nodes[2]=1; 00841 assign_elem_nodes[3]=2; 00842 assign_elem_nodes[4]=3; 00843 assign_elem_nodes[5]=4; 00844 assign_elem_nodes[6]=5; 00845 break; 00846 } 00847 00848 case 115: // Solid Linear Brick 00849 { 00850 elem = new Hex8; // create new element 00851 00852 assign_elem_nodes[1]=0; 00853 assign_elem_nodes[2]=4; 00854 assign_elem_nodes[3]=5; 00855 assign_elem_nodes[4]=1; 00856 assign_elem_nodes[5]=3; 00857 assign_elem_nodes[6]=7; 00858 assign_elem_nodes[7]=6; 00859 assign_elem_nodes[8]=2; 00860 break; 00861 } 00862 00863 case 116: // Solid Quadratic Brick 00864 { 00865 elem = new Hex20; // create new element 00866 00867 assign_elem_nodes[1]=0; 00868 assign_elem_nodes[2]=12; 00869 assign_elem_nodes[3]=4; 00870 assign_elem_nodes[4]=16; 00871 assign_elem_nodes[5]=5; 00872 assign_elem_nodes[6]=13; 00873 assign_elem_nodes[7]=1; 00874 assign_elem_nodes[8]=8; 00875 00876 assign_elem_nodes[9]=11; 00877 assign_elem_nodes[10]=19; 00878 assign_elem_nodes[11]=17; 00879 assign_elem_nodes[12]=9; 00880 00881 assign_elem_nodes[13]=3; 00882 assign_elem_nodes[14]=15; 00883 assign_elem_nodes[15]=7; 00884 assign_elem_nodes[16]=18; 00885 assign_elem_nodes[17]=6; 00886 assign_elem_nodes[18]=14; 00887 assign_elem_nodes[19]=2; 00888 assign_elem_nodes[20]=10; 00889 break; 00890 } 00891 00892 case 117: // Solid Cubic Brick 00893 { 00894 libMesh::err << "Error: UNV-element type 117: Solid Cubic Brick" 00895 << " not supported." 00896 << std::endl; 00897 libmesh_error(); 00898 break; 00899 } 00900 00901 case 118: // Solid Quadratic Tetrahedron 00902 { 00903 elem = new Tet10; // create new element 00904 00905 assign_elem_nodes[1]=0; 00906 assign_elem_nodes[2]=4; 00907 assign_elem_nodes[3]=1; 00908 assign_elem_nodes[4]=5; 00909 assign_elem_nodes[5]=2; 00910 assign_elem_nodes[6]=6; 00911 assign_elem_nodes[7]=7; 00912 assign_elem_nodes[8]=8; 00913 assign_elem_nodes[9]=9; 00914 assign_elem_nodes[10]=3; 00915 break; 00916 } 00917 00918 default: // Unrecognized element type 00919 { 00920 libMesh::err << "ERROR: UNV-element type " 00921 << fe_descriptor_id 00922 << " not supported." 00923 << std::endl; 00924 libmesh_error(); 00925 break; 00926 } 00927 } 00928 00929 // nodes are being stored in element 00930 for (dof_id_type j=1; j<=n_nodes; j++) 00931 { 00932 // Find the position of node_labels[j] in the _assign_nodes vector. 00933 const std::pair<std::vector<dof_id_type>::const_iterator, 00934 std::vector<dof_id_type>::const_iterator> 00935 it = std::equal_range (it_begin, 00936 it_end, 00937 node_labels[j]); 00938 00939 // it better be there, so libmesh_assert that it was found. 00940 libmesh_assert (it.first != it.second); 00941 libmesh_assert_equal_to (*(it.first), node_labels[j]); 00942 00943 // Now, the distance between this UNV id and the beginning of 00944 // the _assign_nodes vector will give us a unique id in the 00945 // range [0,n_nodes) that we can use for defining a contiguous 00946 // connectivity. 00947 const dof_id_type assigned_node = 00948 libmesh_cast_int<dof_id_type> 00949 (std::distance (it_begin, it.first)); 00950 00951 // Make sure we didn't get an out-of-bounds id 00952 libmesh_assert_less (assigned_node, this->_n_nodes); 00953 00954 elem->set_node(assign_elem_nodes[j]) = 00955 mesh.node_ptr(assigned_node); 00956 } 00957 00958 elems_of_dimension[elem->dim()] = true; 00959 00960 // add elem to the Mesh & 00961 // tell the MeshData object the foreign elem id 00962 // (note that mesh.add_elem() returns a pointer to the new element) 00963 elem->set_id(i); 00964 this->_mesh_data.add_foreign_elem_id (mesh.add_elem(elem), element_lab); 00965 } 00966 00967 STOP_LOG("element_in()","UNVIO"); 00968 } 00969 00970 00971 00972 00973 00974 00975 void UNVIO::node_out (std::ostream& out_file) 00976 { 00977 00978 libmesh_assert (this->_mesh_data.active() || 00979 this->_mesh_data.compatibility_mode()); 00980 00981 00982 if (this->verbose()) 00983 libMesh::out << " Writing " << this->_n_nodes << " nodes" << std::endl; 00984 00985 // Write beginning of dataset 00986 out_file << " -1\n" 00987 << " " 00988 << _label_dataset_nodes 00989 << '\n'; 00990 00991 00992 unsigned int exp_coord_sys_dummy = 0; // export coordinate sys. (not supported yet) 00993 unsigned int disp_coord_sys_dummy = 0; // displacement coordinate sys. (not supp. yet) 00994 unsigned int color_dummy = 0; // color(not supported yet) 00995 00996 // A reference to the parent class's mesh 00997 const MeshBase& mesh = MeshOutput<MeshBase>::mesh(); 00998 00999 MeshBase::const_node_iterator nd = mesh.nodes_begin(); 01000 const MeshBase::const_node_iterator end = mesh.nodes_end(); 01001 01002 for (; nd != end; ++nd) 01003 { 01004 const Node* current_node = *nd; 01005 01006 char buf[78]; 01007 std::sprintf(buf, "%10d%10d%10d%10d\n", 01008 this->_mesh_data.node_to_foreign_id(current_node), 01009 exp_coord_sys_dummy, 01010 disp_coord_sys_dummy, 01011 color_dummy); 01012 out_file << buf; 01013 01014 // the coordinates 01015 if (mesh.spatial_dimension() == 3) 01016 std::sprintf(buf, "%25.16E%25.16E%25.16E\n", 01017 static_cast<double>((*current_node)(0)), 01018 static_cast<double>((*current_node)(1)), 01019 static_cast<double>((*current_node)(2))); 01020 else if (mesh.spatial_dimension() == 2) 01021 std::sprintf(buf, "%25.16E%25.16E\n", 01022 static_cast<double>((*current_node)(0)), 01023 static_cast<double>((*current_node)(1))); 01024 else 01025 std::sprintf(buf, "%25.16E\n", 01026 static_cast<double>((*current_node)(0))); 01027 01028 out_file << buf; 01029 } 01030 01031 01032 // Write end of dataset 01033 out_file << " -1\n"; 01034 } 01035 01036 01037 01038 01039 01040 01041 void UNVIO::element_out(std::ostream& out_file) 01042 { 01043 libmesh_assert (this->_mesh_data.active() || 01044 this->_mesh_data.compatibility_mode()); 01045 01046 if (this->verbose()) 01047 libMesh::out << " Writing elements" << std::endl; 01048 01049 // Write beginning of dataset 01050 out_file << " -1\n" 01051 << " " 01052 << _label_dataset_elements 01053 << "\n"; 01054 01055 unsigned long int fe_descriptor_id = 0; // FE descriptor id 01056 unsigned long int phys_prop_tab_dummy = 2; // physical property (not supported yet) 01057 unsigned long int mat_prop_tab_dummy = 1; // material property (not supported yet) 01058 unsigned long int color_dummy = 7; // color (not supported yet) 01059 01060 01061 // vector that assigns element nodes to their correct position 01062 // currently only elements with up to 20 nodes 01063 // 01064 // Example: 01065 // QUAD4 | 44:plane stress 01066 // | linear quad 01067 // position in libMesh | UNV numbering 01068 // (note: 0-based) | (note: 1-based) 01069 // 01070 // assign_elem_node[0] = 0 01071 // assign_elem_node[1] = 3 01072 // assign_elem_node[2] = 2 01073 // assign_elem_node[3] = 1 01074 unsigned int assign_elem_nodes[20]; 01075 01076 unsigned int n_elem_written=0; 01077 01078 // A reference to the parent class's mesh 01079 const MeshBase& mesh = MeshOutput<MeshBase>::mesh(); 01080 01081 MeshBase::const_element_iterator it = mesh.elements_begin(); 01082 const MeshBase::const_element_iterator end = mesh.elements_end(); 01083 01084 for (; it != end; ++it) 01085 { 01086 const Elem* elem = *it; 01087 01088 elem->n_nodes(); 01089 01090 switch (elem->type()) 01091 { 01092 01093 case TRI3: 01094 { 01095 fe_descriptor_id = 41; // Plane Stress Linear Triangle 01096 assign_elem_nodes[0] = 0; 01097 assign_elem_nodes[1] = 2; 01098 assign_elem_nodes[2] = 1; 01099 break; 01100 } 01101 01102 case TRI6: 01103 { 01104 fe_descriptor_id = 42; // Plane Stress Quadratic Triangle 01105 assign_elem_nodes[0] = 0; 01106 assign_elem_nodes[1] = 5; 01107 assign_elem_nodes[2] = 2; 01108 assign_elem_nodes[3] = 4; 01109 assign_elem_nodes[4] = 1; 01110 assign_elem_nodes[5] = 3; 01111 break; 01112 } 01113 01114 case QUAD4: 01115 { 01116 fe_descriptor_id = 44; // Plane Stress Linear Quadrilateral 01117 assign_elem_nodes[0] = 0; 01118 assign_elem_nodes[1] = 3; 01119 assign_elem_nodes[2] = 2; 01120 assign_elem_nodes[3] = 1; 01121 break; 01122 } 01123 01124 case QUAD8: 01125 { 01126 fe_descriptor_id = 45; // Plane Stress Quadratic Quadrilateral 01127 assign_elem_nodes[0] = 0; 01128 assign_elem_nodes[1] = 7; 01129 assign_elem_nodes[2] = 3; 01130 assign_elem_nodes[3] = 6; 01131 assign_elem_nodes[4] = 2; 01132 assign_elem_nodes[5] = 5; 01133 assign_elem_nodes[6] = 1; 01134 assign_elem_nodes[7] = 4; 01135 break; 01136 } 01137 01138 case QUAD9: 01139 { 01140 fe_descriptor_id = 300; // Plane Stress Quadratic Quadrilateral 01141 assign_elem_nodes[0] = 0; 01142 assign_elem_nodes[1] = 7; 01143 assign_elem_nodes[2] = 3; 01144 assign_elem_nodes[3] = 6; 01145 assign_elem_nodes[4] = 2; 01146 assign_elem_nodes[5] = 5; 01147 assign_elem_nodes[6] = 1; 01148 assign_elem_nodes[7] = 4; 01149 assign_elem_nodes[8] = 8; 01150 break; 01151 } 01152 01153 case TET4: 01154 { 01155 fe_descriptor_id = 111; // Solid Linear Tetrahedron 01156 assign_elem_nodes[0] = 0; 01157 assign_elem_nodes[1] = 1; 01158 assign_elem_nodes[2] = 2; 01159 assign_elem_nodes[3] = 3; 01160 break; 01161 } 01162 01163 case PRISM6: 01164 { 01165 fe_descriptor_id = 112; // Solid Linear Prism 01166 assign_elem_nodes[0] = 0; 01167 assign_elem_nodes[1] = 1; 01168 assign_elem_nodes[2] = 2; 01169 assign_elem_nodes[3] = 3; 01170 assign_elem_nodes[4] = 4; 01171 assign_elem_nodes[5] = 5; 01172 break; 01173 } 01174 01175 case HEX8: 01176 { 01177 fe_descriptor_id = 115; // Solid Linear Brick 01178 assign_elem_nodes[0] = 0; 01179 assign_elem_nodes[1] = 4; 01180 assign_elem_nodes[2] = 5; 01181 assign_elem_nodes[3] = 1; 01182 assign_elem_nodes[4] = 3; 01183 assign_elem_nodes[5] = 7; 01184 assign_elem_nodes[6] = 6; 01185 assign_elem_nodes[7] = 2; 01186 break; 01187 } 01188 01189 case HEX20: 01190 { 01191 fe_descriptor_id = 116; // Solid Quadratic Brick 01192 assign_elem_nodes[ 0] = 0; 01193 assign_elem_nodes[ 1] = 12; 01194 assign_elem_nodes[ 2] = 4; 01195 assign_elem_nodes[ 3] = 16; 01196 assign_elem_nodes[ 4] = 5; 01197 assign_elem_nodes[ 5] = 13; 01198 assign_elem_nodes[ 6] = 1; 01199 assign_elem_nodes[ 7] = 8; 01200 01201 assign_elem_nodes[ 8] = 11; 01202 assign_elem_nodes[ 9] = 19; 01203 assign_elem_nodes[10] = 17; 01204 assign_elem_nodes[11] = 9; 01205 01206 assign_elem_nodes[12] = 3; 01207 assign_elem_nodes[13] = 15; 01208 assign_elem_nodes[14] = 7; 01209 assign_elem_nodes[15] = 18; 01210 assign_elem_nodes[16] = 6; 01211 assign_elem_nodes[17] = 14; 01212 assign_elem_nodes[18] = 2; 01213 assign_elem_nodes[19] = 10; 01214 01215 01216 break; 01217 } 01218 01219 case TET10: 01220 { 01221 fe_descriptor_id = 118; // Solid Quadratic Tetrahedron 01222 assign_elem_nodes[0] = 0; 01223 assign_elem_nodes[1] = 4; 01224 assign_elem_nodes[2] = 1; 01225 assign_elem_nodes[3] = 5; 01226 assign_elem_nodes[4] = 2; 01227 assign_elem_nodes[5] = 6; 01228 assign_elem_nodes[6] = 7; 01229 assign_elem_nodes[7] = 8; 01230 assign_elem_nodes[8] = 9; 01231 assign_elem_nodes[9] = 3; 01232 break; 01233 } 01234 01235 default: 01236 { 01237 libMesh::err << "ERROR: Element type = " 01238 << elem->type() 01239 << " not supported in " 01240 << "UNVIO!" 01241 << std::endl; 01242 libmesh_error(); 01243 break; 01244 } 01245 } 01246 01247 01248 out_file << std::setw(10) << this->_mesh_data.elem_to_foreign_id(elem) // element ID 01249 << std::setw(10) << fe_descriptor_id // type of element 01250 << std::setw(10) << phys_prop_tab_dummy // not supported 01251 << std::setw(10) << mat_prop_tab_dummy // not supported 01252 << std::setw(10) << color_dummy // not supported 01253 << std::setw(10) << elem->n_nodes() // No. of nodes per element 01254 << '\n'; 01255 01256 for (unsigned int j=0; j<elem->n_nodes(); j++) 01257 { 01258 // assign_elem_nodes[j]-th node: i.e., j loops over the 01259 // libMesh numbering, and assign_elem_nodes[j] over the 01260 // UNV numbering. 01261 const Node* node_in_unv_order = elem->get_node(assign_elem_nodes[j]); 01262 01263 // new record after 8 id entries 01264 if (j==8 || j==16) 01265 out_file << '\n'; 01266 01267 // write foreign label for this node 01268 out_file << std::setw(10) << this->_mesh_data.node_to_foreign_id(node_in_unv_order); 01269 01270 01271 } 01272 01273 out_file << '\n'; 01274 01275 n_elem_written++; 01276 } 01277 01278 if (this->verbose()) 01279 libMesh::out << " Finished writing " << n_elem_written << " elements" << std::endl; 01280 01281 // Write end of dataset 01282 out_file << " -1\n"; 01283 } 01284 01285 } // namespace libMesh 01286
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:49 UTC
Hosted By: