Remove C API for analysis neighborhoor search.
[alexxy/gromacs.git] / src / gromacs / selection / nbsearch.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2009,2010,2011,2012,2013, by the GROMACS development team, led by
5  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6  * others, as listed in the AUTHORS file in the top-level source
7  * directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \file
36  * \brief API for neighborhood searching for analysis.
37  *
38  * The main part of the API is the class gmx::AnalysisNeighborhood.
39  * See the class documentation for usage.
40  *
41  * The classes within this file can be used independently of the other parts
42  * of the library.
43  * The library also uses the classes internally.
44  *
45  * \author Teemu Murtola <teemu.murtola@gmail.com>
46  * \inpublicapi
47  * \ingroup module_selection
48  */
49 #ifndef GMX_SELECTION_NBSEARCH_H
50 #define GMX_SELECTION_NBSEARCH_H
51
52 #include <boost/shared_ptr.hpp>
53
54 #include "../legacyheaders/typedefs.h"
55 #include "../utility/common.h"
56 #include "../utility/gmxassert.h"
57
58 #include "indexutil.h"
59
60 struct gmx_ana_pos_t;
61
62 namespace gmx
63 {
64
65 namespace internal
66 {
67 class AnalysisNeighborhoodSearchImpl;
68 class AnalysisNeighborhoodPairSearchImpl;
69 };
70
71 class AnalysisNeighborhoodSearch;
72 class AnalysisNeighborhoodPairSearch;
73
74 /*! \brief
75  * Neighborhood searching for analysis tools.
76  *
77  * This class implements neighborhood searching routines for analysis tools.
78  * The emphasis is in flexibility and ease of use; one main driver is to have
79  * a common implementation of grid-based searching to avoid replicating this in
80  * multiple tools (and to make more tools take advantage of the significant
81  * performance improvement this allows).
82  *
83  * To use the search, create an object of this type, call setCutoff() to
84  * initialize it, and then repeatedly call initSearch() to start a search with
85  * different sets of reference positions.  For each set of reference positions,
86  * use methods in the returned AnalysisNeighborhoodSearch to find the reference
87  * positions that are within the given cutoff from a provided position.
88  *
89  * initSearch() is thread-safe and can be called from multiple threads.  Each
90  * call returns a different instance of the search object that can be used
91  * independently of the others.  However, the returned search objects can only
92  * be used within a single thread.  It is also possible to create multiple
93  * concurrent searches within a single thread.
94  *
95  * \todo
96  * Support for exclusions.
97  * The 4.5/4.6 C API had very low-level support for exclusions, which was not
98  * very convenient to use, and hadn't been tested much.  The internal code that
99  * it used to do the exclusion during the search itself is still there, but it
100  * needs more thought on what would be a convenient way to initialize it.
101  * Can be implemented once there is need for it in some calling code.
102  *
103  * \inpublicapi
104  * \ingroup module_selection
105  */
106 class AnalysisNeighborhood
107 {
108     public:
109         //! Searching algorithm to use.
110         enum SearchMode
111         {
112             //! Select algorithm based on heuristic efficiency considerations.
113             eSearchMode_Automatic,
114             //! Use a simple loop over all pairs.
115             eSearchMode_Simple,
116             //! Use grid-based searching whenever possible.
117             eSearchMode_Grid
118         };
119
120         //! Creates an uninitialized neighborhood search.
121         AnalysisNeighborhood();
122         ~AnalysisNeighborhood();
123
124         /*! \brief
125          * Set cutoff distance for the neighborhood searching.
126          *
127          * \param[in]  cutoff Cutoff distance for the search
128          *   (<=0 stands for no cutoff).
129          *
130          * Currently, can only be called before the first call to initSearch().
131          * If this method is not called, no cutoff is used in the searches.
132          *
133          * Does not throw.
134          */
135         void setCutoff(real cutoff);
136         /*! \brief
137          * Sets the algorithm to use for searching.
138          *
139          * \param[in] mode  Search mode to use.
140          *
141          * Note that if \p mode is \ref eSearchMode_Grid, it is still only a
142          * suggestion: grid-based searching may not be possible with the
143          * provided input, in which case a simple search is still used.
144          * This is mainly useful for testing purposes to force a mode.
145          *
146          * Does not throw.
147          */
148         void setMode(SearchMode mode);
149         //! Returns the currently active search mode.
150         SearchMode mode() const;
151
152         /*! \brief
153          * Initializes neighborhood search for a set of positions.
154          *
155          * \param[in] pbc PBC information for the frame.
156          * \param[in] n   Number of reference positions for the frame.
157          * \param[in] x   \p n reference positions for the frame.
158          * \returns   Search object that can be used to find positions from
159          *      \p x within the given cutoff.
160          * \throws    std::bad_alloc if out of memory.
161          */
162         AnalysisNeighborhoodSearch
163         initSearch(const t_pbc *pbc, int n, const rvec x[]);
164         /*! \brief
165          * Initializes neighborhood search for a set of positions.
166          *
167          * \param[in] pbc PBC information for the frame.
168          * \param[in] p   Reference positions for the frame.
169          * \returns   Search object that can be used to find positions from
170          *      \p p within the given cutoff.
171          * \throws    std::bad_alloc if out of memory.
172          */
173         AnalysisNeighborhoodSearch
174         initSearch(const t_pbc *pbc, const gmx_ana_pos_t *p);
175
176     private:
177         class Impl;
178
179         PrivateImplPointer<Impl> impl_;
180 };
181
182 /*! \brief
183  * Value type to represent a pair of positions found in neighborhood searching.
184  *
185  * Methods in this class do not throw.
186  *
187  * \inpublicapi
188  * \ingroup module_selection
189  */
190 class AnalysisNeighborhoodPair
191 {
192     public:
193         //! Initializes an invalid pair.
194         AnalysisNeighborhoodPair() : refIndex_(-1), testIndex_(0) {}
195         //! Initializes a pair object with the given data.
196         AnalysisNeighborhoodPair(int refIndex, int testIndex)
197             : refIndex_(refIndex), testIndex_(testIndex)
198         {
199         }
200
201         /*! \brief
202          * Whether this pair is valid.
203          *
204          * If isValid() returns false, other methods should not be called.
205          */
206         bool isValid() const { return refIndex_ >= 0; }
207
208         /*! \brief
209          * Returns the index of the reference position in the pair.
210          *
211          * This index is always the index into the position array provided to
212          * AnalysisNeighborhood::initSearch().
213          */
214         int refIndex() const
215         {
216             GMX_ASSERT(isValid(), "Accessing invalid object");
217             return refIndex_;
218         }
219         /*! \brief
220          * Returns the index of the test position in the pair.
221          *
222          * The contents of this index depends on the context (method call) that
223          * produces the pair.
224          * If there was no array in the call, this index is zero.
225          */
226         int testIndex() const
227         {
228             GMX_ASSERT(isValid(), "Accessing invalid object");
229             return testIndex_;
230         }
231
232     private:
233         int                     refIndex_;
234         int                     testIndex_;
235 };
236
237 /*! \brief
238  * Initialized neighborhood search with a fixed set of reference positions.
239  *
240  * An instance of this class is obtained through
241  * AnalysisNeighborhood::initSearch(), and can be used to do multiple searches
242  * against the provided set of reference positions.
243  * Currently, it is not possible to call startPairSearch() while a previous
244  * AnalysisNeighborhoodPairSearch object obtained from startPairSearch() of the
245  * same instance still exists.
246  *
247  * This class works like a pointer: copies of it point to the same search.
248  * In general, avoid creating copies, and only use the copy/assignment support
249  * for moving the variable around.  With C++11, this class would best be
250  * movable.
251  *
252  * Methods in this class do not throw.
253  *
254  * \todo
255  * Make it such that reset() is not necessary to call in code that repeatedly
256  * assigns the result of AnalysisNeighborhood::initSearch() to the same
257  * variable (see sm_distance.cpp).
258  *
259  * \todo
260  * Consider merging nearestPoint() and minimumDistance() by adding the distance
261  * to AnalysisNeighborhoodPair.
262  *
263  * \inpublicapi
264  * \ingroup module_selection
265  */
266 class AnalysisNeighborhoodSearch
267 {
268     public:
269         /*! \brief
270          * Internal short-hand type for a pointer to the implementation class.
271          *
272          * shared_ptr is used here to automatically keep a reference count to
273          * track whether an implementation class is still used outside the
274          * AnalysisNeighborhood object.  Ownership currently always stays with
275          * AnalysisNeighborhood; it always keeps one instance of the pointer.
276          */
277         typedef boost::shared_ptr<internal::AnalysisNeighborhoodSearchImpl>
278             ImplPointer;
279
280         /*! \brief
281          * Initializes an invalid search.
282          *
283          * Such an object cannot be used for searching.  It needs to be
284          * assigned a value from AnalysisNeighborhood::initSearch() before it
285          * can be used.  Provided to allow declaring a variable to hold the
286          * search before calling AnalysisNeighborhood::initSearch().
287          */
288         AnalysisNeighborhoodSearch();
289         /*! \brief
290          * Internally initialize the search.
291          *
292          * Used to implement AnalysisNeighborhood::initSearch().
293          * Cannot be called from user code.
294          */
295         explicit AnalysisNeighborhoodSearch(const ImplPointer &impl);
296
297         /*! \brief
298          * Clears this search.
299          *
300          * Equivalent to \c "*this = AnalysisNeighborhoodSearch();".
301          * Currently, this is necessary to avoid unnecessary memory allocation
302          * if the previous search variable is still in scope when you want to
303          * call AnalysisNeighborhood::initSearch() again.
304          */
305         void reset();
306
307         /*! \brief
308          * Returns the searching algorithm that this search is using.
309          *
310          * The return value is never AnalysisNeighborhood::eSearchMode_Automatic.
311          */
312         AnalysisNeighborhood::SearchMode mode() const;
313
314         /*! \brief
315          * Check whether a point is within a neighborhood.
316          *
317          * \param[in] x  Test position.
318          * \returns   true if the test position is within the cutoff of any
319          *     reference position.
320          */
321         bool isWithin(const rvec x) const;
322         /*! \brief
323          * Check whether a point is within a neighborhood.
324          *
325          * \param[in] p  Test positions.
326          * \param[in] i  Use the i'th position in \p p for testing.
327          * \returns   true if the test position is within the cutoff of any
328          *     reference position.
329          */
330         bool isWithin(const gmx_ana_pos_t *p, int i) const;
331         /*! \brief
332          * Calculates the minimum distance from the reference points.
333          *
334          * \param[in] x  Test position.
335          * \returns   The distance to the nearest reference position, or the
336          *     cutoff value if there are no reference positions within the
337          *     cutoff.
338          */
339         real minimumDistance(const rvec x) const;
340         /*! \brief
341          * Calculates the minimum distance from the reference points.
342          *
343          * \param[in] p  Test positions.
344          * \param[in] i  Use the i'th position in \p p for testing.
345          * \returns   The distance to the nearest reference position, or the
346          *     cutoff value if there are no reference positions within the
347          *     cutoff.
348          */
349         real minimumDistance(const gmx_ana_pos_t *p, int i) const;
350         /*! \brief
351          * Finds the closest reference point.
352          *
353          * \param[in] x  Test position.
354          * \returns   The reference index identifies the reference position
355          *     that is closest to the test position.
356          *     The test index is always zero.  The returned pair is invalid if
357          *     no reference position is within the cutoff.
358          */
359         AnalysisNeighborhoodPair nearestPoint(const rvec x) const;
360         /*! \brief
361          * Finds the closest reference point.
362          *
363          * \param[in] p  Test positions.
364          * \param[in] i  Use the i'th position in \p p for testing.
365          * \returns   The reference index identifies the reference position
366          *     that is closest to the test position.
367          *     The test index is always \p i.  The returned pair is invalid if
368          *     no reference position is within the cutoff.
369          */
370         AnalysisNeighborhoodPair nearestPoint(const gmx_ana_pos_t *p, int i) const;
371
372         /*! \brief
373          * Start a search to find reference positions within a cutoff.
374          *
375          * \param[in] x  Test position to search the neighbors for.
376          * \returns   Initialized search object to loop through all reference
377          *     positions within the configured cutoff.
378          *
379          * In the AnalysisNeighborhoodPair objects returned by the search, the
380          * test index is always zero.
381          */
382         AnalysisNeighborhoodPairSearch startPairSearch(const rvec x);
383         /*! \brief
384          * Start a search to find reference positions within a cutoff.
385          *
386          * \param[in] p  Test positions.
387          * \param[in] i  Use the i'th position in \p p for testing.
388          * \returns   Initialized search object to loop through all reference
389          *     positions within the configured cutoff.
390          *
391          * In the AnalysisNeighborhoodPair objects returned by the search, the
392          * test index is always \p i.
393          */
394         AnalysisNeighborhoodPairSearch startPairSearch(const gmx_ana_pos_t *p, int i);
395
396     private:
397         ImplPointer             impl_;
398 };
399
400 /*! \brief
401  * Initialized neighborhood pair search with a fixed set of positions.
402  *
403  * This class is used to loop through pairs of neighbors within the cutoff
404  * provided to AnalysisNeighborhood.  The following code demonstrates its use:
405  * \code
406    gmx::AnalysisNeighborhood       nb;
407    nb.setCutoff(cutoff);
408    gmx::AnalysisNeighborhoodSearch search = nb.initSearch(pbc, nref, xref);
409    gmx::AnalysisNeighborhoodPairSearch pairSearch = search.startPairSearch(x);
410    gmx::AnalysisNeighborhoodPair pair;
411    while (pairSearch.findNextPair(&pair))
412    {
413        // <do something for each found pair the information in pair>
414    }
415  * \endcode
416  *
417  * It is not possible to use a single search object from multiple threads
418  * concurrently.
419  *
420  * This class works like a pointer: copies of it point to the same search.
421  * In general, avoid creating copies, and only use the copy/assignment support
422  * for moving the variable around.  With C++11, this class would best be
423  * movable.
424  *
425  * Methods in this class do not throw.
426  *
427  * \inpublicapi
428  * \ingroup module_selection
429  */
430 class AnalysisNeighborhoodPairSearch
431 {
432     public:
433         /*! \brief
434          * Internal short-hand type for a pointer to the implementation class.
435          *
436          * See AnalysisNeighborhoodSearch::ImplPointer for rationale of using
437          * shared_ptr and ownership semantics.
438          */
439         typedef boost::shared_ptr<internal::AnalysisNeighborhoodPairSearchImpl>
440             ImplPointer;
441
442         /*! \brief
443          * Internally initialize the search.
444          *
445          * Used to implement AnalysisNeighborhoodSearch::startPairSearch().
446          * Cannot be called from user code.
447          */
448         explicit AnalysisNeighborhoodPairSearch(const ImplPointer &impl);
449
450         /*! \brief
451          * Finds the next pair within the cutoff.
452          *
453          * \param[out] pair  Information about the found pair.
454          * \returns    false if there were no more pairs.
455          *
456          * If the method returns false, \p pair will be invalid.
457          *
458          * \see AnalysisNeighborhoodPair
459          * \see AnalysisNeighborhoodSearch::startPairSearch()
460          */
461         bool findNextPair(AnalysisNeighborhoodPair *pair);
462
463     private:
464         ImplPointer             impl_;
465 };
466
467 } // namespace gmx
468
469 #endif