Merge release-4-6 into release-5-0
[alexxy/gromacs.git] / src / gromacs / selection / evaluate.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2009,2010,2011,2012,2013,2014, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source 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 /*! \internal \file
36  * \brief
37  * Implements functions in evaluate.h.
38  *
39  * \todo
40  * One of the major bottlenecks for selection performance is that all the
41  * evaluation is carried out for atoms.
42  * There are several cases when the evaluation could be done for residues
43  * or molecules instead, including keywords that select by residue and
44  * cases where residue centers are used as reference positions.
45  * Implementing this would require a mechanism for recognizing whether
46  * something can be evaluated by residue/molecule instead by atom, and
47  * converting selections by residue/molecule into selections by atom
48  * when necessary.
49  *
50  * \author Teemu Murtola <teemu.murtola@gmail.com>
51  * \ingroup module_selection
52  */
53 #include <string.h>
54
55 #include "gromacs/legacyheaders/vec.h"
56
57 #include "gromacs/math/utilities.h"
58 #include "gromacs/selection/indexutil.h"
59 #include "gromacs/selection/poscalc.h"
60 #include "gromacs/selection/selection.h"
61 #include "gromacs/selection/selmethod.h"
62 #include "gromacs/utility/exceptions.h"
63 #include "gromacs/utility/gmxassert.h"
64 #include "gromacs/utility/smalloc.h"
65
66 #include "evaluate.h"
67 #include "mempool.h"
68 #include "selectioncollection-impl.h"
69 #include "selelem.h"
70
71 using gmx::SelectionTreeElement;
72 using gmx::SelectionTreeElementPointer;
73
74 namespace
75 {
76
77 /*! \brief
78  * Reserves memory for a selection element from the evaluation memory pool.
79  *
80  * This class implements RAII semantics for allocating memory for selection
81  * element values from a selection evaluation memory pool.
82  *
83  * \ingroup module_selection
84  */
85 class MempoolSelelemReserver
86 {
87     public:
88         //! Constructs a reserver without initial reservation.
89         MempoolSelelemReserver() {}
90         /*! \brief
91          * Constructs a reserver with initial reservation.
92          *
93          * \param[in,out] sel    Selection element for which to reserve.
94          * \param[in]     count  Number of values to reserve.
95          *
96          * \see reserve()
97          */
98         MempoolSelelemReserver(const SelectionTreeElementPointer &sel, int count)
99         {
100             reserve(sel, count);
101         }
102         //! Frees any memory allocated using this reserver.
103         ~MempoolSelelemReserver()
104         {
105             if (sel_)
106             {
107                 sel_->mempoolRelease();
108             }
109         }
110
111         /*! \brief
112          * Reserves memory for selection element values using this reserver.
113          *
114          * \param[in,out] sel    Selection element for which to reserve.
115          * \param[in]     count  Number of values to reserve.
116          *
117          * Allocates space to store \p count output values in \p sel from the
118          * memory pool associated with \p sel, or from the heap if there is no
119          * memory pool.  Type of values to allocate is automatically determined
120          * from \p sel.
121          */
122         void reserve(const SelectionTreeElementPointer &sel, int count)
123         {
124             GMX_RELEASE_ASSERT(!sel_,
125                                "Can only reserve one element with one instance");
126             sel->mempoolReserve(count);
127             sel_ = sel;
128         }
129
130     private:
131         SelectionTreeElementPointer     sel_;
132 };
133
134 /*! \brief
135  * Reserves memory for an index group from the evaluation memory pool.
136  *
137  * This class implements RAII semantics for allocating memory for an index
138  * group from a selection evaluation memory pool.
139  *
140  * \ingroup module_selection
141  */
142 class MempoolGroupReserver
143 {
144     public:
145         /*! \brief
146          * Creates a reserver associated with a given memory pool.
147          *
148          * \param    mp  Memory pool from which to reserve memory.
149          */
150         explicit MempoolGroupReserver(gmx_sel_mempool_t *mp)
151             : mp_(mp), g_(NULL)
152         {
153         }
154         //! Frees any memory allocated using this reserver.
155         ~MempoolGroupReserver()
156         {
157             if (g_ != NULL)
158             {
159                 _gmx_sel_mempool_free_group(mp_, g_);
160             }
161         }
162
163         /*! \brief
164          * Reserves memory for an index group using this reserver.
165          *
166          * \param[in,out] g      Index group to reserve.
167          * \param[in]     count  Number of atoms to reserve space for.
168          *
169          * Allocates memory from the memory pool to store \p count atoms in
170          * \p g.
171          */
172         void reserve(gmx_ana_index_t *g, int count)
173         {
174             GMX_RELEASE_ASSERT(g_ == NULL, "Can only reserve one element with one instance");
175             _gmx_sel_mempool_alloc_group(mp_, g, count);
176             g_ = g;
177         }
178
179     private:
180         gmx_sel_mempool_t      *mp_;
181         gmx_ana_index_t        *g_;
182 };
183
184 /*! \brief
185  * Assigns a temporary value for a selection element.
186  *
187  * This class implements RAII semantics for temporarily assigning the value
188  * pointer of a selection element to point to a different location.
189  *
190  * \ingroup module_selection
191  */
192 class SelelemTemporaryValueAssigner
193 {
194     public:
195         //! Constructs an assigner without an initial assignment.
196         SelelemTemporaryValueAssigner()
197             : old_ptr_(NULL), old_nalloc_(0)
198         {
199         }
200         /*! \brief
201          * Constructs an assigner with an initial assignment.
202          *
203          * \param[in,out] sel     Selection element for which to assign.
204          * \param[in]     vsource Element to which \p sel values will point to.
205          *
206          * \see assign()
207          */
208         SelelemTemporaryValueAssigner(const SelectionTreeElementPointer &sel,
209                                       const SelectionTreeElement        &vsource)
210         {
211             assign(sel, vsource);
212         }
213         //! Undoes any temporary assignment done using this assigner.
214         ~SelelemTemporaryValueAssigner()
215         {
216             if (sel_)
217             {
218                 _gmx_selvalue_setstore_alloc(&sel_->v, old_ptr_, old_nalloc_);
219             }
220         }
221
222         /*! \brief
223          * Assigns a temporary value pointer.
224          *
225          * \param[in,out] sel     Selection element for which to assign.
226          * \param[in]     vsource Element to which \p sel values will point to.
227          *
228          * Assigns the value pointer in \p sel to point to the values in
229          * \p vsource, i.e., any access/modification to values in \p sel
230          * actually accesses values in \p vsource.
231          */
232         void assign(const SelectionTreeElementPointer &sel,
233                     const SelectionTreeElement        &vsource)
234         {
235             GMX_RELEASE_ASSERT(!sel_,
236                                "Can only assign one element with one instance");
237             GMX_RELEASE_ASSERT(sel->v.type == vsource.v.type,
238                                "Mismatching selection value types");
239             old_ptr_    = sel->v.u.ptr;
240             old_nalloc_ = sel->v.nalloc;
241             _gmx_selvalue_setstore(&sel->v, vsource.v.u.ptr);
242             sel_ = sel;
243         }
244
245     private:
246         SelectionTreeElementPointer     sel_;
247         void                           *old_ptr_;
248         int                             old_nalloc_;
249 };
250
251 } // namespace
252
253 /*!
254  * \param[in] fp       File handle to receive the output.
255  * \param[in] evalfunc Function pointer to print.
256  */
257 void
258 _gmx_sel_print_evalfunc_name(FILE *fp, gmx::sel_evalfunc evalfunc)
259 {
260     if (!evalfunc)
261     {
262         fprintf(fp, "none");
263     }
264     else if (evalfunc == &_gmx_sel_evaluate_root)
265     {
266         fprintf(fp, "root");
267     }
268     else if (evalfunc == &_gmx_sel_evaluate_static)
269     {
270         fprintf(fp, "static");
271     }
272     else if (evalfunc == &_gmx_sel_evaluate_subexpr_simple)
273     {
274         fprintf(fp, "subexpr_simple");
275     }
276     else if (evalfunc == &_gmx_sel_evaluate_subexpr_staticeval)
277     {
278         fprintf(fp, "subexpr_staticeval");
279     }
280     else if (evalfunc == &_gmx_sel_evaluate_subexpr)
281     {
282         fprintf(fp, "subexpr");
283     }
284     else if (evalfunc == &_gmx_sel_evaluate_subexprref_simple)
285     {
286         fprintf(fp, "ref_simple");
287     }
288     else if (evalfunc == &_gmx_sel_evaluate_subexprref)
289     {
290         fprintf(fp, "ref");
291     }
292     else if (evalfunc == &_gmx_sel_evaluate_method)
293     {
294         fprintf(fp, "method");
295     }
296     else if (evalfunc == &_gmx_sel_evaluate_modifier)
297     {
298         fprintf(fp, "mod");
299     }
300     else if (evalfunc == &_gmx_sel_evaluate_not)
301     {
302         fprintf(fp, "not");
303     }
304     else if (evalfunc == &_gmx_sel_evaluate_and)
305     {
306         fprintf(fp, "and");
307     }
308     else if (evalfunc == &_gmx_sel_evaluate_or)
309     {
310         fprintf(fp, "or");
311     }
312     else if (evalfunc == &_gmx_sel_evaluate_arithmetic)
313     {
314         fprintf(fp, "arithmetic");
315     }
316     else
317     {
318         fprintf(fp, "%p", (void*)(evalfunc));
319     }
320 }
321
322 /*!
323  * \param[out] data Evaluation data structure to initialize.
324  * \param[in]  mp   Memory pool for intermediate evaluation values.
325  * \param[in]  gall Index group with all the atoms.
326  * \param[in]  top  Topology structure for evaluation.
327  * \param[in]  fr   New frame for evaluation.
328  * \param[in]  pbc  New PBC information for evaluation.
329  */
330 void
331 _gmx_sel_evaluate_init(gmx_sel_evaluate_t *data,
332                        gmx_sel_mempool_t *mp, gmx_ana_index_t *gall,
333                        t_topology *top, t_trxframe *fr, t_pbc *pbc)
334 {
335     data->mp   = mp;
336     data->gall = gall;
337     data->top  = top;
338     data->fr   = fr;
339     data->pbc  = pbc;
340 }
341
342 /*! \brief
343  * Recursively initializes the flags for evaluation.
344  *
345  * \param[in,out] sel Selection element to clear.
346  *
347  * The \ref SEL_INITFRAME flag is set for \ref SEL_EXPRESSION elements whose
348  * method defines the \p init_frame callback (see sel_framefunc()), and
349  * cleared for other elements.
350  *
351  * The \ref SEL_EVALFRAME flag is cleared for all elements.
352  */
353 static void
354 init_frame_eval(SelectionTreeElementPointer sel)
355 {
356     while (sel)
357     {
358         sel->flags &= ~(SEL_INITFRAME | SEL_EVALFRAME);
359         if (sel->type == SEL_EXPRESSION)
360         {
361             if (sel->u.expr.method && sel->u.expr.method->init_frame)
362             {
363                 sel->flags |= SEL_INITFRAME;
364             }
365         }
366         if (sel->child && sel->type != SEL_SUBEXPRREF)
367         {
368             init_frame_eval(sel->child);
369         }
370         sel = sel->next;
371     }
372 }
373
374 namespace gmx
375 {
376
377 SelectionEvaluator::SelectionEvaluator()
378 {
379 }
380
381 /*!
382  * \param[in,out] coll  The selection collection to evaluate.
383  * \param[in] fr  Frame for which the evaluation should be carried out.
384  * \param[in] pbc PBC data, or NULL if no PBC should be used.
385  * \returns   0 on successful evaluation, a non-zero error code on error.
386  *
387  * This functions sets the global variables for topology, frame and PBC,
388  * clears some information in the selection to initialize the evaluation
389  * for a new frame, and evaluates \p sel and all the selections pointed by
390  * the \p next pointers of \p sel.
391  *
392  * This is the only function that user code should call if they want to
393  * evaluate a selection for a new frame.
394  */
395 void
396 SelectionEvaluator::evaluate(SelectionCollection *coll,
397                              t_trxframe *fr, t_pbc *pbc)
398 {
399     gmx_ana_selcollection_t *sc = &coll->impl_->sc_;
400     gmx_sel_evaluate_t       data;
401
402     _gmx_sel_evaluate_init(&data, sc->mempool, &sc->gall, sc->top, fr, pbc);
403     init_frame_eval(sc->root);
404     SelectionTreeElementPointer sel = sc->root;
405     while (sel)
406     {
407         /* Clear the evaluation group of subexpressions */
408         if (sel->child && sel->child->type == SEL_SUBEXPR
409             && sel->child->evaluate != NULL)
410         {
411             sel->child->u.cgrp.isize = 0;
412             /* Not strictly necessary, because the value will be overwritten
413              * during first evaluation of the subexpression anyways, but we
414              * clear the group for clarity. Note that this is _not_ done during
415              * compilation because of some additional complexities involved
416              * (see compiler.cpp), so it should not be relied upon in
417              * _gmx_sel_evaluate_subexpr(). */
418             if (sel->child->v.type == GROUP_VALUE)
419             {
420                 sel->child->v.u.g->isize = 0;
421             }
422         }
423         if (sel->evaluate)
424         {
425             sel->evaluate(&data, sel, NULL);
426         }
427         sel = sel->next;
428     }
429     /* Update selection information */
430     SelectionDataList::const_iterator isel;
431     for (isel = sc->sel.begin(); isel != sc->sel.end(); ++isel)
432     {
433         internal::SelectionData &sel = **isel;
434         sel.refreshMassesAndCharges(sc->top);
435         sel.updateCoveredFractionForFrame();
436     }
437 }
438
439 /*!
440  * \param[in,out] coll  The selection collection to evaluate.
441  * \param[in]     nframes Total number of frames.
442  */
443 void
444 SelectionEvaluator::evaluateFinal(SelectionCollection *coll, int nframes)
445 {
446     gmx_ana_selcollection_t          *sc = &coll->impl_->sc_;
447
448     SelectionDataList::const_iterator isel;
449     for (isel = sc->sel.begin(); isel != sc->sel.end(); ++isel)
450     {
451         internal::SelectionData &sel = **isel;
452         sel.restoreOriginalPositions(sc->top);
453         sel.computeAverageCoveredFraction(nframes);
454     }
455 }
456
457 } // namespace gmx
458
459 /*!
460  * \param[in] data Data for the current frame.
461  * \param[in] sel  Selection element being evaluated.
462  * \param[in] g    Group for which \p sel should be evaluated.
463  * \returns   0 on success, a non-zero error code on error.
464  *
465  * Evaluates each child of \p sel in \p g.
466  */
467 void
468 _gmx_sel_evaluate_children(gmx_sel_evaluate_t                     *data,
469                            const gmx::SelectionTreeElementPointer &sel,
470                            gmx_ana_index_t                        *g)
471 {
472     SelectionTreeElementPointer child = sel->child;
473     while (child)
474     {
475         if (child->evaluate)
476         {
477             child->evaluate(data, child, g);
478         }
479         child = child->next;
480     }
481 }
482
483 void
484 _gmx_sel_evaluate_root(gmx_sel_evaluate_t                     *data,
485                        const gmx::SelectionTreeElementPointer &sel,
486                        gmx_ana_index_t                         * /* g */)
487 {
488     if (sel->u.cgrp.isize == 0 || !sel->child->evaluate)
489     {
490         return;
491     }
492
493     sel->child->evaluate(data, sel->child,
494                          sel->u.cgrp.isize < 0 ? NULL : &sel->u.cgrp);
495 }
496
497 void
498 _gmx_sel_evaluate_static(gmx_sel_evaluate_t                      * /* data */,
499                          const gmx::SelectionTreeElementPointer &sel,
500                          gmx_ana_index_t                        *g)
501 {
502     if (sel->flags & SEL_UNSORTED)
503     {
504         // This only works if g contains all the atoms, but that is currently
505         // the only supported case.
506         gmx_ana_index_copy(sel->v.u.g, &sel->u.cgrp, false);
507     }
508     else
509     {
510         gmx_ana_index_intersection(sel->v.u.g, &sel->u.cgrp, g);
511     }
512 }
513
514
515 /*********************************************************************
516  * SUBEXPRESSION EVALUATION
517  *********************************************************************/
518
519 /*!
520  * \param[in] data Data for the current frame.
521  * \param[in] sel  Selection element being evaluated.
522  * \param[in] g    Group for which \p sel should be evaluated.
523  * \returns   0 on success, a non-zero error code on error.
524  *
525  * Evaluates the child element (there should be exactly one) in \p g.
526  * The compiler has taken care that the child actually stores the evaluated
527  * value in the value pointer of this element.
528  *
529  * This function is used as gmx::SelectionTreeElement::evaluate for
530  * \ref SEL_SUBEXPR elements that are used only once, and hence do not need
531  * full subexpression handling.
532  */
533 void
534 _gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t                     *data,
535                                  const gmx::SelectionTreeElementPointer &sel,
536                                  gmx_ana_index_t                        *g)
537 {
538     if (sel->child->evaluate)
539     {
540         sel->child->evaluate(data, sel->child, g);
541     }
542     sel->v.nr = sel->child->v.nr;
543 }
544
545 /*!
546  * \param[in] data Data for the current frame.
547  * \param[in] sel  Selection element being evaluated.
548  * \param[in] g    Group for which \p sel should be evaluated.
549  * \returns   0 on success, a non-zero error code on error.
550  *
551  * If this is the first call for this frame, evaluates the child element
552  * there should be exactly one in \p g.
553  * The compiler has taken care that the child actually stores the evaluated
554  * value in the value pointer of this element.
555  * Assumes that \p g is persistent for the duration of the whole evaluation.
556  *
557  * This function is used as gmx::SelectionTreeElement::evaluate for
558  * \ref SEL_SUBEXPR elements that have a static evaluation group, and hence do
559  * not need full subexpression handling.
560  */
561 void
562 _gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t                     *data,
563                                      const gmx::SelectionTreeElementPointer &sel,
564                                      gmx_ana_index_t                        *g)
565 {
566     if (sel->u.cgrp.isize == 0)
567     {
568         sel->child->evaluate(data, sel->child, g);
569         sel->v.nr = sel->child->v.nr;
570         if (!g)
571         {
572             sel->u.cgrp.isize = -1;
573         }
574         else
575         {
576             gmx_ana_index_set(&sel->u.cgrp, g->isize, g->index, 0);
577         }
578     }
579 }
580
581 /*!
582  * \param[in]  data  Data for the current frame.
583  * \param[in]  sel   Selection element being evaluated.
584  * \param[in]  g     Group for which \p sel should be evaluated.
585  * \returns    0 on success, a non-zero error code on error.
586  *
587  * Finds the part of \p g for which the subexpression
588  * has not yet been evaluated by comparing \p g to \p sel->u.cgrp.
589  * If the part is not empty, the child expression is evaluated for this
590  * part, and the results merged to the old values of the child.
591  * The value of \p sel itself is undefined after the call.
592  *
593  * \todo
594  * The call to gmx_ana_index_difference() can take quite a lot of unnecessary
595  * time if the subexpression is evaluated either several times for the same
596  * group or for completely distinct groups.
597  * However, in the majority of cases, these situations occur when
598  * _gmx_sel_evaluate_subexpr_staticeval() can be used, so this should not be a
599  * major problem.
600  */
601 void
602 _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t                     *data,
603                           const gmx::SelectionTreeElementPointer &sel,
604                           gmx_ana_index_t                        *g)
605 {
606     gmx_ana_index_t      gmiss;
607
608     MempoolGroupReserver gmissreserver(data->mp);
609     if (sel->u.cgrp.isize == 0)
610     {
611         {
612             SelelemTemporaryValueAssigner assigner(sel->child, *sel);
613             sel->child->evaluate(data, sel->child, g);
614         }
615         gmx_ana_index_copy(&sel->u.cgrp, g, false);
616         gmiss.isize      = 0;
617     }
618     else
619     {
620         gmissreserver.reserve(&gmiss, g->isize);
621         gmx_ana_index_difference(&gmiss, g, &sel->u.cgrp);
622     }
623     if (gmiss.isize > 0)
624     {
625         MempoolSelelemReserver reserver(sel->child, gmiss.isize);
626         /* Evaluate the missing values for the child */
627         sel->child->evaluate(data, sel->child, &gmiss);
628         /* Merge the missing values to the existing ones. */
629         if (sel->v.type == GROUP_VALUE)
630         {
631             gmx_ana_index_merge(sel->v.u.g, sel->child->v.u.g, sel->v.u.g);
632         }
633         else
634         {
635             int  i, j, k;
636
637             i = sel->u.cgrp.isize - 1;
638             j = gmiss.isize - 1;
639             /* TODO: This switch is kind of ugly, but it may be difficult to
640              * do this portably without C++ templates. */
641             switch (sel->v.type)
642             {
643                 case INT_VALUE:
644                     for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--)
645                     {
646                         if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
647                         {
648                             sel->v.u.i[k] = sel->child->v.u.i[j--];
649                         }
650                         else
651                         {
652                             sel->v.u.i[k] = sel->v.u.i[i--];
653                         }
654                     }
655                     break;
656
657                 case REAL_VALUE:
658                     for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--)
659                     {
660                         if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
661                         {
662                             sel->v.u.r[k] = sel->child->v.u.r[j--];
663                         }
664                         else
665                         {
666                             sel->v.u.r[k] = sel->v.u.r[i--];
667                         }
668                     }
669                     break;
670
671                 case STR_VALUE:
672                     // Note: with the currently allowed syntax, this case is never
673                     // reached.
674                     for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--)
675                     {
676                         if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
677                         {
678                             sel->v.u.s[k] = sel->child->v.u.s[j--];
679                         }
680                         else
681                         {
682                             sel->v.u.s[k] = sel->v.u.s[i--];
683                         }
684                     }
685                     break;
686
687                 case POS_VALUE:
688                     /* TODO: Implement this */
689                     GMX_THROW(gmx::NotImplementedError("position subexpressions not implemented properly"));
690
691                 case NO_VALUE:
692                 case GROUP_VALUE:
693                     GMX_THROW(gmx::InternalError("Invalid subexpression type"));
694             }
695         }
696         gmx_ana_index_merge(&sel->u.cgrp, &sel->u.cgrp, &gmiss);
697     }
698 }
699
700 /*!
701  * \param[in] data Data for the current frame.
702  * \param[in] sel Selection element being evaluated.
703  * \param[in] g   Group for which \p sel should be evaluated.
704  * \returns   0 for success.
705  *
706  * Sets the value pointers of the child and its child to point to the same
707  * memory as the value pointer of this element to avoid copying, and then
708  * evaluates evaluates the child.
709  *
710  * This function is used as gmx::SelectionTreeElement:evaluate for
711  * \ref SEL_SUBEXPRREF elements for which the \ref SEL_SUBEXPR does not have
712  * other references.
713  */
714 void
715 _gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t                     *data,
716                                     const gmx::SelectionTreeElementPointer &sel,
717                                     gmx_ana_index_t                        *g)
718 {
719     if (g)
720     {
721         _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
722         _gmx_selvalue_setstore_alloc(&sel->child->child->v, sel->v.u.ptr,
723                                      sel->child->child->v.nalloc);
724         sel->child->evaluate(data, sel->child, g);
725     }
726     sel->v.nr = sel->child->v.nr;
727     if (sel->u.param)
728     {
729         sel->u.param->val.nr = sel->v.nr;
730         if (sel->u.param->nvalptr)
731         {
732             *sel->u.param->nvalptr = sel->u.param->val.nr;
733         }
734     }
735 }
736
737 /*!
738  * \param[in] data Data for the current frame.
739  * \param[in] sel Selection element being evaluated.
740  * \param[in] g   Group for which \p sel should be evaluated.
741  * \returns   0 on success, a non-zero error code on error.
742  *
743  * If the value type is \ref POS_VALUE, the value of the child is simply
744  * copied to set the value of \p sel (the child subexpression should
745  * already have been evaluated by its root).
746  * If the value type is something else, the child is evaluated for the
747  * group \p g, and the value of the child is then copied.
748  * There should be only one child element.
749  *
750  * This function is used as gmx::SelectionTreeElement::evaluate for
751  * \ref SEL_SUBEXPRREF elements.
752  */
753 void
754 _gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t                     *data,
755                              const gmx::SelectionTreeElementPointer &sel,
756                              gmx_ana_index_t                        *g)
757 {
758     int        i, j;
759
760     if (g != NULL && sel->child->evaluate != NULL)
761     {
762         sel->child->evaluate(data, sel->child, g);
763     }
764     const SelectionTreeElementPointer &expr = sel->child;
765     switch (sel->v.type)
766     {
767         case INT_VALUE:
768             if (!g)
769             {
770                 sel->v.nr = expr->v.nr;
771                 memcpy(sel->v.u.i, expr->v.u.i, sel->v.nr*sizeof(*sel->v.u.i));
772             }
773             else
774             {
775                 sel->v.nr = g->isize;
776                 /* Extract the values corresponding to g */
777                 for (i = j = 0; i < g->isize; ++i, ++j)
778                 {
779                     while (sel->child->u.cgrp.index[j] < g->index[i])
780                     {
781                         ++j;
782                     }
783                     sel->v.u.i[i] = expr->v.u.i[j];
784                 }
785             }
786             break;
787
788         case REAL_VALUE:
789             if (!g)
790             {
791                 sel->v.nr = expr->v.nr;
792                 memcpy(sel->v.u.r, expr->v.u.r, sel->v.nr*sizeof(*sel->v.u.r));
793             }
794             else
795             {
796                 sel->v.nr = g->isize;
797                 /* Extract the values corresponding to g */
798                 for (i = j = 0; i < g->isize; ++i, ++j)
799                 {
800                     while (sel->child->u.cgrp.index[j] < g->index[i])
801                     {
802                         ++j;
803                     }
804                     sel->v.u.r[i] = expr->v.u.r[j];
805                 }
806             }
807             break;
808
809         case STR_VALUE:
810             if (!g)
811             {
812                 sel->v.nr = expr->v.nr;
813                 memcpy(sel->v.u.s, expr->v.u.s, sel->v.nr*sizeof(*sel->v.u.s));
814             }
815             else
816             {
817                 sel->v.nr = g->isize;
818                 /* Extract the values corresponding to g */
819                 for (i = j = 0; i < g->isize; ++i, ++j)
820                 {
821                     while (sel->child->u.cgrp.index[j] < g->index[i])
822                     {
823                         ++j;
824                     }
825                     sel->v.u.s[i] = expr->v.u.s[j];
826                 }
827             }
828             break;
829
830         case POS_VALUE:
831             /* Currently, there is no need to do anything fancy here,
832              * but some future extensions may need a more flexible
833              * implementation. */
834             gmx_ana_pos_copy(sel->v.u.p, expr->v.u.p, false);
835             break;
836
837         case GROUP_VALUE:
838             if (!g)
839             {
840                 gmx_ana_index_copy(sel->v.u.g, expr->v.u.g, false);
841             }
842             else
843             {
844                 gmx_ana_index_intersection(sel->v.u.g, expr->v.u.g, g);
845             }
846             break;
847
848         default: /* should not be reached */
849             GMX_THROW(gmx::InternalError("Invalid subexpression reference type"));
850     }
851     /* Store the number of values if needed */
852     if (sel->u.param)
853     {
854         sel->u.param->val.nr = sel->v.nr;
855         if (sel->u.param->nvalptr)
856         {
857             *sel->u.param->nvalptr = sel->u.param->val.nr;
858         }
859     }
860 }
861
862 /********************************************************************
863  * METHOD EXPRESSION EVALUATION
864  ********************************************************************/
865
866 /*!
867  * \param[in] data Data for the current frame.
868  * \param[in] sel Selection element being evaluated.
869  * \param[in] g   Group for which \p sel should be evaluated.
870  * \returns   0 on success, a non-zero error code on error.
871  *
872  * Evaluates each child of a \ref SEL_EXPRESSION element.
873  * The value of \p sel is not touched.
874  *
875  * This function is not used as gmx::SelectionTreeElement::evaluate,
876  * but is used internally.
877  */
878 void
879 _gmx_sel_evaluate_method_params(gmx_sel_evaluate_t                     *data,
880                                 const gmx::SelectionTreeElementPointer &sel,
881                                 gmx_ana_index_t                        *g)
882 {
883     SelectionTreeElementPointer child = sel->child;
884     while (child)
885     {
886         if (child->evaluate && !(child->flags & SEL_EVALFRAME))
887         {
888             if (child->flags & SEL_ATOMVAL)
889             {
890                 child->evaluate(data, child, g);
891             }
892             else
893             {
894                 child->flags |= SEL_EVALFRAME;
895                 child->evaluate(data, child, NULL);
896             }
897         }
898         child = child->next;
899     }
900 }
901
902 /*!
903  * \param[in] data Data for the current frame.
904  * \param[in] sel Selection element being evaluated.
905  * \param[in] g   Group for which \p sel should be evaluated.
906  * \returns   0 on success, a non-zero error code on error.
907  *
908  * Evaluates all child selections (using _gmx_sel_evaluate_method_params())
909  * to evaluate any parameter values.
910  * If this is the first time this expression is evaluated for
911  * the frame, sel_framefunc() callback is called if one is provided.
912  * If a reference position calculation has been initialized for this element,
913  * the positions are also updated, and sel_updatefunc_pos() is used to
914  * evaluate the value. Otherwise, sel_updatefunc() is used.
915  *
916  * This function is used as gmx::SelectionTreeElement::evaluate for
917  * \ref SEL_EXPRESSION elements.
918  */
919 void
920 _gmx_sel_evaluate_method(gmx_sel_evaluate_t                     *data,
921                          const gmx::SelectionTreeElementPointer &sel,
922                          gmx_ana_index_t                        *g)
923 {
924     _gmx_sel_evaluate_method_params(data, sel, g);
925     if (sel->flags & SEL_INITFRAME)
926     {
927         sel->flags &= ~SEL_INITFRAME;
928         sel->u.expr.method->init_frame(data->top, data->fr, data->pbc,
929                                        sel->u.expr.mdata);
930     }
931     if (sel->u.expr.pc)
932     {
933         gmx_ana_poscalc_update(sel->u.expr.pc, sel->u.expr.pos, g,
934                                data->fr, data->pbc);
935         sel->u.expr.method->pupdate(data->top, data->fr, data->pbc,
936                                     sel->u.expr.pos, &sel->v,
937                                     sel->u.expr.mdata);
938     }
939     else
940     {
941         sel->u.expr.method->update(data->top, data->fr, data->pbc, g,
942                                    &sel->v, sel->u.expr.mdata);
943     }
944 }
945
946 /*!
947  * \param[in] data Data for the current frame.
948  * \param[in] sel Selection element being evaluated.
949  * \param[in] g   Group for which \p sel should be evaluated.
950  * \returns   0 on success, a non-zero error code on error.
951  *
952  * Evaluates all child selections (using _gmx_sel_evaluate_method_params())
953  * to evaluate any parameter values.
954  * If this is the first time this expression is evaluated for
955  * the frame, sel_framefunc() callback is called if one is provided.
956  * The modifier is then evaluated using sel_updatefunc_pos().
957  *
958  * This function is used as gmx::SelectionTreeElement::evaluate for
959  * \ref SEL_MODIFIER elements.
960  */
961 void
962 _gmx_sel_evaluate_modifier(gmx_sel_evaluate_t                     *data,
963                            const gmx::SelectionTreeElementPointer &sel,
964                            gmx_ana_index_t                        *g)
965 {
966     _gmx_sel_evaluate_method_params(data, sel, g);
967     if (sel->flags & SEL_INITFRAME)
968     {
969         sel->flags &= ~SEL_INITFRAME;
970         sel->u.expr.method->init_frame(data->top, data->fr, data->pbc,
971                                        sel->u.expr.mdata);
972     }
973     GMX_RELEASE_ASSERT(sel->child != NULL,
974                        "Modifier element with a value must have a child");
975     if (sel->child->v.type != POS_VALUE)
976     {
977         GMX_THROW(gmx::NotImplementedError("Non-position valued modifiers not implemented"));
978     }
979     sel->u.expr.method->pupdate(data->top, data->fr, data->pbc,
980                                 sel->child->v.u.p,
981                                 &sel->v, sel->u.expr.mdata);
982 }
983
984
985 /********************************************************************
986  * BOOLEAN EXPRESSION EVALUATION
987  ********************************************************************/
988
989 /*!
990  * \param[in] data Data for the current frame.
991  * \param[in] sel Selection element being evaluated.
992  * \param[in] g   Group for which \p sel should be evaluated.
993  * \returns   0 on success, a non-zero error code on error.
994  *
995  * Evaluates the child element (there should be only one) in the group
996  * \p g, and then sets the value of \p sel to the complement of the
997  * child value.
998  *
999  * This function is used as gmx::SelectionTreeElement::evaluate for
1000  * \ref SEL_BOOLEAN elements with \ref BOOL_NOT.
1001  */
1002 void
1003 _gmx_sel_evaluate_not(gmx_sel_evaluate_t                     *data,
1004                       const gmx::SelectionTreeElementPointer &sel,
1005                       gmx_ana_index_t                        *g)
1006 {
1007     MempoolSelelemReserver reserver(sel->child, g->isize);
1008     sel->child->evaluate(data, sel->child, g);
1009     gmx_ana_index_difference(sel->v.u.g, g, sel->child->v.u.g);
1010 }
1011
1012 /*!
1013  * \param[in] data Data for the current frame.
1014  * \param[in] sel Selection element being evaluated.
1015  * \param[in] g   Group for which \p sel should be evaluated.
1016  * \returns   0 on success, a non-zero error code on error.
1017  *
1018  * Short-circuiting evaluation of logical AND expressions.
1019  *
1020  * Starts by evaluating the first child element in the group \p g.
1021  * The each following child element is evaluated in the intersection
1022  * of all the previous values until all children have been evaluated
1023  * or the intersection becomes empty.
1024  * The value of \p sel is set to the intersection of all the (evaluated)
1025  * child values.
1026  *
1027  * If the first child does not have an evaluation function, it is skipped
1028  * and the evaluation is started at the second child.
1029  * This happens if the first child is a constant expression and during
1030  * compilation it was detected that the evaluation group is always a subset
1031  * of the constant group
1032  * (currently, the compiler never detects this).
1033  *
1034  * This function is used as gmx::SelectionTreeElement::evaluate for
1035  * \ref SEL_BOOLEAN elements with \ref BOOL_AND.
1036  */
1037 void
1038 _gmx_sel_evaluate_and(gmx_sel_evaluate_t                     *data,
1039                       const gmx::SelectionTreeElementPointer &sel,
1040                       gmx_ana_index_t                        *g)
1041 {
1042     SelectionTreeElementPointer child = sel->child;
1043     /* Skip the first child if it does not have an evaluation function. */
1044     if (!child->evaluate)
1045     {
1046         child = child->next;
1047     }
1048     /* Evaluate the first child */
1049     {
1050         MempoolSelelemReserver reserver(child, g->isize);
1051         child->evaluate(data, child, g);
1052         gmx_ana_index_copy(sel->v.u.g, child->v.u.g, false);
1053     }
1054     child = child->next;
1055     while (child && sel->v.u.g->isize > 0)
1056     {
1057         MempoolSelelemReserver reserver(child, sel->v.u.g->isize);
1058         child->evaluate(data, child, sel->v.u.g);
1059         gmx_ana_index_intersection(sel->v.u.g, sel->v.u.g, child->v.u.g);
1060         child = child->next;
1061     }
1062 }
1063
1064 /*!
1065  * \param[in] data Data for the current frame.
1066  * \param[in] sel Selection element being evaluated.
1067  * \param[in] g   Group for which \p sel should be evaluated.
1068  * \returns   0 on success, a non-zero error code on error.
1069  *
1070  * Short-circuiting evaluation of logical OR expressions.
1071  *
1072  * Starts by evaluating the first child element in the group \p g.
1073  * For each subsequent child, finds the part of \p g that is not
1074  * included the value of any previous child, and evaluates the child
1075  * in that group until the last child is evaluated or all of \p g
1076  * is included in some child value.
1077  * The value of \p sel is set to the union of all the (evaluated)
1078  * child values.
1079  *
1080  * If the first child does not have an evaluation function, its value is
1081  * used without evaluation.
1082  * This happens if the first child is a constant expression, the selection
1083  * has been compiled, and the evaluation group is the same for each frame.
1084  * In this case, the compiler has taken care of that the child value is a
1085  * subset of \p g, making it unnecessary to evaluate it.
1086  *
1087  * This function is used as gmx::SelectionTreeElement::evaluate for
1088  * \ref SEL_BOOLEAN elements with \ref BOOL_OR.
1089  */
1090 void
1091 _gmx_sel_evaluate_or(gmx_sel_evaluate_t                     *data,
1092                      const gmx::SelectionTreeElementPointer &sel,
1093                      gmx_ana_index_t                        *g)
1094 {
1095     gmx_ana_index_t             tmp, tmp2;
1096
1097     SelectionTreeElementPointer child = sel->child;
1098     if (child->evaluate)
1099     {
1100         MempoolSelelemReserver reserver(child, g->isize);
1101         child->evaluate(data, child, g);
1102         gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
1103     }
1104     else
1105     {
1106         gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
1107     }
1108     child = child->next;
1109     while (child && tmp.isize > 0)
1110     {
1111         {
1112             MempoolSelelemReserver reserver(child, tmp.isize);
1113             child->evaluate(data, child, &tmp);
1114             gmx_ana_index_partition(&tmp, &tmp2, &tmp, child->v.u.g);
1115         }
1116         sel->v.u.g->isize += tmp.isize;
1117         tmp.isize          = tmp2.isize;
1118         tmp.index          = tmp2.index;
1119         child              = child->next;
1120     }
1121     gmx_ana_index_sort(sel->v.u.g);
1122 }
1123
1124
1125 /********************************************************************
1126  * ARITHMETIC EVALUATION
1127  ********************************************************************/
1128
1129 /*!
1130  * \param[in] data Data for the current frame.
1131  * \param[in] sel  Selection element being evaluated.
1132  * \param[in] g    Group for which \p sel should be evaluated.
1133  * \returns   0 on success, a non-zero error code on error.
1134  */
1135 void
1136 _gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t                     *data,
1137                              const gmx::SelectionTreeElementPointer &sel,
1138                              gmx_ana_index_t                        *g)
1139 {
1140     int         n, i, i1, i2;
1141     real        lval, rval = 0., val = 0.;
1142
1143     const SelectionTreeElementPointer &left  = sel->child;
1144     const SelectionTreeElementPointer &right = left->next;
1145
1146     SelelemTemporaryValueAssigner      assigner;
1147     MempoolSelelemReserver             reserver;
1148     if (left->mempool)
1149     {
1150         assigner.assign(left, *sel);
1151         if (right)
1152         {
1153             reserver.reserve(right, g->isize);
1154         }
1155     }
1156     else if (right && right->mempool)
1157     {
1158         assigner.assign(right, *sel);
1159     }
1160     _gmx_sel_evaluate_children(data, sel, g);
1161
1162     n         = (sel->flags & SEL_SINGLEVAL) ? 1 : g->isize;
1163     sel->v.nr = n;
1164
1165     bool bArithNeg = (sel->u.arith.type == ARITH_NEG);
1166     GMX_ASSERT(right || bArithNeg,
1167                "Right operand cannot be null except for negations");
1168     for (i = i1 = i2 = 0; i < n; ++i)
1169     {
1170         lval = left->v.u.r[i1];
1171         if (!bArithNeg)
1172         {
1173             rval = right->v.u.r[i2];
1174         }
1175         switch (sel->u.arith.type)
1176         {
1177             case ARITH_PLUS:    val = lval + rval;     break;
1178             case ARITH_MINUS:   val = lval - rval;     break;
1179             case ARITH_NEG:     val = -lval;           break;
1180             case ARITH_MULT:    val = lval * rval;     break;
1181             case ARITH_DIV:     val = lval / rval;     break;
1182             case ARITH_EXP:     val = pow(lval, rval); break;
1183         }
1184         sel->v.u.r[i] = val;
1185         if (!(left->flags & SEL_SINGLEVAL))
1186         {
1187             ++i1;
1188         }
1189         if (!bArithNeg && !(right->flags & SEL_SINGLEVAL))
1190         {
1191             ++i2;
1192         }
1193     }
1194 }