mesh_base.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 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 // library configuration 00021 #include "libmesh/libmesh_config.h" 00022 00023 // C++ includes 00024 #include <algorithm> // for std::min 00025 #include <map> // for std::multimap 00026 #include <sstream> // for std::ostringstream 00027 00028 00029 // Local includes 00030 #include "libmesh/boundary_info.h" 00031 #include "libmesh/elem.h" 00032 #include "libmesh/mesh_base.h" 00033 #include "libmesh/parallel.h" 00034 #include "libmesh/partitioner.h" 00035 #include "libmesh/point_locator_base.h" 00036 #include "libmesh/threads.h" 00037 00038 00039 namespace libMesh 00040 { 00041 00042 00043 00044 // ------------------------------------------------------------ 00045 // MeshBase class member functions 00046 MeshBase::MeshBase (unsigned int d) : 00047 boundary_info (new BoundaryInfo(*this)), 00048 _n_parts (1), 00049 _dim (d), 00050 _is_prepared (false), 00051 _point_locator (NULL), 00052 _partitioner (NULL), 00053 _skip_partitioning(false), 00054 _skip_renumber_nodes_and_elements(false) 00055 { 00056 libmesh_assert_less_equal (LIBMESH_DIM, 3); 00057 libmesh_assert_greater_equal (LIBMESH_DIM, _dim); 00058 libmesh_assert (libMesh::initialized()); 00059 } 00060 00061 00062 00063 MeshBase::MeshBase (const MeshBase& other_mesh) : 00064 boundary_info (new BoundaryInfo(*this)), 00065 _n_parts (other_mesh._n_parts), 00066 _dim (other_mesh._dim), 00067 _is_prepared (other_mesh._is_prepared), 00068 _point_locator (NULL), 00069 _partitioner (NULL), 00070 _skip_partitioning(other_mesh._skip_partitioning), 00071 _skip_renumber_nodes_and_elements(false) 00072 { 00073 if(other_mesh._partitioner.get()) 00074 { 00075 _partitioner = other_mesh._partitioner->clone(); 00076 } 00077 } 00078 00079 00080 00081 MeshBase::~MeshBase() 00082 { 00083 this->clear(); 00084 00085 libmesh_assert (!libMesh::closed()); 00086 } 00087 00088 00089 00090 void MeshBase::prepare_for_use (const bool skip_renumber_nodes_and_elements) 00091 { 00092 parallel_only(); 00093 00094 // A distributed mesh may have processors with no elements (or 00095 // processors with no elements of higher dimension, if we ever 00096 // support mixed-dimension meshes), but we want consistent 00097 // mesh_dimension anyways. 00098 libmesh_assert(CommWorld.verify(this->is_serial())); 00099 00100 if (!this->is_serial()) 00101 { 00102 unsigned int dim = this->mesh_dimension(); 00103 CommWorld.max(dim); 00104 this->set_mesh_dimension(dim); 00105 } 00106 00107 // Renumber the nodes and elements so that they in contiguous 00108 // blocks. By default, _skip_renumber_nodes_and_elements is false. 00109 // 00110 // We may currently change that by passing 00111 // skip_renumber_nodes_and_elements==true to this function, but we 00112 // should use the allow_renumbering() accessor instead. 00113 // 00114 // Instances where you if prepare_for_use() should not renumber the nodes 00115 // and elements include reading in e.g. an xda/r or gmv file. In 00116 // this case, the ordering of the nodes may depend on an accompanying 00117 // solution, and the node ordering cannot be changed. 00118 00119 if (skip_renumber_nodes_and_elements) 00120 { 00121 libmesh_deprecated(); 00122 this->allow_renumbering(false); 00123 } 00124 00125 // Mesh modification operations might not leave us with consistent 00126 // id counts, but our partitioner might need that consistency. 00127 if(!_skip_renumber_nodes_and_elements) 00128 this->renumber_nodes_and_elements(); 00129 else 00130 this->update_parallel_id_counts(); 00131 00132 // Let all the elements find their neighbors 00133 this->find_neighbors(); 00134 00135 // Partition the mesh. 00136 this->partition(); 00137 00138 // If we're using ParallelMesh, we'll want it parallelized. 00139 this->delete_remote_elements(); 00140 00141 if(!_skip_renumber_nodes_and_elements) 00142 this->renumber_nodes_and_elements(); 00143 00144 // Reset our PointLocator. This needs to happen any time the elements 00145 // in the underlying elements in the mesh have changed, so we do it here. 00146 this->clear_point_locator(); 00147 00148 // The mesh is now prepared for use. 00149 _is_prepared = true; 00150 } 00151 00152 00153 00154 void MeshBase::clear () 00155 { 00156 // Reset the number of partitions 00157 _n_parts = 1; 00158 00159 // Reset the _is_prepared flag 00160 _is_prepared = false; 00161 00162 // Clear boundary information 00163 this->boundary_info->clear(); 00164 00165 // Clear our point locator. 00166 this->clear_point_locator(); 00167 } 00168 00169 00170 00171 void MeshBase::subdomain_ids (std::set<subdomain_id_type> &ids) const 00172 { 00173 // This requires an inspection on every processor 00174 parallel_only(); 00175 00176 ids.clear(); 00177 00178 const_element_iterator el = this->active_elements_begin(); 00179 const const_element_iterator end = this->active_elements_end(); 00180 00181 for (; el!=end; ++el) 00182 ids.insert((*el)->subdomain_id()); 00183 00184 // Some subdomains may only live on other processors 00185 CommWorld.set_union(ids); 00186 } 00187 00188 00189 00190 subdomain_id_type MeshBase::n_subdomains() const 00191 { 00192 // This requires an inspection on every processor 00193 parallel_only(); 00194 00195 std::set<subdomain_id_type> ids; 00196 00197 this->subdomain_ids (ids); 00198 00199 return ids.size(); 00200 } 00201 00202 00203 00204 00205 dof_id_type MeshBase::n_nodes_on_proc (const processor_id_type proc_id) const 00206 { 00207 // We're either counting a processor's nodes or unpartitioned 00208 // nodes 00209 libmesh_assert (proc_id < libMesh::n_processors() || 00210 proc_id == DofObject::invalid_processor_id); 00211 00212 return static_cast<dof_id_type>(std::distance (this->pid_nodes_begin(proc_id), 00213 this->pid_nodes_end (proc_id))); 00214 } 00215 00216 00217 00218 dof_id_type MeshBase::n_elem_on_proc (const processor_id_type proc_id) const 00219 { 00220 // We're either counting a processor's elements or unpartitioned 00221 // elements 00222 libmesh_assert (proc_id < libMesh::n_processors() || 00223 proc_id == DofObject::invalid_processor_id); 00224 00225 return static_cast<dof_id_type>(std::distance (this->pid_elements_begin(proc_id), 00226 this->pid_elements_end (proc_id))); 00227 } 00228 00229 00230 00231 dof_id_type MeshBase::n_active_elem_on_proc (const processor_id_type proc_id) const 00232 { 00233 libmesh_assert_less (proc_id, libMesh::n_processors()); 00234 return static_cast<dof_id_type>(std::distance (this->active_pid_elements_begin(proc_id), 00235 this->active_pid_elements_end (proc_id))); 00236 } 00237 00238 00239 00240 dof_id_type MeshBase::n_sub_elem () const 00241 { 00242 dof_id_type ne=0; 00243 00244 const_element_iterator el = this->elements_begin(); 00245 const const_element_iterator end = this->elements_end(); 00246 00247 for (; el!=end; ++el) 00248 ne += (*el)->n_sub_elem(); 00249 00250 return ne; 00251 } 00252 00253 00254 00255 dof_id_type MeshBase::n_active_sub_elem () const 00256 { 00257 dof_id_type ne=0; 00258 00259 const_element_iterator el = this->active_elements_begin(); 00260 const const_element_iterator end = this->active_elements_end(); 00261 00262 for (; el!=end; ++el) 00263 ne += (*el)->n_sub_elem(); 00264 00265 return ne; 00266 } 00267 00268 00269 00270 std::string MeshBase::get_info() const 00271 { 00272 std::ostringstream oss; 00273 00274 oss << " Mesh Information:" << '\n' 00275 << " mesh_dimension()=" << this->mesh_dimension() << '\n' 00276 << " spatial_dimension()=" << this->spatial_dimension() << '\n' 00277 << " n_nodes()=" << this->n_nodes() << '\n' 00278 << " n_local_nodes()=" << this->n_local_nodes() << '\n' 00279 << " n_elem()=" << this->n_elem() << '\n' 00280 << " n_local_elem()=" << this->n_local_elem() << '\n' 00281 #ifdef LIBMESH_ENABLE_AMR 00282 << " n_active_elem()=" << this->n_active_elem() << '\n' 00283 #endif 00284 << " n_subdomains()=" << this->n_subdomains() << '\n' 00285 << " n_partitions()=" << this->n_partitions() << '\n' 00286 << " n_processors()=" << libMesh::n_processors() << '\n' 00287 << " n_threads()=" << libMesh::n_threads() << '\n' 00288 << " processor_id()=" << this->processor_id() << '\n'; 00289 00290 return oss.str(); 00291 } 00292 00293 00294 void MeshBase::print_info(std::ostream& os) const 00295 { 00296 os << this->get_info() 00297 << std::endl; 00298 } 00299 00300 00301 std::ostream& operator << (std::ostream& os, const MeshBase& m) 00302 { 00303 m.print_info(os); 00304 return os; 00305 } 00306 00307 00308 void MeshBase::partition (const unsigned int n_parts) 00309 { 00310 // NULL partitioner means don't partition 00311 // Non-serial meshes aren't ready for partitioning yet. 00312 if(!skip_partitioning() && 00313 partitioner().get() && 00314 this->is_serial()) 00315 { 00316 partitioner()->partition (*this, n_parts); 00317 } 00318 else 00319 { 00320 // Make sure locally cached partition count 00321 this->recalculate_n_partitions(); 00322 00323 // Make sure any other locally cached data is correct 00324 this->update_post_partitioning(); 00325 } 00326 } 00327 00328 unsigned int MeshBase::recalculate_n_partitions() 00329 { 00330 const_element_iterator el = this->active_elements_begin(); 00331 const const_element_iterator end = this->active_elements_end(); 00332 00333 unsigned int max_proc_id=0; 00334 00335 for (; el!=end; ++el) 00336 max_proc_id = std::max(max_proc_id, static_cast<unsigned int>((*el)->processor_id())); 00337 00338 // The number of partitions is one more than the max processor ID. 00339 _n_parts = max_proc_id+1; 00340 00341 CommWorld.max(_n_parts); 00342 00343 return _n_parts; 00344 } 00345 00346 00347 00348 const PointLocatorBase& MeshBase::point_locator () const 00349 { 00350 libmesh_deprecated(); 00351 00352 if (_point_locator.get() == NULL) 00353 { 00354 // PointLocator construction may not be safe within threads 00355 libmesh_assert(!Threads::in_threads); 00356 00357 _point_locator.reset (PointLocatorBase::build(TREE, *this).release()); 00358 } 00359 00360 return *_point_locator; 00361 } 00362 00363 00364 AutoPtr<PointLocatorBase> MeshBase::sub_point_locator () const 00365 { 00366 if (_point_locator.get() == NULL) 00367 { 00368 // PointLocator construction may not be safe within threads 00369 libmesh_assert(!Threads::in_threads); 00370 00371 _point_locator.reset (PointLocatorBase::build(TREE, *this).release()); 00372 } 00373 00374 return PointLocatorBase::build(TREE, *this, _point_locator.get()); 00375 } 00376 00377 00378 00379 void MeshBase::clear_point_locator () 00380 { 00381 _point_locator.reset(NULL); 00382 } 00383 00384 00385 00386 std::string& MeshBase::subdomain_name(subdomain_id_type id) 00387 { 00388 return _block_id_to_name[id]; 00389 } 00390 00391 const std::string& MeshBase::subdomain_name(subdomain_id_type id) const 00392 { 00393 // An empty string to return when no matching subdomain name is found 00394 static const std::string empty; 00395 00396 std::map<subdomain_id_type, std::string>::const_iterator iter = _block_id_to_name.find(id); 00397 if (iter == _block_id_to_name.end()) 00398 return empty; 00399 else 00400 return iter->second; 00401 } 00402 00403 00404 00405 00406 subdomain_id_type MeshBase::get_id_by_name(const std::string& name) const 00407 { 00408 // This function is searching the *values* of the map (linear search) 00409 // We might want to make this more efficient... 00410 std::map<subdomain_id_type, std::string>::const_iterator 00411 iter = _block_id_to_name.begin(), 00412 end_iter = _block_id_to_name.end(); 00413 00414 for ( ; iter != end_iter; ++iter) 00415 { 00416 if (iter->second == name) 00417 return iter->first; 00418 } 00419 00420 libMesh::err << "Block '" << name << "' does not exist in mesh" << std::endl; 00421 libmesh_error(); 00422 } 00423 00424 00425 } // namespace libMesh 00426
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:47 UTC
Hosted By: