$extrastylesheet
point_locator_list.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 
00022 // Local Includes
00023 #include "libmesh/elem.h"
00024 #include "libmesh/libmesh_logging.h"
00025 #include "libmesh/mesh_base.h"
00026 #include "libmesh/point_locator_list.h"
00027 
00028 namespace libMesh
00029 {
00030 
00031 
00032 // typedefs
00033 typedef std::vector<Point>::const_iterator   const_list_iterator;
00034 
00035 
00036 //------------------------------------------------------------------
00037 // PointLocator methods
00038 PointLocatorList::PointLocatorList (const MeshBase& mesh,
00039                                     const PointLocatorBase* master) :
00040   PointLocatorBase (mesh,master),
00041   _list            (NULL)
00042 {
00043   // This code will only work if your mesh is the Voroni mesh of it's
00044   // own elements' centroids.  If your mesh is that regular you might
00045   // as well hand-code an O(1) algorithm for locating points within
00046   // it. - RHS
00047   libmesh_experimental();
00048 
00049   this->init();
00050 }
00051 
00052 
00053 
00054 PointLocatorList::~PointLocatorList ()
00055 {
00056   this->clear ();
00057 }
00058 
00059 
00060 
00061 void PointLocatorList::clear ()
00062 {
00063   // only delete the list when we are the master
00064   if (this->_list != NULL)
00065     {
00066       if (this->_master == NULL)
00067         {
00068           // we own the list
00069           this->_list->clear();
00070           delete this->_list;
00071         }
00072       else
00073         // someone else owns and therefore deletes the list
00074         this->_list = NULL;
00075     }
00076 }
00077 
00078 
00079 
00080 void PointLocatorList::init ()
00081 {
00082   libmesh_assert (!this->_list);
00083 
00084   if (this->_initialized)
00085     libMesh::err << "ERROR: Already initialized!  Will ignore this call..." << std::endl;
00086 
00087   else
00088     {
00089       if (this->_master == NULL)
00090         {
00091           START_LOG("init(no master)", "PointLocatorList");
00092 
00093           // We are the master, so we have to build the list.
00094           // First create it, then get a handy reference, and
00095           // then try to speed up by reserving space...
00096           this->_list = new std::vector<std::pair<Point, const Elem *> >;
00097           std::vector<std::pair<Point, const Elem *> >& my_list = *(this->_list);
00098 
00099           my_list.clear();
00100           my_list.reserve(this->_mesh.n_active_elem());
00101 
00102           // fill our list with the centroids and element
00103           // pointers of the mesh.  For this use the handy
00104           // element iterators.
00105           MeshBase::const_element_iterator       el  = _mesh.active_elements_begin();
00106           const MeshBase::const_element_iterator end = _mesh.active_elements_end();
00107 
00108           for (; el!=end; ++el)
00109             my_list.push_back(std::make_pair((*el)->centroid(), *el));
00110 
00111           STOP_LOG("init(no master)", "PointLocatorList");
00112         }
00113 
00114       else
00115         {
00116           // We are _not_ the master.  Let our _list point to
00117           // the master's list.  But for this we first transform
00118           // the master in a state for which we are friends
00119           // (this should also beware of a bad master pointer?).
00120           // And make sure the master @e has a list!
00121           const PointLocatorList* my_master =
00122             cast_ptr<const PointLocatorList*>(this->_master);
00123 
00124           if (my_master->initialized())
00125             this->_list = my_master->_list;
00126           else
00127             libmesh_error_msg("ERROR: Initialize master first, then servants!");
00128         }
00129     }
00130 
00131   // ready for take-off
00132   this->_initialized = true;
00133 }
00134 
00135 
00136 
00137 const Elem* PointLocatorList::operator() (const Point& p, const std::set<subdomain_id_type> *allowed_subdomains) const
00138 {
00139   libmesh_assert (this->_initialized);
00140 
00141   START_LOG("operator()", "PointLocatorList");
00142 
00143   // Ask the list.  This is quite expensive, since
00144   // we loop through the whole list to try to find
00145   // the @e nearest element.
00146   // However, there is not much else to do: when
00147   // we would use bounding boxes like in a tree,
00148   // it may happen that a surface element is just
00149   // in plane with a bounding box face, and quite
00150   // close to it.  But when a point comes, this
00151   // point may belong to the bounding box (where the
00152   // coplanar element does @e not belong to).  Then
00153   // we would search through the elements in this
00154   // bounding box, while the other bounding box'es
00155   // element is closer, but we simply don't consider
00156   // it!
00157   //
00158   // We _can_, however, use size_sq() instead of size()
00159   // here to avoid repeated calls to std::sqrt(), which is
00160   // pretty expensive.
00161   {
00162     std::vector<std::pair<Point, const Elem *> >& my_list = *(this->_list);
00163 
00164     Real              last_distance_sq = std::numeric_limits<Real>::max();
00165     const Elem *      last_elem        = NULL;
00166     const std::size_t max_index        = my_list.size();
00167 
00168     for (std::size_t n=0; n<max_index; n++)
00169       {
00170         // Only consider elements in the allowed_subdomains list, if it exists
00171         if (!allowed_subdomains ||
00172             allowed_subdomains->count(my_list[n].second->subdomain_id()))
00173           {
00174             const Real current_distance_sq = Point(my_list[n].first -p).size_sq();
00175 
00176             if (current_distance_sq < last_distance_sq)
00177               {
00178                 last_distance_sq = current_distance_sq;
00179                 last_elem        = my_list[n].second;
00180               }
00181           }
00182       }
00183 
00184     // If we found an element, it should be active
00185     libmesh_assert (!last_elem || last_elem->active());
00186 
00187     // If we found an element and have a restriction list, they better match
00188     libmesh_assert (!last_elem || !allowed_subdomains || allowed_subdomains->count(last_elem->subdomain_id()));
00189 
00190     STOP_LOG("operator()", "PointLocatorList");
00191 
00192     // return the element
00193     return last_elem;
00194   }
00195 }
00196 
00197 
00198 
00199 void PointLocatorList::enable_out_of_mesh_mode ()
00200 {
00201   // This functionality is not yet implemented for PointLocatorList.
00202   libmesh_not_implemented();
00203 }
00204 
00205 
00206 
00207 void PointLocatorList::disable_out_of_mesh_mode ()
00208 {
00209   // This functionality is not yet implemented for PointLocatorList.
00210   libmesh_not_implemented();
00211 }
00212 
00213 
00214 void PointLocatorList::set_close_to_point_tol (Real /*close_to_point_tol*/)
00215 {
00216   // This functionality is not yet implemented for PointLocatorList.
00217   libmesh_not_implemented();
00218 }
00219 
00220 
00221 void PointLocatorList::unset_close_to_point_tol ()
00222 {
00223   // This functionality is not yet implemented for PointLocatorList.
00224   libmesh_not_implemented();
00225 }
00226 
00227 } // namespace libMesh