Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / selection / nbsearch.cpp
index 24a66ddbda7538ff88f2e9f9e03c72ed9356bc5f..7e32fa6536b1ad066a2d7cdb1bb9df420a9fc742 100644 (file)
@@ -40,9 +40,6 @@
  * The grid implementation could still be optimized in several different ways:
  *   - Triclinic grid cells are not the most efficient shape, but make PBC
  *     handling easier.
- *   - Precalculating the required PBC shift for a pair of cells outside the
- *     inner loop. After this is done, it should be quite straightforward to
- *     move to rectangular cells.
  *   - Pruning grid cells from the search list if they are completely outside
  *     the sphere that is being considered.
  *   - A better heuristic could be added for falling back to simple loops for a
  * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \ingroup module_selection
  */
-#include "gromacs/selection/nbsearch.h"
+#include "gmxpre.h"
 
-#include <math.h>
+#include "nbsearch.h"
+
+#include <cmath>
+#include <cstring>
 
 #include <algorithm>
 #include <vector>
 
 #include "thread_mpi/mutex.h"
 
-#include "gromacs/legacyheaders/typedefs.h"
-#include "gromacs/legacyheaders/pbc.h"
-#include "gromacs/legacyheaders/vec.h"
-
+#include "gromacs/legacyheaders/names.h"
+#include "gromacs/math/vec.h"
+#include "gromacs/pbcutil/pbc.h"
 #include "gromacs/selection/position.h"
+#include "gromacs/topology/block.h"
 #include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
 
 namespace gmx
 {
@@ -98,10 +100,14 @@ class AnalysisNeighborhoodSearchImpl
          * Initializes the search with a given box and reference positions.
          *
          * \param[in]     mode      Search mode to use.
+         * \param[in]     bXY       Whether to use 2D searching.
+         * \param[in]     excls     Exclusions.
          * \param[in]     pbc       PBC information.
          * \param[in]     positions Set of reference positions.
          */
         void init(AnalysisNeighborhood::SearchMode     mode,
+                  bool                                 bXY,
+                  const t_blocka                      *excls,
                   const t_pbc                         *pbc,
                   const AnalysisNeighborhoodPositions &positions);
         PairSearchImplPointer getPairSearch();
@@ -118,23 +124,23 @@ class AnalysisNeighborhoodSearchImpl
          * \param[in]     pbc  Information about the box.
          * \returns  false if grid search is not suitable.
          */
-        bool initGridCells(const t_pbc *pbc);
+        bool initGridCells(const t_pbc &pbc);
         /*! \brief
          * Sets ua a search grid for a given box.
          *
          * \param[in]     pbc  Information about the box.
          * \returns  false if grid search is not suitable.
          */
-        bool initGrid(const t_pbc *pbc);
+        bool initGrid(const t_pbc &pbc);
         /*! \brief
          * Maps a point into a grid cell.
          *
          * \param[in]  x    Point to map.
          * \param[out] cell Indices of the grid cell in which \p x lies.
-         *
-         * \p x should be within the triclinic unit cell.
+         * \param[out] xout Coordinates to use
+         *     (will be within the triclinic unit cell).
          */
-        void mapPointToGridCell(const rvec x, ivec cell) const;
+        void mapPointToGridCell(const rvec x, ivec cell, rvec xout) const;
         /*! \brief
          * Calculates linear index of a grid cell.
          *
@@ -149,6 +155,16 @@ class AnalysisNeighborhoodSearchImpl
          * \param[in]     i    Index to add.
          */
         void addToGridCell(const ivec cell, int i);
+        /*! \brief
+         * Calculates the index of a neighboring grid cell.
+         *
+         * \param[in]  sourceCell Location of the source cell.
+         * \param[in]  index      Index of the neighbor to calculate.
+         * \param[out] shift      Shift to apply to get the periodic distance
+         *     for distances between the cells.
+         * \returns    Grid cell index of the neighboring cell.
+         */
+        int getNeighboringCell(const ivec sourceCell, int index, rvec shift) const;
 
         //! Whether to try grid searching.
         bool                    bTryGrid_;
@@ -156,20 +172,19 @@ class AnalysisNeighborhoodSearchImpl
         real                    cutoff_;
         //! The cutoff squared.
         real                    cutoff2_;
+        //! Whether to do searching in XY plane only.
+        bool                    bXY_;
 
         //! Number of reference points for the current frame.
         int                     nref_;
         //! Reference point positions.
         const rvec             *xref_;
-        //! Reference position ids (NULL if not available).
-        const int              *refid_;
+        //! Reference position exclusion IDs.
+        const int              *refExclusionIds_;
+        //! Exclusions.
+        const t_blocka         *excls_;
         //! PBC data.
-        t_pbc                  *pbc_;
-
-        //! Number of excluded reference positions for current test particle.
-        int                     nexcl_;
-        //! Exclusions for current test particle.
-        int                    *excl_;
+        t_pbc                   pbc_;
 
         //! Whether grid searching is actually used for the current positions.
         bool                    bGrid_;
@@ -208,6 +223,9 @@ class AnalysisNeighborhoodPairSearchImpl
         explicit AnalysisNeighborhoodPairSearchImpl(const AnalysisNeighborhoodSearchImpl &search)
             : search_(search)
         {
+            testExclusionIds_ = NULL;
+            nexcl_            = 0;
+            excl_             = NULL;
             clear_rvec(xtest_);
             clear_ivec(testcell_);
             reset(-1);
@@ -233,12 +251,20 @@ class AnalysisNeighborhoodPairSearchImpl
         const AnalysisNeighborhoodSearchImpl   &search_;
         //! Reference to the test positions.
         ConstArrayRef<rvec>                     testPositions_;
+        //! Reference to the test exclusion indices.
+        const int                              *testExclusionIds_;
+        //! Number of excluded reference positions for current test particle.
+        int                                     nexcl_;
+        //! Exclusions for current test particle.
+        const int                              *excl_;
         //! Index of the currently active test position in \p testPositions_.
         int                                     testIndex_;
         //! Stores test position during a pair loop.
         rvec                                    xtest_;
         //! Stores the previous returned position during a pair loop.
         int                                     previ_;
+        //! Stores the pair distance corresponding to previ_;
+        real                                    prevr2_;
         //! Stores the current exclusion index during loops.
         int                                     exclind_;
         //! Stores the test particle cell index during loops.
@@ -265,14 +291,12 @@ AnalysisNeighborhoodSearchImpl::AnalysisNeighborhoodSearchImpl(real cutoff)
         bTryGrid_   = false;
     }
     cutoff2_        = sqr(cutoff_);
+    bXY_            = false;
 
-    nref_           = 0;
-    xref_           = NULL;
-    refid_          = NULL;
-    pbc_            = NULL;
-
-    nexcl_          = 0;
-    excl_           = NULL;
+    nref_            = 0;
+    xref_            = NULL;
+    refExclusionIds_ = NULL;
+    std::memset(&pbc_, 0, sizeof(pbc_));
 
     bGrid_          = false;
 
@@ -358,16 +382,16 @@ void AnalysisNeighborhoodSearchImpl::initGridCellNeighborList()
     }
 }
 
-bool AnalysisNeighborhoodSearchImpl::initGridCells(const t_pbc *pbc)
+bool AnalysisNeighborhoodSearchImpl::initGridCells(const t_pbc &pbc)
 {
     const real targetsize =
-        pow(pbc->box[XX][XX] * pbc->box[YY][YY] * pbc->box[ZZ][ZZ]
+        pow(pbc.box[XX][XX] * pbc.box[YY][YY] * pbc.box[ZZ][ZZ]
             * 10 / nref_, static_cast<real>(1./3.));
 
     int cellCount = 1;
     for (int dd = 0; dd < DIM; ++dd)
     {
-        ncelldim_[dd] = static_cast<int>(pbc->box[dd][dd] / targetsize);
+        ncelldim_[dd] = static_cast<int>(pbc.box[dd][dd] / targetsize);
         cellCount    *= ncelldim_[dd];
         if (ncelldim_[dd] < 3)
         {
@@ -388,10 +412,10 @@ bool AnalysisNeighborhoodSearchImpl::initGridCells(const t_pbc *pbc)
     return true;
 }
 
-bool AnalysisNeighborhoodSearchImpl::initGrid(const t_pbc *pbc)
+bool AnalysisNeighborhoodSearchImpl::initGrid(const t_pbc &pbc)
 {
     /* TODO: This check could be improved. */
-    if (0.5*pbc->max_cutoff2 < cutoff2_)
+    if (0.5*pbc.max_cutoff2 < cutoff2_)
     {
         return false;
     }
@@ -401,12 +425,12 @@ bool AnalysisNeighborhoodSearchImpl::initGrid(const t_pbc *pbc)
         return false;
     }
 
-    bTric_ = TRICLINIC(pbc->box);
+    bTric_ = TRICLINIC(pbc.box);
     if (bTric_)
     {
         for (int dd = 0; dd < DIM; ++dd)
         {
-            svmul(1.0 / ncelldim_[dd], pbc->box[dd], cellbox_[dd]);
+            svmul(1.0 / ncelldim_[dd], pbc.box[dd], cellbox_[dd]);
         }
         m_inv_ur0(cellbox_, recipcell_);
     }
@@ -414,7 +438,7 @@ bool AnalysisNeighborhoodSearchImpl::initGrid(const t_pbc *pbc)
     {
         for (int dd = 0; dd < DIM; ++dd)
         {
-            cellbox_[dd][dd]   = pbc->box[dd][dd] / ncelldim_[dd];
+            cellbox_[dd][dd]   = pbc.box[dd][dd] / ncelldim_[dd];
             recipcell_[dd][dd] = 1.0 / cellbox_[dd][dd];
         }
     }
@@ -423,25 +447,52 @@ bool AnalysisNeighborhoodSearchImpl::initGrid(const t_pbc *pbc)
 }
 
 void AnalysisNeighborhoodSearchImpl::mapPointToGridCell(const rvec x,
-                                                        ivec       cell) const
+                                                        ivec       cell,
+                                                        rvec       xout) const
 {
+    rvec xtmp;
+    copy_rvec(x, xtmp);
     if (bTric_)
     {
         rvec tx;
-
-        tmvmul_ur0(recipcell_, x, tx);
+        tmvmul_ur0(recipcell_, xtmp, tx);
         for (int dd = 0; dd < DIM; ++dd)
         {
-            cell[dd] = static_cast<int>(tx[dd]);
+            const int cellCount = ncelldim_[dd];
+            int       cellIndex = static_cast<int>(floor(tx[dd]));
+            while (cellIndex < 0)
+            {
+                cellIndex += cellCount;
+                rvec_add(xtmp, pbc_.box[dd], xtmp);
+            }
+            while (cellIndex >= cellCount)
+            {
+                cellIndex -= cellCount;
+                rvec_sub(xtmp, pbc_.box[dd], xtmp);
+            }
+            cell[dd] = cellIndex;
         }
     }
     else
     {
         for (int dd = 0; dd < DIM; ++dd)
         {
-            cell[dd] = static_cast<int>(x[dd] * recipcell_[dd][dd]);
+            const int cellCount = ncelldim_[dd];
+            int       cellIndex = static_cast<int>(floor(xtmp[dd] * recipcell_[dd][dd]));
+            while (cellIndex < 0)
+            {
+                cellIndex += cellCount;
+                xtmp[dd]  += pbc_.box[dd][dd];
+            }
+            while (cellIndex >= cellCount)
+            {
+                cellIndex -= cellCount;
+                xtmp[dd]  -= pbc_.box[dd][dd];
+            }
+            cell[dd] = cellIndex;
         }
     }
+    copy_rvec(xtmp, xout);
 }
 
 int AnalysisNeighborhoodSearchImpl::getGridCellIndex(const ivec cell) const
@@ -462,19 +513,72 @@ void AnalysisNeighborhoodSearchImpl::addToGridCell(const ivec cell, int i)
     cells_[ci].push_back(i);
 }
 
