Fixing copyright issues and code contributors
[alexxy/gromacs.git] / src / gmxlib / selection / sm_distance.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2009, The GROMACS development team,
6  * check out http://www.gromacs.org for more information.
7  * Copyright (c) 2012,2013, by the GROMACS development team, led by
8  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9  * others, as listed in the AUTHORS file in the top-level source
10  * directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 /*! \internal \file
39  * \brief Implementation of distance-based selection methods.
40  *
41  * This file implements the \p distance, \p mindistance and \p within
42  * selection methods.
43  */
44 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #endif
47
48 #include <macros.h>
49 #include <pbc.h>
50 #include <smalloc.h>
51 #include <vec.h>
52
53 #include <nbsearch.h>
54 #include <position.h>
55 #include <selmethod.h>
56
57 /*! \internal \brief
58  * Data structure for distance-based selection method.
59  *
60  * The same data structure is used by all the distance-based methods.
61  */
62 typedef struct
63 {
64     /** Cutoff distance. */
65     real                cutoff;
66     /** Positions of the reference points. */
67     gmx_ana_pos_t       p;
68     /** Neighborhood search data. */
69     gmx_ana_nbsearch_t *nb;
70 } t_methoddata_distance;
71
72 /** Allocates data for distance-based selection methods. */
73 static void *
74 init_data_common(int npar, gmx_ana_selparam_t *param);
75 /** Initializes a distance-based selection method. */
76 static int
77 init_common(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
78 /** Frees the data allocated for a distance-based selection method. */
79 static void
80 free_data_common(void *data);
81 /** Initializes the evaluation of a distance-based within selection method for a frame. */
82 static int
83 init_frame_common(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
84 /** Evaluates the \p distance selection method. */
85 static int
86 evaluate_distance(t_topology *top, t_trxframe *fr, t_pbc *pbc,
87                   gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
88 /** Evaluates the \p within selection method. */
89 static int
90 evaluate_within(t_topology *top, t_trxframe *fr, t_pbc *pbc,
91                 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
92
93 /** Parameters for the \p distance selection method. */
94 static gmx_ana_selparam_t smparams_distance[] = {
95     {"cutoff", {REAL_VALUE, 1, {NULL}}, NULL, SPAR_OPTIONAL},
96     {"from",   {POS_VALUE,  1, {NULL}}, NULL, SPAR_DYNAMIC},
97 };
98
99 /** Parameters for the \p mindistance selection method. */
100 static gmx_ana_selparam_t smparams_mindistance[] = {
101     {"cutoff", {REAL_VALUE, 1, {NULL}}, NULL, SPAR_OPTIONAL},
102     {"from",   {POS_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
103 };
104
105 /** Parameters for the \p within selection method. */
106 static gmx_ana_selparam_t smparams_within[] = {
107     {NULL, {REAL_VALUE,  1, {NULL}}, NULL, 0},
108     {"of", {POS_VALUE,  -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
109 };
110
111 /** Help text for the distance selection methods. */
112 static const char *help_distance[] = {
113     "DISTANCE-BASED SELECTION KEYWORDS[PAR]",
114
115     "[TT]distance from POS [cutoff REAL][tt][BR]",
116     "[TT]mindistance from POS_EXPR [cutoff REAL][tt][BR]",
117     "[TT]within REAL of POS_EXPR[tt][PAR]",
118
119     "[TT]distance[tt] and [TT]mindistance[tt] calculate the distance from the",
120     "given position(s), the only difference being in that [TT]distance[tt]",
121     "only accepts a single position, while any number of positions can be",
122     "given for [TT]mindistance[tt], which then calculates the distance to the",
123     "closest position.",
124     "[TT]within[tt] directly selects atoms that are within [TT]REAL[tt] of",
125     "[TT]POS_EXPR[tt].[PAR]",
126
127     "For the first two keywords, it is possible to specify a cutoff to speed",
128     "up the evaluation: all distances above the specified cutoff are",
129     "returned as equal to the cutoff.",
130     "Currently, this does nothing, but in the future, it allows the use of",
131     "grid-based neighborhood search techniques.",
132 };
133
134 /** \internal Selection method data for the \p distance method. */
135 gmx_ana_selmethod_t sm_distance = {
136     "distance", REAL_VALUE, SMETH_DYNAMIC,
137     asize(smparams_distance), smparams_distance,
138     &init_data_common,
139     NULL,
140     &init_common,
141     NULL,
142     &free_data_common,
143     &init_frame_common,
144     NULL,
145     &evaluate_distance,
146     {"distance from POS [cutoff REAL]", asize(help_distance), help_distance},
147 };
148
149 /** \internal Selection method data for the \p distance method. */
150 gmx_ana_selmethod_t sm_mindistance = {
151     "mindistance", REAL_VALUE, SMETH_DYNAMIC,
152     asize(smparams_mindistance), smparams_mindistance,
153     &init_data_common,
154     NULL,
155     &init_common,
156     NULL,
157     &free_data_common,
158     &init_frame_common,
159     NULL,
160     &evaluate_distance,
161     {"mindistance from POS_EXPR [cutoff REAL]", asize(help_distance), help_distance},
162 };
163
164 /** \internal Selection method data for the \p within method. */
165 gmx_ana_selmethod_t sm_within = {
166     "within", GROUP_VALUE, SMETH_DYNAMIC,
167     asize(smparams_within), smparams_within,
168     &init_data_common,
169     NULL,
170     &init_common,
171     NULL,
172     &free_data_common,
173     &init_frame_common,
174     NULL,
175     &evaluate_within,
176     {"within REAL of POS_EXPR", asize(help_distance), help_distance},
177 };
178
179 /*!
180  * \param[in]     npar  Not used (should be 2).
181  * \param[in,out] param Method parameters (should point to one of the distance
182  *   parameter arrays).
183  * \returns       Pointer to the allocated data (\c t_methoddata_distance).
184  *
185  * Allocates memory for a \c t_methoddata_distance structure and
186  * initializes the parameter as follows:
187  *  - the first parameter defines the value for
188  *    \c t_methoddata_distance::cutoff.
189  *  - the second parameter defines the reference positions and the value is
190  *    stored in \c t_methoddata_distance::p.
191  */
192 static void *
193 init_data_common(int npar, gmx_ana_selparam_t *param)
194 {
195     t_methoddata_distance *data;
196
197     snew(data, 1);
198     data->cutoff     = -1;
199     param[0].val.u.r = &data->cutoff;
200     param[1].val.u.p = &data->p;
201     return data;
202 }
203
204 /*!
205  * \param   top   Not used.
206  * \param   npar  Not used (should be 2).
207  * \param   param Method parameters (should point to one of the distance
208  *   parameter arrays).
209  * \param   data  Pointer to \c t_methoddata_distance to initialize.
210  * \returns 0 on success, a non-zero error code on failure.
211  *
212  * Initializes the neighborhood search data structure
213  * (\c t_methoddata_distance::nb).
214  * Also checks that the cutoff is valid.
215  */
216 static int
217 init_common(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
218 {
219     t_methoddata_distance *d = (t_methoddata_distance *)data;
220
221     if ((param[0].flags & SPAR_SET) && d->cutoff <= 0)
222     {
223         fprintf(stderr, "error: distance cutoff should be > 0");
224         return -1;
225     }
226     return gmx_ana_nbsearch_create(&d->nb, d->cutoff, d->p.nr);
227 }
228
229 /*!
230  * \param data Data to free (should point to a \c t_methoddata_distance).
231  *
232  * Frees the memory allocated for \c t_methoddata_distance::xref and
233  * \c t_methoddata_distance::nb.
234  */
235 static void
236 free_data_common(void *data)
237 {
238     t_methoddata_distance *d = (t_methoddata_distance *)data;
239
240     if (d->nb)
241     {
242         gmx_ana_nbsearch_free(d->nb);
243     }
244 }
245
246 /*!
247  * \param[in]  top  Not used.
248  * \param[in]  fr   Current frame.
249  * \param[in]  pbc  PBC structure.
250  * \param      data Should point to a \c t_methoddata_distance.
251  * \returns    0 on success, a non-zero error code on error.
252  *
253  * Initializes the neighborhood search for the current frame.
254  */
255 static int
256 init_frame_common(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
257 {
258     t_methoddata_distance *d = (t_methoddata_distance *)data;
259
260     return gmx_ana_nbsearch_pos_init(d->nb, pbc, &d->p);
261 }
262
263 /*!
264  * See sel_updatefunc_pos() for description of the parameters.
265  * \p data should point to a \c t_methoddata_distance.
266  *
267  * Calculates the distance of each position from \c t_methoddata_distance::p
268  * and puts them in \p out->u.r.
269  */
270 static int
271 evaluate_distance(t_topology *top, t_trxframe *fr, t_pbc *pbc,
272                   gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
273 {
274     t_methoddata_distance *d = (t_methoddata_distance *)data;
275     int  b, i;
276     real n;
277
278     out->nr = pos->g->isize;
279     for (b = 0; b < pos->nr; ++b)
280     {
281         n = gmx_ana_nbsearch_pos_mindist(d->nb, pos, b);
282         for (i = pos->m.mapb.index[b]; i < pos->m.mapb.index[b+1]; ++i)
283         {
284             out->u.r[i] = n;
285         }
286     }
287     return 0;
288 }
289
290 /*!
291  * See sel_updatefunc() for description of the parameters.
292  * \p data should point to a \c t_methoddata_distance.
293  *
294  * Finds the atoms that are closer than the defined cutoff to
295  * \c t_methoddata_distance::xref and puts them in \p out.g.
296  */
297 static int
298 evaluate_within(t_topology *top, t_trxframe *fr, t_pbc *pbc,
299                 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
300 {
301     t_methoddata_distance *d = (t_methoddata_distance *)data;
302     int                    b;
303
304     out->u.g->isize = 0;
305     for (b = 0; b < pos->nr; ++b)
306     {
307         if (gmx_ana_nbsearch_pos_is_within(d->nb, pos, b))
308         {
309             gmx_ana_pos_append(NULL, out->u.g, pos, b, 0);
310         }
311     }
312     return 0;
313 }