$extrastylesheet
location_maps.C
Go to the documentation of this file.
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