+int AnalysisNeighborhoodSearchImpl::getNeighboringCell(
+        const ivec sourceCell, int index, rvec shift) const
+{
+    ivec cell;
+    ivec_add(sourceCell, gnboffs_[index], cell);
+
+    // TODO: Consider unifying with the similar shifting code in
+    // mapPointToGridCell().
+    clear_rvec(shift);
+    for (int d = 0; d < DIM; ++d)
+    {
+        const int cellCount = ncelldim_[d];
+        if (cell[d] < 0)
+        {
+            cell[d] += cellCount;
+            rvec_add(shift, pbc_.box[d], shift);
+        }
+        else if (cell[d] >= cellCount)
+        {
+            cell[d] -= cellCount;
+            rvec_sub(shift, pbc_.box[d], shift);
+        }
+    }
+
+    return getGridCellIndex(cell);
+}
+
 void AnalysisNeighborhoodSearchImpl::init(
         AnalysisNeighborhood::SearchMode     mode,
+        bool                                 bXY,
+        const t_blocka                      *excls,
         const t_pbc                         *pbc,
         const AnalysisNeighborhoodPositions &positions)
 {
     GMX_RELEASE_ASSERT(positions.index_ == -1,
                        "Individual indexed positions not supported as reference");
-    pbc_  = const_cast<t_pbc *>(pbc);
+    bXY_ = bXY;
+    if (bXY_ && pbc->ePBC != epbcNONE)
+    {
+        if (pbc->ePBC != epbcXY && pbc->ePBC != epbcXYZ)
+        {
+            std::string message =
+                formatString("Computations in the XY plane are not supported with PBC type '%s'",
+                             EPBC(pbc->ePBC));
+            GMX_THROW(NotImplementedError(message));
+        }
+        if (std::fabs(pbc->box[ZZ][XX]) > GMX_REAL_EPS*pbc->box[ZZ][ZZ] ||
+            std::fabs(pbc->box[ZZ][YY]) > GMX_REAL_EPS*pbc->box[ZZ][ZZ])
+        {
+            GMX_THROW(NotImplementedError("Computations in the XY plane are not supported when the last box vector is not parallel to the Z axis"));
+        }
+        set_pbc(&pbc_, epbcXY, const_cast<rvec *>(pbc->box));
+    }
+    else if (pbc != NULL)
+    {
+        pbc_  = *pbc;
+    }
+    else
+    {
+        pbc_.ePBC = epbcNONE;
+    }
     nref_ = positions.count_;
     // TODO: Consider whether it would be possible to support grid searching in
     // more cases.
     if (mode == AnalysisNeighborhood::eSearchMode_Simple
-        || pbc_ == NULL || pbc_->ePBC != epbcXYZ)
+        || pbc_.ePBC != epbcXYZ)
     {
         bGrid_ = false;
     }
