$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 // C++ includes 00021 #include <sstream> 00022 00023 // Local includes 00024 #include "libmesh/mesh_data.h" 00025 #include "libmesh/mesh_base.h" 00026 #include "libmesh/libmesh_logging.h" 00027 #include "libmesh/elem.h" 00028 00029 namespace libMesh 00030 { 00031 00032 00033 //------------------------------------------------------ 00034 // MeshData functions 00035 MeshData::MeshData(const MeshBase& m) : 00036 _mesh (m), 00037 _data_descriptor (""), 00038 _node_id_map_closed (false), 00039 _node_data_closed (false), 00040 _elem_id_map_closed (false), 00041 _elem_data_closed (false), 00042 _active (false), 00043 _compatibility_mode (false), 00044 _unv_header (NULL) 00045 { 00046 // This class isn't actively maintained, doesn't work in parallel, 00047 // and usually isn't as good a solution as adding an additional 00048 // ExplicitSystem with appropriate data field(s). 00049 libmesh_deprecated(); 00050 } 00051 00052 00053 00054 00055 MeshData::~MeshData() 00056 { 00057 clear(); 00058 } 00059 00060 00061 00062 00063 00064 void MeshData::activate (const std::string& descriptor) 00065 { 00066 #ifdef DEBUG 00067 if (_compatibility_mode) 00068 libMesh::err << "WARNING: MeshData was in compatibility mode, now being activated." 00069 << std::endl; 00070 #endif 00071 00072 _compatibility_mode = false; 00073 _active = true; 00074 _data_descriptor = descriptor; 00075 } 00076 00077 00078 00079 00080 00081 void MeshData::enable_compatibility_mode (const std::string& descriptor) 00082 { 00083 if (!_active) 00084 { 00085 _compatibility_mode = true; 00086 _active = false; 00087 // do as if the id maps are already closed 00088 _node_id_map_closed = true; 00089 _elem_id_map_closed = true; 00090 _data_descriptor = descriptor; 00091 // we can safely clear the id maps 00092 _node_id.clear(); 00093 _id_node.clear(); 00094 _elem_id.clear(); 00095 _id_elem.clear(); 00096 } 00097 #ifdef DEBUG 00098 else 00099 libMesh::err << "WARNING: MeshData was in compatibility mode, now being activated." 00100 << std::endl; 00101 #endif 00102 } 00103 00104 00105 00106 00107 00108 00109 void MeshData::clear() 00110 { 00111 _data_descriptor = ""; 00112 _node_data.clear(); 00113 _elem_data.clear(); 00114 _node_data_closed = false; 00115 _elem_data_closed = false; 00116 } 00117 00118 00119 00120 00121 00122 void MeshData::slim (const bool node_id_map, 00123 const bool elem_id_map) 00124 { 00125 if (this->active()) 00126 { 00127 00128 if (node_id_map) 00129 { 00130 // dumb check 00131 libmesh_assert (_node_id_map_closed); 00132 00133 _node_id_map_closed = false; 00134 _node_id.clear(); 00135 _id_node.clear(); 00136 } 00137 00138 if (elem_id_map) 00139 { 00140 // dumb check 00141 libmesh_assert (_elem_id_map_closed); 00142 00143 _elem_id_map_closed = false; 00144 _elem_id.clear(); 00145 _id_elem.clear(); 00146 } 00147 } 00148 00149 #ifdef DEBUG 00150 else if (this->compatibility_mode()) 00151 { 00152 libMesh::err << "WARNING: No need for MeshData::slim() in compatibility mode." << std::endl; 00153 } 00154 #endif 00155 } 00156 00157 00158 00159 00160 void MeshData::translate (const MeshBase& out_mesh, 00161 std::vector<Number>& values, 00162 std::vector<std::string>& names) const 00163 { 00164 libmesh_assert (_active || _compatibility_mode); 00165 00166 START_LOG("translate()", "MeshData"); 00167 00168 const unsigned int n_comp = this->n_val_per_node(); 00169 00170 // transfer our nodal data to a vector 00171 // that may be written concurrently 00172 // with the \p out_mesh. 00173 { 00174 // reserve memory for the nodal data 00175 values.reserve(n_comp*out_mesh.n_nodes()); 00176 00177 // iterate over the mesh's nodes 00178 MeshBase::const_node_iterator nodes_it = out_mesh.nodes_begin(); 00179 const MeshBase::const_node_iterator nodes_end = out_mesh.nodes_end(); 00180 00181 // Do not use the \p get_data() method, but the operator() 00182 // method, since this returns by default a zero value, 00183 // when there is no nodal data. 00184 for (; nodes_it != nodes_end; ++nodes_it) 00185 { 00186 const Node* node = *nodes_it; 00187 00188 for (unsigned int c= 0; c<n_comp; c++) 00189 values.push_back(this->operator()(node, c)); 00190 } 00191 } 00192 00193 00194 00195 // Now we have the data, nicely stored in \p values. 00196 // It remains to give names to the data, then write to 00197 // file. 00198 { 00199 names.reserve(n_comp); 00200 00201 // this naming scheme only works up to n_comp=100 00202 // (at least for gmv-accepted variable names) 00203 libmesh_assert_less (n_comp, 100); 00204 00205 for (unsigned int n=0; n<n_comp; n++) 00206 { 00207 std::ostringstream name_buf; 00208 name_buf << "bc_" << n; 00209 names.push_back(name_buf.str()); 00210 } 00211 } 00212 00213 STOP_LOG("translate()", "MeshData"); 00214 } 00215 00216 00217 00218 00219 void MeshData::close_foreign_id_maps () 00220 { 00221 if (_active) 00222 { 00223 libmesh_assert (!_elem_id.empty()); 00224 libmesh_assert (!_id_elem.empty()); 00225 libmesh_assert (!_node_id.empty()); 00226 libmesh_assert (!_id_node.empty()); 00227 00228 _elem_id_map_closed = true; 00229 _node_id_map_closed = true; 00230 } 00231 } 00232 00233 00234 00235 00236 00237 void MeshData::read (const std::string& name) 00238 { 00239 START_LOG("read()", "MeshData"); 00240 00241 libmesh_assert (_active || _compatibility_mode); 00242 00243 // the id maps have to be closed before reading 00244 // (note that in compatibility mode these are also true) 00245 libmesh_assert (_elem_id_map_closed && _node_id_map_closed); 00246 00247 #ifdef DEBUG 00248 if (this->compatibility_mode()) 00249 libMesh::err << "WARNING: MeshData in compatibility mode, node and element ids" << std::endl 00250 << " stored in file may be totally different from libMesh ids!" << std::endl; 00251 #endif 00252 00253 // Read the file based on extension. We let all processors read the 00254 // data because it would be inaccurate to let only one processor 00255 // have it and we're too lazy to code up a proper parallel read or 00256 // read+broadcast right now. 00257 00258 if (name.rfind(".xta") < name.size()) 00259 this->read_xdr (name, READ); 00260 00261 else if (name.rfind(".xtr") < name.size()) 00262 this->read_xdr (name, DECODE); 00263 00264 else if (name.rfind(".unv") < name.size()) 00265 this->read_unv (name); 00266 00267 else if ((name.rfind(".node") < name.size()) || 00268 (name.rfind(".ele") < name.size())) 00269 this->read_tetgen (name); 00270 00271 else 00272 libmesh_error_msg(" ERROR: Unrecognized file extension: " << name \ 00273 << "\n I understand the following:\n\n" \ 00274 << " *.xta -- Internal ASCII data format\n" \ 00275 << " *.xtr -- Internal binary data format\n" \ 00276 << " *.unv -- I-deas format"); 00277 00278 STOP_LOG("read()", "MeshData"); 00279 } 00280 00281 00282 00283 00284 00285 00286 void MeshData::write (const std::string& name) 00287 { 00288 START_LOG("write()", "MeshData"); 00289 00290 libmesh_assert (_active || _compatibility_mode); 00291 00292 // the id maps have to be closed before writing 00293 // (note that in compatibility mode these are also true) 00294 libmesh_assert (_elem_id_map_closed && _node_id_map_closed); 00295 00296 #ifdef DEBUG 00297 if (this->compatibility_mode()) 00298 libMesh::err << "WARNING: MeshData in compatibility mode. Node and element ids" << std::endl 00299 << " written to file may differ from libMesh numbering" << std::endl 00300 << " next time this file is read!" << std::endl; 00301 #endif 00302 00303 // Read the file based on extension 00304 { 00305 if (name.rfind(".xta") < name.size()) 00306 write_xdr (name, WRITE); 00307 00308 else if (name.rfind(".xtr") < name.size()) 00309 write_xdr (name, ENCODE); 00310 00311 else if (name.rfind(".unv") < name.size()) 00312 write_unv (name); 00313 00314 else 00315 libmesh_error_msg(" ERROR: Unrecognized file extension: " << name \ 00316 << "\n I understand the following:\n\n" \ 00317 << " *.xta -- Internal ASCII data format\n" \ 00318 << " *.xtr -- Internal binary data format\n" \ 00319 << " *.unv -- I-deas format"); 00320 } 00321 STOP_LOG("write()", "MeshData"); 00322 } 00323 00324 00325 00326 00327 std::string MeshData::get_info() const 00328 { 00329 std::ostringstream oss; 00330 00331 if (this->active() || this->compatibility_mode()) 00332 { 00333 oss << " MeshData Information:\n"; 00334 if (this->active()) 00335 oss << " object activated.\n"; 00336 if (this->compatibility_mode()) 00337 oss << " object in compatibility mode.\n"; 00338 if (this->_data_descriptor != "") 00339 oss << " descriptor=" << this->_data_descriptor << '\n'; 00340 if (this->elem_initialized()) 00341 oss << " Element associated data initialized.\n" 00342 << " n_val_per_elem()=" << this->n_val_per_elem() << '\n' 00343 << " n_elem_data()=" << this->n_elem_data() << '\n'; 00344 if (this->node_initialized()) 00345 oss << " Node associated data initialized.\n" 00346 << " n_val_per_node()=" << this->n_val_per_node() << '\n' 00347 << " n_node_data()=" << this->n_node_data() << '\n'; 00348 } 00349 else 00350 oss << " MeshData neither active nor in compatibility mode.\n"; 00351 00352 return oss.str(); 00353 } 00354 00355 00356 00357 00358 void MeshData::print_info(std::ostream& os) const 00359 { 00360 os << this->get_info() 00361 << std::endl; 00362 } 00363 00364 00365 std::ostream& operator << (std::ostream& os, const MeshData& m) 00366 { 00367 m.print_info(os); 00368 return os; 00369 } 00370 00371 00372 00373 00374 const Node* MeshData::foreign_id_to_node (const unsigned int fid) const 00375 { 00376 if (_active) 00377 { 00378 // when active, use our _id_node map 00379 libmesh_assert (_node_id_map_closed); 00380 00381 std::map<unsigned int, 00382 const Node*>::const_iterator pos = _id_node.find(fid); 00383 00384 if (pos == _id_node.end()) 00385 libmesh_error_msg("ERROR: Have no Node* associated with the foreign id = " << fid); 00386 00387 else 00388 return pos->second; 00389 } 00390 else if (_compatibility_mode) 00391 // when only in compatibility mode, 00392 // return the node stored in the MeshBase 00393 // under its current id 00394 return this->_mesh.node_ptr(fid); 00395 00396 libmesh_error_msg("We'll never get here!"); 00397 return NULL; 00398 } 00399 00400 00401 00402 00403 00404 unsigned int MeshData::node_to_foreign_id (const Node* n) const 00405 { 00406 libmesh_assert(n); 00407 00408 if (_active) 00409 { 00410 // when active, use our _node_id map 00411 libmesh_assert (_node_id_map_closed); 00412 00413 // look it up in the map 00414 std::map<const Node*, 00415 unsigned int>::const_iterator pos = _node_id.find(n); 00416 00417 if (pos == _node_id.end()) 00418 libmesh_error_msg("ERROR: No foreign id stored for the node with the libMesh id = " << n->id()); 00419 00420 else 00421 return pos->second; 00422 } 00423 else if (_compatibility_mode) 00424 // when only in compatibility mode, 00425 // return libMesh's node id 00426 return n->id(); 00427 00428 libmesh_error_msg("We'll never get here!"); 00429 return 0; 00430 } 00431 00432 00433 00434 00435 00436 00437 00438 00439 const Elem* MeshData::foreign_id_to_elem (const unsigned int fid) const 00440 { 00441 if (_active) 00442 { 00443 // when active, use our _id_elem map 00444 libmesh_assert (_elem_id_map_closed); 00445 00446 std::map<unsigned int, 00447 const Elem*>::const_iterator pos = _id_elem.find(fid); 00448 00449 if (pos == _id_elem.end()) 00450 libmesh_error_msg("ERROR: Have no Elem* associated with the foreign id = " << fid); 00451 00452 else 00453 return pos->second; 00454 } 00455 else if (_compatibility_mode) 00456 // when only in compatibility mode, 00457 // return element using the libMesh id 00458 return this->_mesh.elem(fid); 00459 00460 libmesh_error_msg("We'll never get here!"); 00461 return NULL; 00462 } 00463 00464 00465 00466 00467 00468 unsigned int MeshData::elem_to_foreign_id (const Elem* e) const 00469 { 00470 libmesh_assert(e); 00471 00472 if (_active) 00473 { 00474 // when active, use our _id_elem map 00475 libmesh_assert (_elem_id_map_closed); 00476 00477 // look it up in the map 00478 std::map<const Elem*, 00479 unsigned int>::const_iterator pos = _elem_id.find(e); 00480 00481 if (pos == _elem_id.end()) 00482 libmesh_error_msg("ERROR: No foreign id stored for the element with the libMesh id = " << e->id()); 00483 00484 else 00485 return pos->second; 00486 } 00487 else if (_compatibility_mode) 00488 // when only in compatibility mode, 00489 // return libMesh's element id 00490 return e->id(); 00491 00492 libmesh_error_msg("We'll never get here!"); 00493 return 0; 00494 } 00495 00496 00497 00498 00499 00500 00501 00502 void MeshData::insert_node_data (std::map<const Node*, 00503 std::vector<Number> >& nd, 00504 const bool close_elem_data) 00505 { 00506 libmesh_assert (this->_active || this->_compatibility_mode); 00507 // these are also true in compatibility mode 00508 libmesh_assert (this->_node_id_map_closed); 00509 00510 if (this->_node_data_closed) 00511 libmesh_error_msg("ERROR: Nodal data already closed! Use clear() first!"); 00512 00513 libmesh_assert (this->_node_data.empty()); 00514 00515 #ifdef DEBUG 00516 std::map<const Node*, 00517 std::vector<Number> >::const_iterator nd_pos = nd.begin(); 00518 std::map<const Node*, 00519 std::vector<Number> >::const_iterator nd_end = nd.end(); 00520 00521 // Compare entity-by-entity that the 00522 // sizes of the std::vector's are identical. 00523 // For this, simply take the length of the 0th 00524 // entry as reference length, and compare this 00525 // with the length of the 1st, 2nd... 00526 libmesh_assert (nd_pos != nd_end); 00527 const std::size_t reference_length = (*nd_pos).second.size(); 00528 00529 // advance, so that we compare with the 1st 00530 ++nd_pos; 00531 00532 for (; nd_pos != nd_end; ++nd_pos) 00533 if ( (*nd_pos).second.size() != reference_length) 00534 libmesh_error_msg("ERROR: Size mismatch."); 00535 #endif 00536 00537 // copy over 00538 _node_data = nd; 00539 00540 // we may freely trash the nd 00541 nd.clear(); 00542 00543 // close node data 00544 this->_node_data_closed = true; 00545 00546 // if user wants to, then close elem data, too 00547 if (close_elem_data) 00548 { 00549 libmesh_assert((this->_elem_id_map_closed)); 00550 this->_elem_data_closed = true; 00551 } 00552 } 00553 00554 00555 00556 00557 00558 void MeshData::insert_elem_data (std::map<const Elem*, 00559 std::vector<Number> >& ed, 00560 const bool close_node_data) 00561 { 00562 libmesh_assert (this->_active || this->_compatibility_mode); 00563 // these are also true in compatibility mode 00564 libmesh_assert (this->_elem_id_map_closed); 00565 00566 if (this->_elem_data_closed) 00567 libmesh_error_msg("ERROR: Element data already closed! Use clear() first!"); 00568 00569 libmesh_assert (this->_elem_data.empty()); 00570 00571 #ifdef DEBUG 00572 std::map<const Elem*, 00573 std::vector<Number> >::const_iterator ed_pos = ed.begin(); 00574 std::map<const Elem*, 00575 std::vector<Number> >::const_iterator ed_end = ed.end(); 00576 00577 // Compare entity-by-entity that the 00578 // sizes of the std::vector's are identical. 00579 const std::size_t reference_length = (*ed_pos).second.size(); 00580 ++ed_pos; 00581 00582 for (; ed_pos != ed_end; ++ed_pos) 00583 if ( (*ed_pos).second.size() != reference_length) 00584 libmesh_error_msg("ERROR: Size mismatch."); 00585 #endif 00586 00587 // copy over 00588 _elem_data = ed; 00589 00590 // we may freely trash the ed 00591 ed.clear(); 00592 00593 // close elem data 00594 this->_elem_data_closed = true; 00595 00596 // if user wants to, then close node data, too 00597 if (close_node_data) 00598 { 00599 libmesh_assert((this->_node_id_map_closed)); 00600 this->_node_data_closed = true; 00601 } 00602 } 00603 00604 00605 00606 00607 00608 unsigned int MeshData::n_val_per_node () const 00609 { 00610 libmesh_assert (this->_active || this->_compatibility_mode); 00611 libmesh_assert (this->_node_data_closed); 00612 00613 if (!this->_node_data.empty()) 00614 { 00615 std::map<const Node*, 00616 std::vector<Number> >::const_iterator pos = _node_data.begin(); 00617 libmesh_assert (pos != _node_data.end()); 00618 return cast_int<unsigned int>(pos->second.size()); 00619 } 00620 else 00621 return 0; 00622 } 00623 00624 00625 00626 00627 dof_id_type MeshData::n_node_data () const 00628 { 00629 libmesh_assert (this->_active || this->_compatibility_mode); 00630 libmesh_assert (this->_node_data_closed); 00631 00632 return cast_int<dof_id_type>(this->_node_data.size()); 00633 } 00634 00635 00636 00637 00638 unsigned int MeshData::n_val_per_elem () const 00639 { 00640 libmesh_assert (this->_active || this->_compatibility_mode); 00641 libmesh_assert (this->_elem_data_closed); 00642 00643 if (!_elem_data.empty()) 00644 { 00645 std::map<const Elem*, 00646 std::vector<Number> >::const_iterator pos = _elem_data.begin(); 00647 libmesh_assert (pos != _elem_data.end()); 00648 return cast_int<unsigned int>(pos->second.size()); 00649 } 00650 else 00651 return 0; 00652 } 00653 00654 00655 00656 00657 dof_id_type MeshData::n_elem_data () const 00658 { 00659 libmesh_assert (this->_active || this->_compatibility_mode); 00660 libmesh_assert (this->_elem_data_closed); 00661 00662 return cast_int<dof_id_type>(_elem_data.size()); 00663 } 00664 00665 00666 00667 00668 void MeshData::assign (const MeshData& omd) 00669 { 00670 this->_data_descriptor = omd._data_descriptor; 00671 this->_node_id_map_closed = omd._node_id_map_closed; 00672 this->_node_data_closed = omd._node_data_closed; 00673 00674 // we have to be able to modify our elem id maps 00675 libmesh_assert (!this->_elem_id_map_closed); 00676 00677 this->_elem_data_closed = omd._elem_data_closed; 00678 this->_active = omd._active; 00679 this->_compatibility_mode = omd._compatibility_mode; 00680 00681 // this is ok because we do not manage the UnvHeader 00682 // in terms of memory, but only hold a pointer to it... 00683 this->_unv_header = omd._unv_header; 00684 00685 // Now copy the foreign id maps -- but only for the 00686 // nodes. The nodes of the boundary mesh are actually 00687 // nodes of the volume mesh. 00688 this->_node_id = omd._node_id; 00689 this->_id_node = omd._id_node; 00690 00691 // The element vector of the boundary mesh contains elements 00692 // that are new, and there _cannot_ be any associated 00693 // foreign id in the maps. Therefore, fill the maps with 00694 // the libMesh id's. But only when the other MeshData 00695 // has element ids. 00696 if ((this->_active) && (omd._elem_id.size() != 0)) 00697 { 00698 00699 MeshBase::const_element_iterator elem_it = _mesh.elements_begin(); 00700 const MeshBase::const_element_iterator elem_end = _mesh.elements_end(); 00701 00702 for (; elem_it != elem_end; ++elem_it) 00703 { 00704 const Elem* elem = *elem_it; 00705 this->add_foreign_elem_id(elem, elem->id()); 00706 } 00707 } 00708 00709 // now we can safely assign omd's value 00710 this->_elem_id_map_closed = omd._elem_id_map_closed; 00711 00712 00713 // and finally the node- and element-associated data 00714 this->_node_data = omd._node_data; 00715 this->_elem_data = omd._elem_data; 00716 } 00717 00718 } // namespace libMesh