$extrastylesheet
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 <limits> 00022 #include <utility> 00023 00024 // Local Includes ----------------------------------- 00025 #include "libmesh/elem.h" 00026 #include "libmesh/location_maps.h" 00027 #include "libmesh/mesh_base.h" 00028 #include "libmesh/node.h" 00029 #include "libmesh/parallel.h" 00030 00031 00032 00033 //-------------------------------------------------------------------------- 00034 namespace 00035 { 00036 using libMesh::Real; 00037 00038 // 10 bits per coordinate, to work with 32+ bit machines 00039 const unsigned int chunkmax = 1024; 00040 const Real chunkfloat = 1024.0; 00041 } 00042 00043 00044 00045 namespace libMesh 00046 { 00047 00048 //-------------------------------------------------------------------------- 00049 template <typename T> 00050 void LocationMap<T>::init(MeshBase& mesh) 00051 { 00052 // This function must be run on all processors at once 00053 // for non-serial meshes 00054 if (!mesh.is_serial()) 00055 libmesh_parallel_only(mesh.comm()); 00056 00057 START_LOG("init()", "LocationMap"); 00058 00059 // Clear the old map 00060 _map.clear(); 00061 00062 // Cache a bounding box 00063 _lower_bound.clear(); 00064 _lower_bound.resize(LIBMESH_DIM, std::numeric_limits<Real>::max()); 00065 _upper_bound.clear(); 00066 _upper_bound.resize(LIBMESH_DIM, -std::numeric_limits<Real>::max()); 00067 00068 MeshBase::node_iterator it = mesh.nodes_begin(); 00069 const MeshBase::node_iterator end = mesh.nodes_end(); 00070 00071 for (; it != end; ++it) 00072 { 00073 Node* node = *it; 00074 00075 for (unsigned int i=0; i != LIBMESH_DIM; ++i) 00076 { 00077 // Expand the bounding box if necessary 00078 _lower_bound[i] = std::min(_lower_bound[i], 00079 (*node)(i)); 00080 _upper_bound[i] = std::max(_upper_bound[i], 00081 (*node)(i)); 00082 } 00083 } 00084 00085 // On a parallel mesh we might not yet have a full bounding box 00086 if (!mesh.is_serial()) 00087 { 00088 mesh.comm().min(_lower_bound); 00089 mesh.comm().max(_upper_bound); 00090 } 00091 00092 this->fill(mesh); 00093 00094 STOP_LOG("init()", "LocationMap"); 00095 } 00096 00097 00098 00099 template <typename T> 00100 void LocationMap<T>::insert(T &t) 00101 { 00102 this->_map.insert(std::make_pair(this->key(this->point_of(t)), &t)); 00103 } 00104 00105 00106 00107 template <> 00108 Point LocationMap<Node>::point_of(const Node& node) const 00109 { 00110 return node; 00111 } 00112 00113 00114 00115 template <> 00116 Point LocationMap<Elem>::point_of(const Elem& elem) const 00117 { 00118 return elem.centroid(); 00119 } 00120 00121 00122 00123 template <typename T> 00124 T* LocationMap<T>::find(const Point& p, 00125 const Real tol) 00126 { 00127 START_LOG("find()","LocationMap"); 00128 00129 // Look for a likely key in the multimap 00130 unsigned int pointkey = this->key(p); 00131 00132 // Look for the exact key first 00133 std::pair<typename map_type::iterator, 00134 typename map_type::iterator> 00135 pos = _map.equal_range(pointkey); 00136 00137 while (pos.first != pos.second) 00138 if (p.absolute_fuzzy_equals 00139 (this->point_of(*(pos.first->second)), tol)) 00140 { 00141 STOP_LOG("find()","LocationMap"); 00142 return pos.first->second; 00143 } 00144 else 00145 ++pos.first; 00146 00147 // Look for neighboring bins' keys next 00148 for (int xoffset = -1; xoffset != 2; ++xoffset) 00149 { 00150 for (int yoffset = -1; yoffset != 2; ++yoffset) 00151 { 00152 for (int zoffset = -1; zoffset != 2; ++zoffset) 00153 { 00154 std::pair<typename map_type::iterator, 00155 typename map_type::iterator> 00156 key_pos = _map.equal_range(pointkey + 00157 xoffset*chunkmax*chunkmax + 00158 yoffset*chunkmax + 00159 zoffset); 00160 while (key_pos.first != key_pos.second) 00161 if (p.absolute_fuzzy_equals 00162 (this->point_of(*(key_pos.first->second)), tol)) 00163 { 00164 STOP_LOG("find()","LocationMap"); 00165 return key_pos.first->second; 00166 } 00167 else 00168 ++key_pos.first; 00169 } 00170 } 00171 } 00172 00173 STOP_LOG("find()","LocationMap"); 00174 return NULL; 00175 } 00176 00177 00178 00179 template <typename T> 00180 unsigned int LocationMap<T>::key(const Point& p) 00181 { 00182 Real xscaled = 0., yscaled = 0., zscaled = 0.; 00183 00184 Real deltax = _upper_bound[0] - _lower_bound[0]; 00185 00186 if (std::abs(deltax) > TOLERANCE) 00187 xscaled = (p(0) - _lower_bound[0])/deltax; 00188 00189 // Only check y-coords if libmesh is compiled with LIBMESH_DIM>1 00190 #if LIBMESH_DIM > 1 00191 Real deltay = _upper_bound[1] - _lower_bound[1]; 00192 00193 if (std::abs(deltay) > TOLERANCE) 00194 yscaled = (p(1) - _lower_bound[1])/deltay; 00195 #endif 00196 00197 // Only check z-coords if libmesh is compiled with LIBMESH_DIM>2 00198 #if LIBMESH_DIM > 2 00199 Real deltaz = _upper_bound[2] - _lower_bound[2]; 00200 00201 if (std::abs(deltaz) > TOLERANCE) 00202 zscaled = (p(2) - _lower_bound[2])/deltaz; 00203 #endif 00204 00205 unsigned int n0 = static_cast<unsigned int> (chunkfloat * xscaled), 00206 n1 = static_cast<unsigned int> (chunkfloat * yscaled), 00207 n2 = static_cast<unsigned int> (chunkfloat * zscaled); 00208 00209 return chunkmax*chunkmax*n0 + chunkmax*n1 + n2; 00210 } 00211 00212 00213 00214 template <> 00215 void LocationMap<Node>::fill(MeshBase& mesh) 00216 { 00217 // Populate the nodes map 00218 MeshBase::node_iterator it = mesh.nodes_begin(), 00219 end = mesh.nodes_end(); 00220 for (; it != end; ++it) 00221 this->insert(**it); 00222 } 00223 00224 00225 00226 template <> 00227 void LocationMap<Elem>::fill(MeshBase& mesh) 00228 { 00229 // Populate the elem map 00230 MeshBase::element_iterator it = mesh.active_elements_begin(), 00231 end = mesh.active_elements_end(); 00232 for (; it != end; ++it) 00233 this->insert(**it); 00234 } 00235 00236 00237 00238 template class LocationMap<Elem>; 00239 template class LocationMap<Node>; 00240 00241 } // namespace libMesh