@@ -492,17 +596,10 @@ void AnalysisNeighborhoodSearchImpl::init(
         }
         xref_ = xref_alloc_;
 
-        for (int i = 0; i < nref_; ++i)
-        {
-            copy_rvec(positions.x_[i], xref_alloc_[i]);
-        }
-        put_atoms_in_triclinic_unitcell(ecenterTRIC, pbc_->box,
-                                        nref_, xref_alloc_);
         for (int i = 0; i < nref_; ++i)
         {
             ivec refcell;
-
-            mapPointToGridCell(xref_[i], refcell);
+            mapPointToGridCell(positions.x_[i], refcell, xref_alloc_[i]);
             addToGridCell(refcell, i);
         }
     }
@@ -510,29 +607,17 @@ void AnalysisNeighborhoodSearchImpl::init(
     {
         xref_ = positions.x_;
     }
-    // TODO: Once exclusions are supported, this may need to be initialized.
-    refid_ = NULL;
-}
-
-#if 0
-/*! \brief
- * Sets the exclusions for the next neighborhood search.
- *
- * \param[in,out] d     Neighborhood search data structure.
- * \param[in]     nexcl Number of reference positions to exclude from next
- *      search.
- * \param[in]     excl  Indices of reference positions to exclude.
- *
- * The set exclusions remain in effect until the next call of this function.
- */
-void
-gmx_ana_nbsearch_set_excl(gmx_ana_nbsearch_t *d, int nexcl, int excl[])
-{
-
-    d->nexcl = nexcl;
-    d->excl  = excl;
+    excls_           = excls;
+    refExclusionIds_ = NULL;
+    if (excls != NULL)
+    {
+        // TODO: Check that the IDs are ascending, or remove the limitation.
+        refExclusionIds_ = positions.exclusionIds_;
+        GMX_RELEASE_ASSERT(refExclusionIds_ != NULL,
+                           "Exclusion IDs must be set for reference positions "
+                           "when exclusions are enabled");
+    }
 }
-#endif
 
 /********************************************************************
  * AnalysisNeighborhoodPairSearchImpl
@@ -546,12 +631,30 @@ void AnalysisNeighborhoodPairSearchImpl::reset(int testIndex)
         copy_rvec(testPositions_[testIndex_], xtest_);
         if (search_.bGrid_)
         {
-            put_atoms_in_triclinic_unitcell(ecenterTRIC, search_.pbc_->box,
-                                            1, &xtest_);
-            search_.mapPointToGridCell(xtest_, testcell_);
+            search_.mapPointToGridCell(testPositions_[testIndex], testcell_, xtest_);
+        }
+        else
+        {
+            copy_rvec(testPositions_[testIndex_], xtest_);
+        }
+        if (search_.excls_ != NULL)
+        {
+            const int exclIndex  = testExclusionIds_[testIndex];
+            if (exclIndex < search_.excls_->nr)
+            {
+                const int startIndex = search_.excls_->index[exclIndex];
+                nexcl_ = search_.excls_->index[exclIndex + 1] - startIndex;
+                excl_  = &search_.excls_->a[startIndex];
+            }
+            else
+            {
+                nexcl_ = 0;
+                excl_  = NULL;
+            }
         }
     }
     previ_     = -1;
+    prevr2_    = 0.0;
     exclind_   = 0;
     prevnbi_   = 0;
     prevcai_   = -1;
@@ -568,34 +671,17 @@ void AnalysisNeighborhoodPairSearchImpl::nextTestPosition()
 
 bool AnalysisNeighborhoodPairSearchImpl::isExcluded(int j)
 {
-    if (exclind_ < search_.nexcl_)
+    if (exclind_ < nexcl_)
     {
-        if (search_.refid_)
+        const int refId = search_.refExclusionIds_[j];
+        while (exclind_ < nexcl_ && excl_[exclind_] < refId)
         {
-            while (exclind_ < search_.nexcl_
-                   && search_.excl_[exclind_] < search_.refid_[j])
-            {
-                ++exclind_;
-            }
-            if (exclind_ < search_.nexcl_
-                && search_.refid_[j] == search_.excl_[exclind_])
-            {
-                ++exclind_;
-                return true;
-            }
+            ++exclind_;
         }
-        else
+        if (exclind_ < nexcl_ && refId == excl_[exclind_])
         {
-            while (search_.bGrid_ && exclind_ < search_.nexcl_
-                   && search_.excl_[exclind_] < j)
-            {
-                ++exclind_;
-            }
-            if (search_.excl_[exclind_] == j)
-            {
-                ++exclind_;
-                return true;
-            }
+            ++exclind_;
+            return true;
         }
     }
     return false;
@@ -604,6 +690,9 @@ bool AnalysisNeighborhoodPairSearchImpl::isExcluded(int j)
 void AnalysisNeighborhoodPairSearchImpl::startSearch(
         const AnalysisNeighborhoodPositions &positions)
 {
+    testExclusionIds_ = positions.exclusionIds_;
+    GMX_RELEASE_ASSERT(search_.excls_ == NULL || testExclusionIds_ != NULL,
+                       "Exclusion IDs must be set when exclusions are enabled");
     if (positions.index_ < 0)
     {
         testPositions_ = constArrayRefFromArray<rvec>(positions.x_, positions.count_);
@@ -625,21 +714,16 @@ bool AnalysisNeighborhoodPairSearchImpl::searchNext(Action action)
     {
         if (search_.bGrid_)
         {
+            GMX_RELEASE_ASSERT(!search_.bXY_, "Grid-based XY searches not implemented");
+
             int nbi = prevnbi_;
             int cai = prevcai_ + 1;
 
             for (; nbi < search_.ngridnb_; ++nbi)
             {
-                ivec cell;
-
-                ivec_add(testcell_, search_.gnboffs_[nbi], cell);
-                cell[XX] = (cell[XX] + search_.ncelldim_[XX]) % search_.ncelldim_[XX];
-                cell[YY] = (cell[YY] + search_.ncelldim_[YY]) % search_.ncelldim_[YY];
-                cell[ZZ] = (cell[ZZ] + search_.ncelldim_[ZZ]) % search_.ncelldim_[ZZ];
-
-                const int ci       = search_.getGridCellIndex(cell);
+                rvec      shift;
+                const int ci       = search_.getNeighboringCell(testcell_, nbi, shift);
                 const int cellSize = static_cast<int>(search_.cells_[ci].size());
-                /* TODO: Calculate the required PBC shift outside the inner loop */
                 for (; cai < cellSize; ++cai)
                 {
                     const int i = search_.cells_[ci][cai];
@@ -648,7 +732,8 @@ bool AnalysisNeighborhoodPairSearchImpl::searchNext(Action action)
                         continue;
                     }
                     rvec       dx;
