mesh_data.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 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 (libMesh::processor_id() == 0) 00259 // { 00260 if (name.rfind(".xta") < name.size()) 00261 this->read_xdr (name, READ); 00262 00263 else if (name.rfind(".xtr") < name.size()) 00264 this->read_xdr (name, DECODE); 00265 00266 else if (name.rfind(".unv") < name.size()) 00267 this->read_unv (name); 00268 00269 else if ((name.rfind(".node") < name.size()) || 00270 (name.rfind(".ele") < name.size())) 00271 this->read_tetgen (name); 00272 00273 else 00274 { 00275 libMesh::err << " ERROR: Unrecognized file extension: " << name 00276 << "\n I understand the following:\n\n" 00277 << " *.xta -- Internal ASCII data format\n" 00278 << " *.xtr -- Internal binary data format\n" 00279 << " *.unv -- I-deas format\n" 00280 << std::endl; 00281 libmesh_error(); 00282 00283 } 00284 //} 00285 STOP_LOG("read()", "MeshData"); 00286 } 00287 00288 00289 00290 00291 00292 00293 void MeshData::write (const std::string& name) 00294 { 00295 START_LOG("write()", "MeshData"); 00296 00297 libmesh_assert (_active || _compatibility_mode); 00298 00299 // the id maps have to be closed before writing 00300 // (note that in compatibility mode these are also true) 00301 libmesh_assert (_elem_id_map_closed && _node_id_map_closed); 00302 00303 #ifdef DEBUG 00304 if (this->compatibility_mode()) 00305 libMesh::err << "WARNING: MeshData in compatibility mode. Node and element ids" << std::endl 00306 << " written to file may differ from libMesh numbering" << std::endl 00307 << " next time this file is read!" << std::endl; 00308 #endif 00309 00310 // Read the file based on extension 00311 { 00312 if (name.rfind(".xta") < name.size()) 00313 write_xdr (name, WRITE); 00314 00315 else if (name.rfind(".xtr") < name.size()) 00316 write_xdr (name, ENCODE); 00317 00318 else if (name.rfind(".unv") < name.size()) 00319 write_unv (name); 00320 00321 else 00322 { 00323 libMesh::err << " ERROR: Unrecognized file extension: " << name 00324 << "\n I understand the following:\n\n" 00325 << " *.xta -- Internal ASCII data format\n" 00326 << " *.xtr -- Internal binary data format\n" 00327 << " *.unv -- I-deas format\n" 00328 << std::endl; 00329 libmesh_error(); 00330 00331 } 00332 } 00333 STOP_LOG("write()", "MeshData"); 00334 } 00335 00336 00337 00338 00339 std::string MeshData::get_info() const 00340 { 00341 std::ostringstream oss; 00342 00343 if (this->active() || this->compatibility_mode()) 00344 { 00345 oss << " MeshData Information:\n"; 00346 if (this->active()) 00347 oss << " object activated.\n"; 00348 if (this->compatibility_mode()) 00349 oss << " object in compatibility mode.\n"; 00350 if (this->_data_descriptor != "") 00351 oss << " descriptor=" << this->_data_descriptor << '\n'; 00352 if (this->elem_initialized()) 00353 oss << " Element associated data initialized.\n" 00354 << " n_val_per_elem()=" << this->n_val_per_elem() << '\n' 00355 << " n_elem_data()=" << this->n_elem_data() << '\n'; 00356 if (this->node_initialized()) 00357 oss << " Node associated data initialized.\n" 00358 << " n_val_per_node()=" << this->n_val_per_node() << '\n' 00359 << " n_node_data()=" << this->n_node_data() << '\n'; 00360 } 00361 else 00362 oss << " MeshData neither active nor in compatibility mode.\n"; 00363 00364 return oss.str(); 00365 } 00366 00367 00368 00369 00370 void MeshData::print_info(std::ostream& os) const 00371 { 00372 os << this->get_info() 00373 << std::endl; 00374 } 00375 00376 00377 std::ostream& operator << (std::ostream& os, const MeshData& m) 00378 { 00379 m.print_info(os); 00380 return os; 00381 } 00382 00383 00384 00385 00386 const Node* MeshData::foreign_id_to_node (const unsigned int fid) const 00387 { 00388 if (_active) 00389 { 00390 // when active, use our _id_node map 00391 libmesh_assert (_node_id_map_closed); 00392 00393 std::map<unsigned int, 00394 const Node*>::const_iterator pos = _id_node.find(fid); 00395 00396 if (pos == _id_node.end()) 00397 { 00398 libMesh::err << "ERROR: Have no Node* associated with the foreign id = " 00399 << fid 00400 << std::endl; 00401 libmesh_error(); 00402 return NULL; 00403 } 00404 else 00405 return pos->second; 00406 } 00407 else if (_compatibility_mode) 00408 // when only in compatibility mode, 00409 // return the node stored in the MeshBase 00410 // under its current id 00411 return this->_mesh.node_ptr(fid); 00412 00413 // should never get here 00414 libmesh_error(); 00415 return NULL; 00416 } 00417 00418 00419 00420 00421 00422 unsigned int MeshData::node_to_foreign_id (const Node* n) const 00423 { 00424 libmesh_assert(n); 00425 00426 if (_active) 00427 { 00428 // when active, use our _node_id map 00429 libmesh_assert (_node_id_map_closed); 00430 00431 // look it up in the map 00432 std::map<const Node*, 00433 unsigned int>::const_iterator pos = _node_id.find(n); 00434 00435 if (pos == _node_id.end()) 00436 { 00437 libMesh::err << "ERROR: No foreign id stored for the node " 00438 << "with the libMesh id = " 00439 << n->id() 00440 << std::endl; 00441 libmesh_error(); 00442 return 0; 00443 } 00444 else 00445 return pos->second; 00446 } 00447 else if (_compatibility_mode) 00448 // when only in compatibility mode, 00449 // return libMesh's node id 00450 return n->id(); 00451 00452 // should never get here 00453 libmesh_error(); 00454 return 0; 00455 } 00456 00457 00458 00459 00460 00461 00462 00463 00464 const Elem* MeshData::foreign_id_to_elem (const unsigned int fid) const 00465 { 00466 if (_active) 00467 { 00468 // when active, use our _id_elem map 00469 libmesh_assert (_elem_id_map_closed); 00470 00471 std::map<unsigned int, 00472 const Elem*>::const_iterator pos = _id_elem.find(fid); 00473 00474 if (pos == _id_elem.end()) 00475 { 00476 libMesh::err << "ERROR: Have no Elem* associated with the foreign id = " 00477 << fid 00478 << std::endl; 00479 libmesh_error(); 00480 return NULL; 00481 } 00482 else 00483 return pos->second; 00484 } 00485 else if (_compatibility_mode) 00486 // when only in compatibility mode, 00487 // return element using the libMesh id 00488 return this->_mesh.elem(fid); 00489 00490 // should never get here 00491 libmesh_error(); 00492 return NULL; 00493 } 00494 00495 00496 00497 00498 00499 unsigned int MeshData::elem_to_foreign_id (const Elem* e) const 00500 { 00501 libmesh_assert(e); 00502 00503 if (_active) 00504 { 00505 // when active, use our _id_elem map 00506 libmesh_assert (_elem_id_map_closed); 00507 00508 // look it up in the map 00509 std::map<const Elem*, 00510 unsigned int>::const_iterator pos = _elem_id.find(e); 00511 00512 if (pos == _elem_id.end()) 00513 { 00514 libMesh::err << "ERROR: No foreign id stored for the element " 00515 << "with the libMesh id = " 00516 << e->id() 00517 << std::endl; 00518 libmesh_error(); 00519 return 0; 00520 } 00521 else 00522 return pos->second; 00523 } 00524 else if (_compatibility_mode) 00525 // when only in compatibility mode, 00526 // return libMesh's element id 00527 return e->id(); 00528 00529 // should never get here 00530 libmesh_error(); 00531 return 0; 00532 } 00533 00534 00535 00536 00537 00538 00539 00540 void MeshData::insert_node_data (std::map<const Node*, 00541 std::vector<Number> >& nd, 00542 const bool close_elem_data) 00543 { 00544 libmesh_assert (this->_active || this->_compatibility_mode); 00545 // these are also true in compatibility mode 00546 libmesh_assert (this->_node_id_map_closed); 00547 00548 if (this->_node_data_closed) 00549 { 00550 libMesh::err << "ERROR: Nodal data already closed! Use clear() first!" 00551 << std::endl; 00552 libmesh_error(); 00553 } 00554 00555 libmesh_assert (this->_node_data.empty()); 00556 00557 #ifdef DEBUG 00558 std::map<const Node*, 00559 std::vector<Number> >::const_iterator nd_pos = nd.begin(); 00560 std::map<const Node*, 00561 std::vector<Number> >::const_iterator nd_end = nd.end(); 00562 00563 // Compare entity-by-entity that the 00564 // sizes of the std::vector's are identical. 00565 // For this, simply take the length of the 0th 00566 // entry as reference length, and compare this 00567 // with the length of the 1st, 2nd... 00568 libmesh_assert (nd_pos != nd_end); 00569 const unsigned int reference_length = (*nd_pos).second.size(); 00570 00571 // advance, so that we compare with the 1st 00572 ++nd_pos; 00573 00574 for (; nd_pos != nd_end; ++nd_pos) 00575 if ( (*nd_pos).second.size() != reference_length) 00576 { 00577 libMesh::err << "ERROR: Size mismatch." 00578 << std::endl; 00579 libmesh_error(); 00580 } 00581 #endif 00582 00583 // copy over 00584 _node_data = nd; 00585 00586 // we may freely trash the nd 00587 nd.clear(); 00588 00589 // close node data 00590 this->_node_data_closed = true; 00591 00592 // if user wants to, then close elem data, too 00593 if (close_elem_data) 00594 { 00595 libmesh_assert((this->_elem_id_map_closed)); 00596 this->_elem_data_closed = true; 00597 } 00598 } 00599 00600 00601 00602 00603 00604 void MeshData::insert_elem_data (std::map<const Elem*, 00605 std::vector<Number> >& ed, 00606 const bool close_node_data) 00607 { 00608 libmesh_assert (this->_active || this->_compatibility_mode); 00609 // these are also true in compatibility mode 00610 libmesh_assert (this->_elem_id_map_closed); 00611 00612 if (this->_elem_data_closed) 00613 { 00614 libMesh::err << "ERROR: Element data already closed! Use clear() first!" 00615 << std::endl; 00616 libmesh_error(); 00617 } 00618 00619 libmesh_assert (this->_elem_data.empty()); 00620 00621 #ifdef DEBUG 00622 std::map<const Elem*, 00623 std::vector<Number> >::const_iterator ed_pos = ed.begin(); 00624 std::map<const Elem*, 00625 std::vector<Number> >::const_iterator ed_end = ed.end(); 00626 00627 // Compare entity-by-entity that the 00628 // sizes of the std::vector's are identical. 00629 const unsigned int reference_length = (*ed_pos).second.size(); 00630 ++ed_pos; 00631 00632 for (; ed_pos != ed_end; ++ed_pos) 00633 if ( (*ed_pos).second.size() != reference_length) 00634 { 00635 libMesh::err << "ERROR: Size mismatch." 00636 << std::endl; 00637 libmesh_error(); 00638 } 00639 #endif 00640 00641 // copy over 00642 _elem_data = ed; 00643 00644 // we may freely trash the ed 00645 ed.clear(); 00646 00647 // close elem data 00648 this->_elem_data_closed = true; 00649 00650 // if user wants to, then close node data, too 00651 if (close_node_data) 00652 { 00653 libmesh_assert((this->_node_id_map_closed)); 00654 this->_node_data_closed = true; 00655 } 00656 } 00657 00658 00659 00660 00661 00662 unsigned int MeshData::n_val_per_node () const 00663 { 00664 libmesh_assert (this->_active || this->_compatibility_mode); 00665 libmesh_assert (this->_node_data_closed); 00666 00667 if (!this->_node_data.empty()) 00668 { 00669 std::map<const Node*, 00670 std::vector<Number> >::const_iterator pos = _node_data.begin(); 00671 libmesh_assert (pos != _node_data.end()); 00672 return (pos->second.size()); 00673 } 00674 else 00675 return 0; 00676 } 00677 00678 00679 00680 00681 unsigned int MeshData::n_node_data () const 00682 { 00683 libmesh_assert (this->_active || this->_compatibility_mode); 00684 libmesh_assert (this->_node_data_closed); 00685 00686 return this->_node_data.size(); 00687 } 00688 00689 00690 00691 00692 unsigned int MeshData::n_val_per_elem () const 00693 { 00694 libmesh_assert (this->_active || this->_compatibility_mode); 00695 libmesh_assert (this->_elem_data_closed); 00696 00697 if (!_elem_data.empty()) 00698 { 00699 std::map<const Elem*, 00700 std::vector<Number> >::const_iterator pos = _elem_data.begin(); 00701 libmesh_assert (pos != _elem_data.end()); 00702 return (pos->second.size()); 00703 } 00704 else 00705 return 0; 00706 } 00707 00708 00709 00710 00711 unsigned int MeshData::n_elem_data () const 00712 { 00713 libmesh_assert (this->_active || this->_compatibility_mode); 00714 libmesh_assert (this->_elem_data_closed); 00715 00716 return _elem_data.size(); 00717 } 00718 00719 00720 00721 00722 void MeshData::assign (const MeshData& omd) 00723 { 00724 this->_data_descriptor = omd._data_descriptor; 00725 this->_node_id_map_closed = omd._node_id_map_closed; 00726 this->_node_data_closed = omd._node_data_closed; 00727 00728 // we have to be able to modify our elem id maps 00729 libmesh_assert (!this->_elem_id_map_closed); 00730 00731 this->_elem_data_closed = omd._elem_data_closed; 00732 this->_active = omd._active; 00733 this->_compatibility_mode = omd._compatibility_mode; 00734 00735 // this is ok because we do not manage the UnvHeader 00736 // in terms of memory, but only hold a pointer to it... 00737 this->_unv_header = omd._unv_header; 00738 00739 // Now copy the foreign id maps -- but only for the 00740 // nodes. The nodes of the boundary mesh are actually 00741 // nodes of the volume mesh. 00742 this->_node_id = omd._node_id; 00743 this->_id_node = omd._id_node; 00744 00745 // The element vector of the boundary mesh contains elements 00746 // that are new, and there _cannot_ be any associated 00747 // foreign id in the maps. Therefore, fill the maps with 00748 // the libMesh id's. But only when the other MeshData 00749 // has element ids. 00750 if ((this->_active) && (omd._elem_id.size() != 0)) 00751 { 00752 00753 MeshBase::const_element_iterator elem_it = _mesh.elements_begin(); 00754 const MeshBase::const_element_iterator elem_end = _mesh.elements_end(); 00755 00756 for (; elem_it != elem_end; ++elem_it) 00757 { 00758 const Elem* elem = *elem_it; 00759 this->add_foreign_elem_id(elem, elem->id()); 00760 } 00761 } 00762 00763 // now we can safely assign omd's value 00764 this->_elem_id_map_closed = omd._elem_id_map_closed; 00765 00766 00767 // and finally the node- and element-associated data 00768 this->_node_data = omd._node_data; 00769 this->_elem_data = omd._elem_data; 00770 } 00771 00772 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:47 UTC
Hosted By: