$extrastylesheet
mesh_data.C
Go to the documentation of this file.
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