mesh_base.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 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 // library configuration
21 #include "libmesh/libmesh_config.h"
22 
23 // C++ includes
24 #include <algorithm> // for std::min
25 #include <map> // for std::multimap
26 #include <sstream> // for std::ostringstream
27 
28 
29 // Local includes
30 #include "libmesh/boundary_info.h"
31 #include "libmesh/elem.h"
32 #include "libmesh/mesh_base.h"
33 #include "libmesh/parallel.h"
34 #include "libmesh/partitioner.h"
36 #include "libmesh/threads.h"
37 
38 namespace libMesh
39 {
40 
41 
42 
43 // ------------------------------------------------------------
44 // MeshBase class member functions
46  unsigned int d) :
47  ParallelObject (comm),
48  boundary_info (new BoundaryInfo(*this)),
49  _n_parts (1),
50  _dim (d),
51  _is_prepared (false),
52  _point_locator (NULL),
53  _partitioner (NULL),
54 #ifdef LIBMESH_ENABLE_UNIQUE_ID
55  _next_unique_id(DofObject::invalid_unique_id),
56 #endif
57  _skip_partitioning(false),
58  _skip_renumber_nodes_and_elements(false)
59 {
60  libmesh_assert_less_equal (LIBMESH_DIM, 3);
61  libmesh_assert_greater_equal (LIBMESH_DIM, _dim);
63 }
64 
65 
66 #ifndef LIBMESH_DISABLE_COMMWORLD
67 MeshBase::MeshBase (unsigned int d) :
69  boundary_info (new BoundaryInfo(*this)),
70  _n_parts (1),
71  _dim (d),
72  _is_prepared (false),
73  _point_locator (NULL),
74  _partitioner (NULL),
75 #ifdef LIBMESH_ENABLE_UNIQUE_ID
76  _next_unique_id(DofObject::invalid_unique_id),
77 #endif
78  _skip_partitioning(false),
79  _skip_renumber_nodes_and_elements(false)
80 {
81  libmesh_assert_less_equal (LIBMESH_DIM, 3);
82  libmesh_assert_greater_equal (LIBMESH_DIM, _dim);
84 }
85 #endif // !LIBMESH_DISABLE_COMMWORLD
86 
87 
88 
89 MeshBase::MeshBase (const MeshBase& other_mesh) :
90  ParallelObject (other_mesh),
91  boundary_info (new BoundaryInfo(*this)),
92  _n_parts (other_mesh._n_parts),
93  _dim (other_mesh._dim),
94  _is_prepared (other_mesh._is_prepared),
95  _point_locator (NULL),
96  _partitioner (NULL),
97 #ifdef LIBMESH_ENABLE_UNIQUE_ID
98  _next_unique_id(other_mesh._next_unique_id),
99 #endif
100  _skip_partitioning(other_mesh._skip_partitioning),
101  _skip_renumber_nodes_and_elements(false)
102 {
103  if(other_mesh._partitioner.get())
104  {
105  _partitioner = other_mesh._partitioner->clone();
106  }
107 }
108 
109 
110 
112 {
113  this->clear();
114 
116 }
117 
118 
119 
120 void MeshBase::prepare_for_use (const bool skip_renumber_nodes_and_elements)
121 {
122  parallel_object_only();
123 
124  // A distributed mesh may have processors with no elements (or
125  // processors with no elements of higher dimension, if we ever
126  // support mixed-dimension meshes), but we want consistent
127  // mesh_dimension anyways.
128  libmesh_assert(this->comm().verify(this->is_serial()));
129 
130  if (!this->is_serial())
131  {
132  unsigned int dim = this->mesh_dimension();
133  this->comm().max(dim);
134  this->set_mesh_dimension(dim);
135  }
136 
137  // Renumber the nodes and elements so that they in contiguous
138  // blocks. By default, _skip_renumber_nodes_and_elements is false.
139  //
140  // We may currently change that by passing
141  // skip_renumber_nodes_and_elements==true to this function, but we
142  // should use the allow_renumbering() accessor instead.
143  //
144  // Instances where you if prepare_for_use() should not renumber the nodes
145  // and elements include reading in e.g. an xda/r or gmv file. In
146  // this case, the ordering of the nodes may depend on an accompanying
147  // solution, and the node ordering cannot be changed.
148 
149  if (skip_renumber_nodes_and_elements)
150  {
151  libmesh_deprecated();
152  this->allow_renumbering(false);
153  }
154 
155  // Mesh modification operations might not leave us with consistent
156  // id counts, but our partitioner might need that consistency.
159  else
161 
162  // Let all the elements find their neighbors
163  this->find_neighbors();
164 
165  // Partition the mesh.
166  this->partition();
167 
168  // If we're using ParallelMesh, we'll want it parallelized.
169  this->delete_remote_elements();
170 
171 #ifdef LIBMESH_ENABLE_UNIQUE_ID
172  // Assign DOF object unique ids
173  this->assign_unique_ids();
174 #endif
175 
178 
179  // Reset our PointLocator. This needs to happen any time the elements
180  // in the underlying elements in the mesh have changed, so we do it here.
181  this->clear_point_locator();
182 
183  // The mesh is now prepared for use.
184  _is_prepared = true;
185 }
186 
187 
188 
190 {
191  // Reset the number of partitions
192  _n_parts = 1;
193 
194  // Reset the _is_prepared flag
195  _is_prepared = false;
196 
197  // Clear boundary information
198  this->boundary_info->clear();
199 
200  // Clear our point locator.
201  this->clear_point_locator();
202 }
203 
204 
205 
206 void MeshBase::subdomain_ids (std::set<subdomain_id_type> &ids) const
207 {
208  // This requires an inspection on every processor
209  parallel_object_only();
210 
211  ids.clear();
212 
215 
216  for (; el!=end; ++el)
217  ids.insert((*el)->subdomain_id());
218 
219  // Some subdomains may only live on other processors
220  this->comm().set_union(ids);
221 }
222 
223 
224 
226 {
227  // This requires an inspection on every processor
228  parallel_object_only();
229 
230  std::set<subdomain_id_type> ids;
231 
232  this->subdomain_ids (ids);
233 
234  return ids.size();
235 }
236 
237 
238 
239 
241 {
242  // We're either counting a processor's nodes or unpartitioned
243  // nodes
244  libmesh_assert (proc_id < this->n_processors() ||
246 
247  return static_cast<dof_id_type>(std::distance (this->pid_nodes_begin(proc_id),
248  this->pid_nodes_end (proc_id)));
249 }
250 
251 
252 
254 {
255  // We're either counting a processor's elements or unpartitioned
256  // elements
257  libmesh_assert (proc_id < this->n_processors() ||
259 
260  return static_cast<dof_id_type>(std::distance (this->pid_elements_begin(proc_id),
261  this->pid_elements_end (proc_id)));
262 }
263 
264 
265 
267 {
268  libmesh_assert_less (proc_id, this->n_processors());
269  return static_cast<dof_id_type>(std::distance (this->active_pid_elements_begin(proc_id),
270  this->active_pid_elements_end (proc_id)));
271 }
272 
273 
274 
276 {
277  dof_id_type ne=0;
278 
280  const const_element_iterator end = this->elements_end();
281 
282  for (; el!=end; ++el)
283  ne += (*el)->n_sub_elem();
284 
285  return ne;
286 }
287 
288 
289 
291 {
292  dof_id_type ne=0;
293 
296 
297  for (; el!=end; ++el)
298  ne += (*el)->n_sub_elem();
299 
300  return ne;
301 }
302 
303 
304 
305 std::string MeshBase::get_info() const
306 {
307  std::ostringstream oss;
308 
309  oss << " Mesh Information:" << '\n'
310  << " mesh_dimension()=" << this->mesh_dimension() << '\n'
311  << " spatial_dimension()=" << this->spatial_dimension() << '\n'
312  << " n_nodes()=" << this->n_nodes() << '\n'
313  << " n_local_nodes()=" << this->n_local_nodes() << '\n'
314  << " n_elem()=" << this->n_elem() << '\n'
315  << " n_local_elem()=" << this->n_local_elem() << '\n'
316 #ifdef LIBMESH_ENABLE_AMR
317  << " n_active_elem()=" << this->n_active_elem() << '\n'
318 #endif
319  << " n_subdomains()=" << static_cast<std::size_t>(this->n_subdomains()) << '\n'
320  << " n_partitions()=" << static_cast<std::size_t>(this->n_partitions()) << '\n'
321  << " n_processors()=" << static_cast<std::size_t>(this->n_processors()) << '\n'
322  << " n_threads()=" << static_cast<std::size_t>(libMesh::n_threads()) << '\n'
323  << " processor_id()=" << static_cast<std::size_t>(this->processor_id()) << '\n';
324 
325  return oss.str();
326 }
327 
328 
329 void MeshBase::print_info(std::ostream& os) const
330 {
331  os << this->get_info()
332  << std::endl;
333 }
334 
335 
336 std::ostream& operator << (std::ostream& os, const MeshBase& m)
337 {
338  m.print_info(os);
339  return os;
340 }
341 
342 
343 void MeshBase::partition (const unsigned int n_parts)
344 {
345  // NULL partitioner means don't partition
346  // Non-serial meshes aren't ready for partitioning yet.
347  if(!skip_partitioning() &&
348  partitioner().get() &&
349  this->is_serial())
350  {
351  partitioner()->partition (*this, n_parts);
352  }
353  else
354  {
355  // Make sure locally cached partition count
356  this->recalculate_n_partitions();
357 
358  // Make sure any other locally cached data is correct
359  this->update_post_partitioning();
360  }
361 }
362 
364 {
367 
368  unsigned int max_proc_id=0;
369 
370  for (; el!=end; ++el)
371  max_proc_id = std::max(max_proc_id, static_cast<unsigned int>((*el)->processor_id()));
372 
373  // The number of partitions is one more than the max processor ID.
374  _n_parts = max_proc_id+1;
375 
376  this->comm().max(_n_parts);
377 
378  return _n_parts;
379 }
380 
381 
382 
384 {
385  libmesh_deprecated();
386 
387  if (_point_locator.get() == NULL)
388  {
389  // PointLocator construction may not be safe within threads
391 
392  _point_locator.reset (PointLocatorBase::build(TREE, *this).release());
393  }
394 
395  return *_point_locator;
396 }
397 
398 
400 {
401  if (_point_locator.get() == NULL)
402  {
403  // PointLocator construction may not be safe within threads
405 
406  _point_locator.reset (PointLocatorBase::build(TREE, *this).release());
407  }
408 
409  return PointLocatorBase::build(TREE, *this, _point_locator.get());
410 }
411 
412 
413 
415 {
416  _point_locator.reset(NULL);
417 }
418 
419 
420 
422 {
423  return _block_id_to_name[id];
424 }
425 
426 const std::string& MeshBase::subdomain_name(subdomain_id_type id) const
427 {
428  // An empty string to return when no matching subdomain name is found
429  static const std::string empty;
430 
431  std::map<subdomain_id_type, std::string>::const_iterator iter = _block_id_to_name.find(id);
432  if (iter == _block_id_to_name.end())
433  return empty;
434  else
435  return iter->second;
436 }
437 
438 
439 
440 
442 {
443  // This function is searching the *values* of the map (linear search)
444  // We might want to make this more efficient...
445  std::map<subdomain_id_type, std::string>::const_iterator
446  iter = _block_id_to_name.begin(),
447  end_iter = _block_id_to_name.end();
448 
449  for ( ; iter != end_iter; ++iter)
450  {
451  if (iter->second == name)
452  return iter->first;
453  }
454 
455  libMesh::err << "Block '" << name << "' does not exist in mesh" << std::endl;
456  libmesh_error();
457 }
458 
459 
460 } // namespace libMesh

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

Hosted By:
SourceForge.net Logo