-                    pbc_dx_aiuc(search_.pbc_, xtest_, search_.xref_[i], dx);
+                    rvec_sub(xtest_, search_.xref_[i], dx);
+                    rvec_add(dx, shift, dx);
                     const real r2 = norm2(dx);
                     if (r2 <= search_.cutoff2_)
                     {
@@ -657,6 +742,7 @@ bool AnalysisNeighborhoodPairSearchImpl::searchNext(Action action)
                             prevnbi_ = nbi;
                             prevcai_ = cai;
                             previ_   = i;
+                            prevr2_  = r2;
                             return true;
                         }
                     }
@@ -674,20 +760,24 @@ bool AnalysisNeighborhoodPairSearchImpl::searchNext(Action action)
                     continue;
                 }
                 rvec dx;
-                if (search_.pbc_)
+                if (search_.pbc_.ePBC != epbcNONE)
                 {
-                    pbc_dx(search_.pbc_, xtest_, search_.xref_[i], dx);
+                    pbc_dx(&search_.pbc_, xtest_, search_.xref_[i], dx);
                 }
                 else
                 {
                     rvec_sub(xtest_, search_.xref_[i], dx);
                 }
-                const real r2 = norm2(dx);
+                const real r2
+                    = search_.bXY_
+                        ? dx[XX]*dx[XX] + dx[YY]*dx[YY]
+                        : norm2(dx);
                 if (r2 <= search_.cutoff2_)
                 {
                     if (action(i, r2))
                     {
-                        previ_ = i;
+                        previ_  = i;
+                        prevr2_ = r2;
                         return true;
                     }
                 }
@@ -707,7 +797,7 @@ void AnalysisNeighborhoodPairSearchImpl::initFoundPair(
     }
     else
     {
-        *pair = AnalysisNeighborhoodPair(previ_, testIndex_);
+        *pair = AnalysisNeighborhoodPair(previ_, testIndex_, prevr2_);
     }
 }
 
@@ -788,7 +878,7 @@ class AnalysisNeighborhood::Impl
         typedef AnalysisNeighborhoodSearch::ImplPointer SearchImplPointer;
         typedef std::vector<SearchImplPointer> SearchList;
 
-        Impl() : cutoff_(0), mode_(eSearchMode_Automatic)
+        Impl() : cutoff_(0), excls_(NULL), mode_(eSearchMode_Automatic), bXY_(false)
         {
         }
         ~Impl()
@@ -806,7 +896,9 @@ class AnalysisNeighborhood::Impl
         tMPI::mutex             createSearchMutex_;
         SearchList              searchList_;
         real                    cutoff_;
+        const t_blocka         *excls_;
         SearchMode              mode_;
+        bool                    bXY_;
 };
 
 AnalysisNeighborhood::Impl::SearchImplPointer
@@ -848,6 +940,18 @@ void AnalysisNeighborhood::setCutoff(real cutoff)
     impl_->cutoff_ = cutoff;
 }
 
+void AnalysisNeighborhood::setXYMode(bool bXY)
+{
+    impl_->bXY_ = bXY;
+}
+
+void AnalysisNeighborhood::setTopologyExclusions(const t_blocka *excls)
+{
+    GMX_RELEASE_ASSERT(impl_->searchList_.empty(),
+                       "Changing the exclusions after initSearch() not currently supported");
+    impl_->excls_ = excls;
+}
+
 void AnalysisNeighborhood::setMode(SearchMode mode)
 {
     impl_->mode_ = mode;
@@ -863,7 +967,7 @@ AnalysisNeighborhood::initSearch(const t_pbc                         *pbc,
                                  const AnalysisNeighborhoodPositions &positions)
 {
     Impl::SearchImplPointer search(impl_->getSearch());
-    search->init(mode(), pbc, positions);
+    search->init(mode(), impl_->bXY_, impl_->excls_, pbc, positions);
     return AnalysisNeighborhoodSearch(search);
 }
 
@@ -926,7 +1030,7 @@ AnalysisNeighborhoodSearch::nearestPoint(
     int           closestPoint = -1;
     MindistAction action(&closestPoint, &minDist2);
     (void)pairSearch.searchNext(action);
-    return AnalysisNeighborhoodPair(closestPoint, 0);
+    return AnalysisNeighborhoodPair(closestPoint, 0, minDist2);
 }
 
 AnalysisNeighborhoodPairSearch