point_locator_tree.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 00022 // Local Includes 00023 #include "libmesh/elem.h" 00024 #include "libmesh/libmesh_logging.h" 00025 #include "libmesh/mesh_base.h" 00026 #include "libmesh/mesh_tools.h" 00027 #include "libmesh/point_locator_tree.h" 00028 #include "libmesh/tree.h" 00029 00030 namespace libMesh 00031 { 00032 00033 00034 00035 //------------------------------------------------------------------ 00036 // PointLocator methods 00037 PointLocatorTree::PointLocatorTree (const MeshBase& mesh, 00038 const PointLocatorBase* master) : 00039 PointLocatorBase (mesh,master), 00040 _tree (NULL), 00041 _element (NULL), 00042 _out_of_mesh_mode(false) 00043 { 00044 this->init(Trees::NODES); 00045 } 00046 00047 00048 00049 00050 PointLocatorTree::PointLocatorTree (const MeshBase& mesh, 00051 const Trees::BuildType build_type, 00052 const PointLocatorBase* master) : 00053 PointLocatorBase (mesh,master), 00054 _tree (NULL), 00055 _element (NULL), 00056 _out_of_mesh_mode(false) 00057 { 00058 this->init(build_type); 00059 } 00060 00061 00062 00063 00064 PointLocatorTree::~PointLocatorTree () 00065 { 00066 this->clear (); 00067 } 00068 00069 00070 00071 00072 void PointLocatorTree::clear () 00073 { 00074 // only delete the tree when we are the master 00075 if (this->_tree != NULL) 00076 { 00077 if (this->_master == NULL) 00078 // we own the tree 00079 delete this->_tree; 00080 else 00081 // someone else owns and therefore deletes the tree 00082 this->_tree = NULL; 00083 } 00084 } 00085 00086 00087 00088 00089 00090 void PointLocatorTree::init (const Trees::BuildType build_type) 00091 { 00092 libmesh_assert (!this->_tree); 00093 00094 if (this->_initialized) 00095 { 00096 libMesh::err << "ERROR: Already initialized! Will ignore this call..." 00097 << std::endl; 00098 } 00099 00100 else 00101 00102 { 00103 00104 if (this->_master == NULL) 00105 { 00106 START_LOG("init(no master)", "PointLocatorTree"); 00107 00108 if (this->_mesh.mesh_dimension() == 3) 00109 _tree = new Trees::OctTree (this->_mesh, 200, build_type); 00110 else 00111 { 00112 // A 1D/2D mesh in 3D space needs special consideration. 00113 // If the mesh is planar XY, we want to build a QuadTree 00114 // to search efficiently. If the mesh is truly a manifold, 00115 // then we need an octree 00116 #if LIBMESH_DIM > 2 00117 bool is_planar_xy = false; 00118 00119 // Build the bounding box for the mesh. If the delta-z bound is 00120 // negligibly small then we can use a quadtree. 00121 { 00122 MeshTools::BoundingBox bbox = MeshTools::bounding_box(this->_mesh); 00123 00124 const Real 00125 Dx = bbox.second(0) - bbox.first(0), 00126 Dz = bbox.second(2) - bbox.first(2); 00127 00128 if (std::abs(Dz/(Dx + 1.e-20)) < 1e-10) 00129 is_planar_xy = true; 00130 } 00131 00132 if (!is_planar_xy) 00133 _tree = new Trees::OctTree (this->_mesh, 200, build_type); 00134 else 00135 #endif 00136 #if LIBMESH_DIM > 1 00137 _tree = new Trees::QuadTree (this->_mesh, 200, build_type); 00138 #else 00139 _tree = new Trees::BinaryTree (this->_mesh, 200, build_type); 00140 #endif 00141 } 00142 00143 STOP_LOG("init(no master)", "PointLocatorTree"); 00144 } 00145 00146 else 00147 00148 { 00149 // We are _not_ the master. Let our Tree point to 00150 // the master's tree. But for this we first transform 00151 // the master in a state for which we are friends. 00152 // And make sure the master @e has a tree! 00153 const PointLocatorTree* my_master = 00154 libmesh_cast_ptr<const PointLocatorTree*>(this->_master); 00155 00156 if (my_master->initialized()) 00157 this->_tree = my_master->_tree; 00158 else 00159 { 00160 libMesh::err << "ERROR: Initialize master first, then servants!" 00161 << std::endl; 00162 libmesh_error(); 00163 } 00164 } 00165 00166 00167 // Not all PointLocators may own a tree, but all of them 00168 // use their own element pointer. Let the element pointer 00169 // be unique for every interpolator. 00170 // Suppose the interpolators are used concurrently 00171 // at different locations in the mesh, then it makes quite 00172 // sense to have unique start elements. 00173 this->_element = NULL; 00174 } 00175 00176 00177 // ready for take-off 00178 this->_initialized = true; 00179 } 00180 00181 00182 00183 00184 00185 const Elem* PointLocatorTree::operator() (const Point& p) const 00186 { 00187 libmesh_assert (this->_initialized); 00188 00189 START_LOG("operator()", "PointLocatorTree"); 00190 00191 // First check the element from last time before asking the tree 00192 if (this->_element==NULL || !(this->_element->contains_point(p))) 00193 { 00194 // ask the tree 00195 this->_element = this->_tree->find_element (p); 00196 00197 if (this->_element == NULL) 00198 { 00199 /* No element seems to contain this point. If out-of-mesh 00200 mode is enabled, just return NULL. If not, however, we 00201 have to perform a linear search before we call \p 00202 libmesh_error() since in the case of curved elements, the 00203 bounding box computed in \p TreeNode::insert(const 00204 Elem*) might be slightly inaccurate. */ 00205 if(!_out_of_mesh_mode) 00206 { 00207 START_LOG("linear search", "PointLocatorTree"); 00208 MeshBase::const_element_iterator pos = this->_mesh.active_elements_begin(); 00209 const MeshBase::const_element_iterator end_pos = this->_mesh.active_elements_end(); 00210 00211 for ( ; pos != end_pos; ++pos) 00212 if ((*pos)->contains_point(p)) 00213 { 00214 STOP_LOG("linear search", "PointLocatorTree"); 00215 STOP_LOG("operator()", "PointLocatorTree"); 00216 return this->_element = (*pos); 00217 } 00218 00219 /* 00220 if (this->_element == NULL) 00221 { 00222 libMesh::err << std::endl 00223 << " ******** Serious Problem. Could not find an Element " 00224 << "in the Mesh" 00225 << std:: endl 00226 << " ******** that contains the Point " 00227 << p; 00228 libmesh_error(); 00229 } 00230 */ 00231 STOP_LOG("linear search", "PointLocatorTree"); 00232 } 00233 } 00234 } 00235 00236 // If we found an element, it should be active 00237 libmesh_assert (!this->_element || this->_element->active()); 00238 00239 STOP_LOG("operator()", "PointLocatorTree"); 00240 00241 // return the element 00242 return this->_element; 00243 } 00244 00245 void PointLocatorTree::enable_out_of_mesh_mode (void) 00246 { 00247 /* Out-of-mesh mode is currently only supported if all of the 00248 elements have affine mappings. The reason is that for quadratic 00249 mappings, it is not easy to construct a relyable bounding box of 00250 the element, and thus, the fallback linear search in \p 00251 operator() is required. Hence, out-of-mesh mode would be 00252 extremely slow. */ 00253 if(!_out_of_mesh_mode) 00254 { 00255 #ifdef DEBUG 00256 MeshBase::const_element_iterator pos = this->_mesh.active_elements_begin(); 00257 const MeshBase::const_element_iterator end_pos = this->_mesh.active_elements_end(); 00258 for ( ; pos != end_pos; ++pos) 00259 if (!(*pos)->has_affine_map()) 00260 { 00261 libMesh::err << "ERROR: Out-of-mesh mode is currently only supported if all elements have affine mappings." << std::endl; 00262 libmesh_error(); 00263 } 00264 #endif 00265 00266 _out_of_mesh_mode = true; 00267 } 00268 } 00269 00270 void PointLocatorTree::disable_out_of_mesh_mode (void) 00271 { 00272 _out_of_mesh_mode = false; 00273 } 00274 00275 } // namespace libMesh 00276
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:48 UTC
Hosted By: