mesh_data.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // C++ includes
21 #include <sstream>
22 
23 // Local includes
24 #include "libmesh/mesh_data.h"
25 #include "libmesh/mesh_base.h"
27 #include "libmesh/elem.h"
28 
29 namespace libMesh
30 {
31 
32 
33 //------------------------------------------------------
34 // MeshData functions
36  _mesh (m),
37  _data_descriptor (""),
38  _node_id_map_closed (false),
39  _node_data_closed (false),
40  _elem_id_map_closed (false),
41  _elem_data_closed (false),
42  _active (false),
43  _compatibility_mode (false),
44  _unv_header (NULL)
45 {
46  // This class isn't actively maintained, doesn't work in parallel,
47  // and usually isn't as good a solution as adding an additional
48  // ExplicitSystem with appropriate data field(s).
49  libmesh_deprecated();
50 }
51 
52 
53 
54 
56 {
57  clear();
58 }
59 
60 
61 
62 
63 
64 void MeshData::activate (const std::string& descriptor)
65 {
66 #ifdef DEBUG
68  libMesh::err << "WARNING: MeshData was in compatibility mode, now being activated."
69  << std::endl;
70 #endif
71 
72  _compatibility_mode = false;
73  _active = true;
74  _data_descriptor = descriptor;
75 }
76 
77 
78 
79 
80 
81 void MeshData::enable_compatibility_mode (const std::string& descriptor)
82 {
83  if (!_active)
84  {
85  _compatibility_mode = true;
86  _active = false;
87  // do as if the id maps are already closed
88  _node_id_map_closed = true;
89  _elem_id_map_closed = true;
90  _data_descriptor = descriptor;
91  // we can safely clear the id maps
92  _node_id.clear();
93  _id_node.clear();
94  _elem_id.clear();
95  _id_elem.clear();
96  }
97 #ifdef DEBUG
98  else
99  libMesh::err << "WARNING: MeshData was in compatibility mode, now being activated."
100  << std::endl;
101 #endif
102 }
103 
104 
105 
106 
107 
108 
110 {
111  _data_descriptor = "";
112  _node_data.clear();
113  _elem_data.clear();
114  _node_data_closed = false;
115  _elem_data_closed = false;
116 }
117 
118 
119 
120 
121 
122 void MeshData::slim (const bool node_id_map,
123  const bool elem_id_map)
124 {
125  if (this->active())
126  {
127 
128  if (node_id_map)
129  {
130  // dumb check
132 
133  _node_id_map_closed = false;
134  _node_id.clear();
135  _id_node.clear();
136  }
137 
138  if (elem_id_map)
139  {
140  // dumb check
142 
143  _elem_id_map_closed = false;
144  _elem_id.clear();
145  _id_elem.clear();
146  }
147  }
148 
149 #ifdef DEBUG
150  else if (this->compatibility_mode())
151  {
152  libMesh::err << "WARNING: No need for MeshData::slim() in compatibility mode." << std::endl;
153  }
154 #endif
155 }
156 
157 
158 
159 
160 void MeshData::translate (const MeshBase& out_mesh,
161  std::vector<Number>& values,
162  std::vector<std::string>& names) const
163 {
165 
166  START_LOG("translate()", "MeshData");
167 
168  const unsigned int n_comp = this->n_val_per_node();
169 
170  // transfer our nodal data to a vector
171  // that may be written concurrently
172  // with the \p out_mesh.
173  {
174  // reserve memory for the nodal data
175  values.reserve(n_comp*out_mesh.n_nodes());
176 
177  // iterate over the mesh's nodes
178  MeshBase::const_node_iterator nodes_it = out_mesh.nodes_begin();
179  const MeshBase::const_node_iterator nodes_end = out_mesh.nodes_end();
180 
181  // Do not use the \p get_data() method, but the operator()
182  // method, since this returns by default a zero value,
183  // when there is no nodal data.
184  for (; nodes_it != nodes_end; ++nodes_it)
185  {
186  const Node* node = *nodes_it;
187 
188  for (unsigned int c= 0; c<n_comp; c++)
189  values.push_back(this->operator()(node, c));
190  }
191  }
192 
193 
194 
195  // Now we have the data, nicely stored in \p values.
196  // It remains to give names to the data, then write to
197  // file.
198  {
199  names.reserve(n_comp);
200 
201  // this naming scheme only works up to n_comp=100
202  // (at least for gmv-accepted variable names)
203  libmesh_assert_less (n_comp, 100);
204 
205  for (unsigned int n=0; n<n_comp; n++)
206  {
207  std::ostringstream name_buf;
208  name_buf << "bc_" << n;
209  names.push_back(name_buf.str());
210  }
211  }
212 
213  STOP_LOG("translate()", "MeshData");
214 }
215 
216 
217 
218 
220 {
221  if (_active)
222  {
223  libmesh_assert (!_elem_id.empty());
224  libmesh_assert (!_id_elem.empty());
225  libmesh_assert (!_node_id.empty());
226  libmesh_assert (!_id_node.empty());
227 
228  _elem_id_map_closed = true;
229  _node_id_map_closed = true;
230  }
231 }
232 
233 
234 
235 
236 
237 void MeshData::read (const std::string& name)
238 {
239  START_LOG("read()", "MeshData");
240 
242 
243  // the id maps have to be closed before reading
244  // (note that in compatibility mode these are also true)
246 
247 #ifdef DEBUG
248  if (this->compatibility_mode())
249  libMesh::err << "WARNING: MeshData in compatibility mode, node and element ids" << std::endl
250  << " stored in file may be totally different from libMesh ids!" << std::endl;
251 #endif
252 
253  // Read the file based on extension. We let all processors read the
254  // data because it would be inaccurate to let only one processor
255  // have it and we're too lazy to code up a proper parallel read or
256  // read+broadcast right now.
257 
258  if (name.rfind(".xta") < name.size())
259  this->read_xdr (name, READ);
260 
261  else if (name.rfind(".xtr") < name.size())
262  this->read_xdr (name, DECODE);
263 
264  else if (name.rfind(".unv") < name.size())
265  this->read_unv (name);
266 
267  else if ((name.rfind(".node") < name.size()) ||
268  (name.rfind(".ele") < name.size()))
269  this->read_tetgen (name);
270 
271  else
272  {
273  libMesh::err << " ERROR: Unrecognized file extension: " << name
274  << "\n I understand the following:\n\n"
275  << " *.xta -- Internal ASCII data format\n"
276  << " *.xtr -- Internal binary data format\n"
277  << " *.unv -- I-deas format\n"
278  << std::endl;
279  libmesh_error();
280 
281  }
282  STOP_LOG("read()", "MeshData");
283 }
284 
285 
286 
287 
288 
289 
290 void MeshData::write (const std::string& name)
291 {
292  START_LOG("write()", "MeshData");
293 
295 
296  // the id maps have to be closed before writing
297  // (note that in compatibility mode these are also true)
299 
300 #ifdef DEBUG
301  if (this->compatibility_mode())
302  libMesh::err << "WARNING: MeshData in compatibility mode. Node and element ids" << std::endl
303  << " written to file may differ from libMesh numbering" << std::endl
304  << " next time this file is read!" << std::endl;
305 #endif
306 
307  // Read the file based on extension
308  {
309  if (name.rfind(".xta") < name.size())
310  write_xdr (name, WRITE);
311 
312  else if (name.rfind(".xtr") < name.size())
313  write_xdr (name, ENCODE);
314 
315  else if (name.rfind(".unv") < name.size())
316  write_unv (name);
317 
318  else
319  {
320  libMesh::err << " ERROR: Unrecognized file extension: " << name
321  << "\n I understand the following:\n\n"
322  << " *.xta -- Internal ASCII data format\n"
323  << " *.xtr -- Internal binary data format\n"
324  << " *.unv -- I-deas format\n"
325  << std::endl;
326  libmesh_error();
327 
328  }
329  }
330  STOP_LOG("write()", "MeshData");
331 }
332 
333 
334 
335 
336 std::string MeshData::get_info() const
337 {
338  std::ostringstream oss;
339 
340  if (this->active() || this->compatibility_mode())
341  {
342  oss << " MeshData Information:\n";
343  if (this->active())
344  oss << " object activated.\n";
345  if (this->compatibility_mode())
346  oss << " object in compatibility mode.\n";
347  if (this->_data_descriptor != "")
348  oss << " descriptor=" << this->_data_descriptor << '\n';
349  if (this->elem_initialized())
350  oss << " Element associated data initialized.\n"
351  << " n_val_per_elem()=" << this->n_val_per_elem() << '\n'
352  << " n_elem_data()=" << this->n_elem_data() << '\n';
353  if (this->node_initialized())
354  oss << " Node associated data initialized.\n"
355  << " n_val_per_node()=" << this->n_val_per_node() << '\n'
356  << " n_node_data()=" << this->n_node_data() << '\n';
357  }
358  else
359  oss << " MeshData neither active nor in compatibility mode.\n";
360 
361  return oss.str();
362 }
363 
364 
365 
366 
367 void MeshData::print_info(std::ostream& os) const
368 {
369  os << this->get_info()
370  << std::endl;
371 }
372 
373 
374 std::ostream& operator << (std::ostream& os, const MeshData& m)
375 {
376  m.print_info(os);
377  return os;
378 }
379 
380 
381 
382 
383 const Node* MeshData::foreign_id_to_node (const unsigned int fid) const
384 {
385  if (_active)
386  {
387  // when active, use our _id_node map
389 
390  std::map<unsigned int,
391  const Node*>::const_iterator pos = _id_node.find(fid);
392 
393  if (pos == _id_node.end())
394  {
395  libMesh::err << "ERROR: Have no Node* associated with the foreign id = "
396  << fid
397  << std::endl;
398  libmesh_error();
399  return NULL;
400  }
401  else
402  return pos->second;
403  }
404  else if (_compatibility_mode)
405  // when only in compatibility mode,
406  // return the node stored in the MeshBase
407  // under its current id
408  return this->_mesh.node_ptr(fid);
409 
410  // should never get here
411  libmesh_error();
412  return NULL;
413 }
414 
415 
416 
417 
418 
419 unsigned int MeshData::node_to_foreign_id (const Node* n) const
420 {
421  libmesh_assert(n);
422 
423  if (_active)
424  {
425  // when active, use our _node_id map
427 
428  // look it up in the map
429  std::map<const Node*,
430  unsigned int>::const_iterator pos = _node_id.find(n);
431 
432  if (pos == _node_id.end())
433  {
434  libMesh::err << "ERROR: No foreign id stored for the node "
435  << "with the libMesh id = "
436  << n->id()
437  << std::endl;
438  libmesh_error();
439  return 0;
440  }
441  else
442  return pos->second;
443  }
444  else if (_compatibility_mode)
445  // when only in compatibility mode,
446  // return libMesh's node id
447  return n->id();
448 
449  // should never get here
450  libmesh_error();
451  return 0;
452 }
453 
454 
455 
456 
457 
458 
459 
460 
461 const Elem* MeshData::foreign_id_to_elem (const unsigned int fid) const
462 {
463  if (_active)
464  {
465  // when active, use our _id_elem map
467 
468  std::map<unsigned int,
469  const Elem*>::const_iterator pos = _id_elem.find(fid);
470 
471  if (pos == _id_elem.end())
472  {
473  libMesh::err << "ERROR: Have no Elem* associated with the foreign id = "
474  << fid
475  << std::endl;
476  libmesh_error();
477  return NULL;
478  }
479  else
480  return pos->second;
481  }
482  else if (_compatibility_mode)
483  // when only in compatibility mode,
484  // return element using the libMesh id
485  return this->_mesh.elem(fid);
486 
487  // should never get here
488  libmesh_error();
489  return NULL;
490 }
491 
492 
493 
494 
495 
496 unsigned int MeshData::elem_to_foreign_id (const Elem* e) const
497 {
498  libmesh_assert(e);
499 
500  if (_active)
501  {
502  // when active, use our _id_elem map
504 
505  // look it up in the map
506  std::map<const Elem*,
507  unsigned int>::const_iterator pos = _elem_id.find(e);
508 
509  if (pos == _elem_id.end())
510  {
511  libMesh::err << "ERROR: No foreign id stored for the element "
512  << "with the libMesh id = "
513  << e->id()
514  << std::endl;
515  libmesh_error();
516  return 0;
517  }
518  else
519  return pos->second;
520  }
521  else if (_compatibility_mode)
522  // when only in compatibility mode,
523  // return libMesh's element id
524  return e->id();
525 
526  // should never get here
527  libmesh_error();
528  return 0;
529 }
530 
531 
532 
533 
534 
535 
536 
537 void MeshData::insert_node_data (std::map<const Node*,
538  std::vector<Number> >& nd,
539  const bool close_elem_data)
540 {
541  libmesh_assert (this->_active || this->_compatibility_mode);
542  // these are also true in compatibility mode
544 
545  if (this->_node_data_closed)
546  {
547  libMesh::err << "ERROR: Nodal data already closed! Use clear() first!"
548  << std::endl;
549  libmesh_error();
550  }
551 
552  libmesh_assert (this->_node_data.empty());
553 
554 #ifdef DEBUG
555  std::map<const Node*,
556  std::vector<Number> >::const_iterator nd_pos = nd.begin();
557  std::map<const Node*,
558  std::vector<Number> >::const_iterator nd_end = nd.end();
559 
560  // Compare entity-by-entity that the
561  // sizes of the std::vector's are identical.
562  // For this, simply take the length of the 0th
563  // entry as reference length, and compare this
564  // with the length of the 1st, 2nd...
565  libmesh_assert (nd_pos != nd_end);
566  const unsigned int reference_length = (*nd_pos).second.size();
567 
568  // advance, so that we compare with the 1st
569  ++nd_pos;
570 
571  for (; nd_pos != nd_end; ++nd_pos)
572  if ( (*nd_pos).second.size() != reference_length)
573  {
574  libMesh::err << "ERROR: Size mismatch."
575  << std::endl;
576  libmesh_error();
577  }
578 #endif
579 
580  // copy over
581  _node_data = nd;
582 
583  // we may freely trash the nd
584  nd.clear();
585 
586  // close node data
587  this->_node_data_closed = true;
588 
589  // if user wants to, then close elem data, too
590  if (close_elem_data)
591  {
593  this->_elem_data_closed = true;
594  }
595 }
596 
597 
598 
599 
600 
601 void MeshData::insert_elem_data (std::map<const Elem*,
602  std::vector<Number> >& ed,
603  const bool close_node_data)
604 {
605  libmesh_assert (this->_active || this->_compatibility_mode);
606  // these are also true in compatibility mode
608 
609  if (this->_elem_data_closed)
610  {
611  libMesh::err << "ERROR: Element data already closed! Use clear() first!"
612  << std::endl;
613  libmesh_error();
614  }
615 
616  libmesh_assert (this->_elem_data.empty());
617 
618 #ifdef DEBUG
619  std::map<const Elem*,
620  std::vector<Number> >::const_iterator ed_pos = ed.begin();
621  std::map<const Elem*,
622  std::vector<Number> >::const_iterator ed_end = ed.end();
623 
624  // Compare entity-by-entity that the
625  // sizes of the std::vector's are identical.
626  const unsigned int reference_length = (*ed_pos).second.size();
627  ++ed_pos;
628 
629  for (; ed_pos != ed_end; ++ed_pos)
630  if ( (*ed_pos).second.size() != reference_length)
631  {
632  libMesh::err << "ERROR: Size mismatch."
633  << std::endl;
634  libmesh_error();
635  }
636 #endif
637 
638  // copy over
639  _elem_data = ed;
640 
641  // we may freely trash the ed
642  ed.clear();
643 
644  // close elem data
645  this->_elem_data_closed = true;
646 
647  // if user wants to, then close node data, too
648  if (close_node_data)
649  {
651  this->_node_data_closed = true;
652  }
653 }
654 
655 
656 
657 
658 
659 unsigned int MeshData::n_val_per_node () const
660 {
661  libmesh_assert (this->_active || this->_compatibility_mode);
663 
664  if (!this->_node_data.empty())
665  {
666  std::map<const Node*,
667  std::vector<Number> >::const_iterator pos = _node_data.begin();
668  libmesh_assert (pos != _node_data.end());
669  return (pos->second.size());
670  }
671  else
672  return 0;
673 }
674 
675 
676 
677 
678 unsigned int MeshData::n_node_data () const
679 {
680  libmesh_assert (this->_active || this->_compatibility_mode);
682 
683  return this->_node_data.size();
684 }
685 
686 
687 
688 
689 unsigned int MeshData::n_val_per_elem () const
690 {
691  libmesh_assert (this->_active || this->_compatibility_mode);
693 
694  if (!_elem_data.empty())
695  {
696  std::map<const Elem*,
697  std::vector<Number> >::const_iterator pos = _elem_data.begin();
698  libmesh_assert (pos != _elem_data.end());
699  return (pos->second.size());
700  }
701  else
702  return 0;
703 }
704 
705 
706 
707 
708 unsigned int MeshData::n_elem_data () const
709 {
710  libmesh_assert (this->_active || this->_compatibility_mode);
712 
713  return _elem_data.size();
714 }
715 
716 
717 
718 
719 void MeshData::assign (const MeshData& omd)
720 {
724 
725  // we have to be able to modify our elem id maps
727 
729  this->_active = omd._active;
731 
732  // this is ok because we do not manage the UnvHeader
733  // in terms of memory, but only hold a pointer to it...
734  this->_unv_header = omd._unv_header;
735 
736  // Now copy the foreign id maps -- but only for the
737  // nodes. The nodes of the boundary mesh are actually
738  // nodes of the volume mesh.
739  this->_node_id = omd._node_id;
740  this->_id_node = omd._id_node;
741 
742  // The element vector of the boundary mesh contains elements
743  // that are new, and there _cannot_ be any associated
744  // foreign id in the maps. Therefore, fill the maps with
745  // the libMesh id's. But only when the other MeshData
746  // has element ids.
747  if ((this->_active) && (omd._elem_id.size() != 0))
748  {
749 
752 
753  for (; elem_it != elem_end; ++elem_it)
754  {
755  const Elem* elem = *elem_it;
756  this->add_foreign_elem_id(elem, elem->id());
757  }
758  }
759 
760  // now we can safely assign omd's value
762 
763 
764  // and finally the node- and element-associated data
765  this->_node_data = omd._node_data;
766  this->_elem_data = omd._elem_data;
767 }
768 
769 } // namespace libMesh

Site Created By: libMesh Developers
Last modified: February 07 2014 16:57:06 UTC

Hosted By:
SourceForge.net Logo