ESyS-Particle  4.0.1
NeighbourTable.hpp
00001 
00002 //                                                         //
00003 // Copyright (c) 2003-2011 by The University of Queensland //
00004 // Earth Systems Science Computational Centre (ESSCC)      //
00005 // http://www.uq.edu.au/esscc                              //
00006 //                                                         //
00007 // Primary Business: Brisbane, Queensland, Australia       //
00008 // Licensed under the Open Software License version 3.0    //
00009 // http://www.opensource.org/licenses/osl-3.0.php          //
00010 //                                                         //
00012 
00013 
00014 #ifndef ESYS_LSMNEIGHBOURTABLE_HPP
00015 #define ESYS_LSMNEIGHBOURTABLE_HPP
00016 
00017 namespace esys
00018 {
00019   namespace lsm
00020   {
00021     template <class TmplParticle>
00022     NeighbourTable<TmplParticle>::NeighbourTable(
00023       const BoundingBox &bBox,
00024       double gridSpacing
00025     )
00026       : m_dimensions(),
00027         m_minIndex(),
00028         m_maxIndex(Vec3L(-1, -1, -1)),
00029         m_gridSpacing(gridSpacing),
00030         m_bBox(bBox),
00031         m_insertedParticles(),
00032         m_tablePtr()
00033     {
00034       resize(bBox, gridSpacing);
00035     }
00036 
00037     template <class TmplParticle>
00038     NeighbourTable<TmplParticle>::NeighbourTable(
00039       const NeighbourTable &nTable
00040     )
00041       : m_dimensions(nTable.m_dimensions),
00042         m_minIndex(nTable.m_minIndex),
00043         m_maxIndex(nTable.m_maxIndex),
00044         m_gridSpacing(nTable.m_gridSpacing),
00045         m_bBox(nTable.m_bBox),
00046         m_insertedParticles(nTable.m_insertedParticles),
00047         m_tablePtr()
00048     {
00049       m_tablePtr =
00050         ParticleVectorArrayPtr(
00051           new ParticleVector[nTable.getNumCells()]
00052         );
00053       for (int i = 0; i < nTable.getNumCells(); i++)
00054       {
00055         m_tablePtr[i] = nTable.m_tablePtr[i];
00056       }
00057     }
00058 
00059     template <class TmplParticle>
00060     NeighbourTable<TmplParticle>::~NeighbourTable()
00061     {
00062     }
00063       
00064     template <class TmplParticle>
00065     void NeighbourTable<TmplParticle>::clear()
00066     {
00067       for (int i = getMinVecIndex().X(); i <= getMaxVecIndex().X(); i++) {
00068         for (int j = getMinVecIndex().Y(); j <= getMaxVecIndex().Y(); j++) {
00069           for (int k = getMinVecIndex().Z(); k <= getMaxVecIndex().Z(); k++) {
00070             m_tablePtr[getScalarIndex(i, j, k)].clear();
00071           }
00072         }
00073       }
00074       m_insertedParticles.clear();
00075     }
00076 
00077     template <class TmplParticle>
00078     double NeighbourTable<TmplParticle>::getGridSpacing() const
00079     {
00080       return m_gridSpacing;
00081     }
00082 
00083     template <class TmplParticle>
00084     void NeighbourTable<TmplParticle>::resize(
00085       const BoundingBox &bBox,
00086       double gridSpacing
00087     )
00088     {
00089       ParticleVector particles = getInsertedParticles();
00090       clearAndRecomputeGrid(bBox, gridSpacing);
00091       for (
00092         typename ParticleVector::iterator it = particles.begin();
00093         it != particles.end();
00094         it++
00095       )
00096       {
00097         insert(*it);
00098       }
00099     }
00100 
00101     template <class TmplParticle>
00102     const Vec3L &
00103     NeighbourTable<TmplParticle>::getDimensions() const
00104     {
00105       return m_dimensions;
00106     }
00107 
00108     template <class TmplParticle>
00109     const BoundingBox &
00110     NeighbourTable<TmplParticle>::getBBox() const
00111     {
00112       return m_bBox;
00113     }
00114 
00115     template <class TmplParticle>
00116     const Vec3 &
00117     NeighbourTable<TmplParticle>::getMinPt() const
00118     {
00119       return getBBox().getMinPt();
00120     }
00121 
00122     template <class TmplParticle>
00123     size_t NeighbourTable<TmplParticle>::size() const
00124     {
00125       return m_insertedParticles.size();
00126     }
00127 
00128     template <class TmplParticle>
00129     int NeighbourTable<TmplParticle>::getScalarIndex(
00130       int xIdx,
00131       int yIdx,
00132       int zIdx
00133     ) const
00134     {
00135       return
00136         xIdx*m_dimensions.Z()*m_dimensions.Y()
00137         +
00138         yIdx*m_dimensions.Z()
00139         +
00140         zIdx;
00141     }
00142 
00143     template <class TmplParticle>
00144     int NeighbourTable<TmplParticle>::getScalarIndex(const Vec3L &index) const
00145     {
00146       return getScalarIndex(index.X(), index.Y(), index.Z());
00147     }
00148 
00149     template <class TmplParticle>
00150     int
00151     NeighbourTable<TmplParticle>::getScalarIndex(const Vec3 &pt) const
00152     {
00153       return getScalarIndex(getVecIndex(pt));
00154     }
00155 
00156     template <class TmplParticle>
00157     const Vec3L &
00158     NeighbourTable<TmplParticle>::getMinVecIndex() const
00159     {
00160       return m_minIndex;
00161     }
00162 
00163     template <class TmplParticle>
00164     const Vec3L &
00165     NeighbourTable<TmplParticle>::getMaxVecIndex() const
00166     {
00167       return m_maxIndex;
00168     }
00169 
00170     template <class TmplParticle>
00171     Vec3L
00172     NeighbourTable<TmplParticle>::getVecIndex(const Vec3 &pt) const
00173     {
00174       const Vec3 relPos = Vec3((pt - getMinPt())/m_gridSpacing);
00175       const Vec3L index = Vec3L(int(floor(relPos.X())), int(floor(relPos.Y())), int(floor(relPos.Z())));
00176       return getMinVecIndex().max(getMaxVecIndex().min(index));
00177     }
00178 
00179     template <class TmplParticle>
00180     typename NeighbourTable<TmplParticle>::ParticleVector
00181     NeighbourTable<TmplParticle>::getNeighbourVector(
00182       const Vec3 &pt,
00183       double radius
00184     ) const
00185     {
00186       ParticleVector neighbours;
00187       neighbours.reserve(128);
00188       const Vec3L min = getVecIndex(pt - radius);
00189       const Vec3L max = getVecIndex(pt + radius);
00190       for (int i = min.X(); i <= max.X(); i++) {
00191         for (int j = min.Y(); j <= max.Y(); j++) {
00192           for (int k = min.Z(); k <= max.Z(); k++) {
00193             neighbours.insert(
00194               neighbours.end(),
00195               m_tablePtr[getScalarIndex(i, j, k)].begin(),
00196               m_tablePtr[getScalarIndex(i, j, k)].end()
00197             );
00198           }
00199         }
00200       }
00201       return neighbours;
00202     }
00203 
00204     template <class TmplParticle>
00205     typename NeighbourTable<TmplParticle>::ParticleVector
00206     NeighbourTable<TmplParticle>::getUniqueNeighbourVector(
00207       const Vec3 &pt,
00208       double radius
00209     ) const
00210     {
00211       ParticleVector neighbours = getNeighbourVector(pt, radius);
00212       std::sort(neighbours.begin(), neighbours.end());
00213       typename ParticleVector::iterator uniqueEnd =
00214         std::unique(neighbours.begin(), neighbours.end());
00215       neighbours.erase(
00216         uniqueEnd,
00217         neighbours.end()
00218       );
00219 
00220       return neighbours;
00221     }
00222 
00223     template <class TmplParticle>
00224     typename NeighbourTable<TmplParticle>::ParticleVector
00225     NeighbourTable<TmplParticle>::getNeighbourVector(
00226       const Vec3 &pt
00227     ) const
00228     {
00229       return m_tablePtr[getScalarIndex(pt)];
00230     }
00231 
00232     template <class TmplParticle>
00233     void NeighbourTable<TmplParticle>::insert(Particle *pParticle)
00234     {
00235       const Vec3L minIdx = getVecIndex(pParticle->getPos() - pParticle->getRad());
00236       const Vec3L maxIdx = getVecIndex(pParticle->getPos() + pParticle->getRad());
00237       insertInTable(pParticle, minIdx, maxIdx);
00238       addInserted(pParticle);
00239     }
00240 
00241     template <class TmplParticle>
00242     void NeighbourTable<TmplParticle>::insert(Particle &particle)
00243     {
00244       insert(&particle);
00245     }
00246 
00247     template <class TmplParticle>
00248     typename NeighbourTable<TmplParticle>::ParticleIterator
00249     NeighbourTable<TmplParticle>::getParticleIterator()
00250     {
00251       return ParticleIterator(m_insertedParticles);
00252     }
00253 
00254     template <class TmplParticle>
00255     typename NeighbourTable<TmplParticle>::ParticleConstIterator
00256     NeighbourTable<TmplParticle>::getParticleIterator() const
00257     {
00258       return ParticleConstIterator(m_insertedParticles);
00259     }
00260 
00261     template <class TmplParticle>
00262     void NeighbourTable<TmplParticle>::insertInTable(
00263       Particle *pParticle,
00264       const Vec3L &minIdx,
00265       const Vec3L &maxIdx
00266     )
00267     {
00268       for (int i = minIdx.X(); i <= maxIdx.X(); i++) {
00269         for (int j = minIdx.Y(); j <= maxIdx.Y(); j++) {
00270           for (int k = minIdx.Z(); k <= maxIdx.Z(); k++) {
00271             m_tablePtr[getScalarIndex(i, j, k)].push_back(pParticle);
00272           }
00273         }
00274       }
00275     }
00276 
00277     template <class TmplParticle>
00278     void NeighbourTable<TmplParticle>::addInserted(Particle *pParticle)
00279     {
00280       m_insertedParticles.push_back(pParticle);
00281     }
00282 
00283     template <class TmplParticle>
00284     int NeighbourTable<TmplParticle>::getNumCells() const
00285     {
00286       return getDimensions()[0]*getDimensions()[1]*getDimensions()[2];
00287     }
00288 
00289     template <class TmplParticle>
00290     typename NeighbourTable<TmplParticle>::ParticleVector
00291     NeighbourTable<TmplParticle>::getInsertedParticles() const
00292     {
00293       return m_insertedParticles;
00294     }
00295 
00296     template <class TmplParticle>
00297     void NeighbourTable<TmplParticle>::clearAndRecomputeGrid(
00298       const BoundingBox &bBox,
00299       double gridSpacing
00300     )
00301     {
00302       clear();
00303       m_bBox = bBox;
00304       m_gridSpacing = gridSpacing;
00305 
00306       const Vec3 dims  = m_bBox.getSizes()/gridSpacing;
00307       m_dimensions =
00308         Vec3L(
00309           int(floor(dims[0])),
00310           int(floor(dims[1])),
00311           int(floor(dims[2]))
00312         );
00313       m_dimensions = m_dimensions.max(Vec3L(1, 1, 1));
00314 
00315       m_tablePtr =
00316         ParticleVectorArrayPtr(
00317           new ParticleVector[
00318             m_dimensions.X()*m_dimensions.Y()*m_dimensions.Z()
00319           ]
00320         );
00321       m_minIndex = Vec3L(0, 0, 0);
00322       m_maxIndex = (m_dimensions - 1);
00323     }
00324   }
00325 }
00326 
00327 #endif