2 * This file is part of the GROMACS molecular simulation package.
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.
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.
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.
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.
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.
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.
36 * \brief Selection compilation and optimization.
39 * Better error handling and memory management in error situations.
40 * At least, the main compilation function leaves the selection collection in
41 * a bad state if an error occurs.
44 * The memory usage could still be optimized.
45 * Use of memory pooling could still be extended, and a lot of redundant
46 * gmin/gmax data could be eliminated for complex arithmetic expressions.
48 * \author Teemu Murtola <teemu.murtola@gmail.com>
49 * \ingroup module_selection
52 * \page page_module_selection_compiler Selection compilation
54 * The compiler takes the selection element tree from the selection parser
55 * (see \ref page_module_selection_parser) as input.
56 * The selection parser is quite independent of selection evaluation details,
57 * and the compiler processes the tree to conform to what the evaluation
59 * For better control and optimization possibilities, the compilation is
60 * done on all selections simultaneously.
61 * Hence, all the selections should be parsed before the compiler can be
64 * The compiler initializes all fields in gmx::SelectionTreeElement not
65 * initialized by the parser: gmx::SelectionTreeElement::v (some fields have
66 * already been initialized by the parser),
67 * gmx::SelectionTreeElement::evaluate, and gmx::SelectionTreeElement::u
68 * (again, some elements have been initialized in the parser).
69 * The gmx::SelectionTreeElement::cdata field is used during the compilation to store
70 * internal data, but the data is freed when the compiler returns.
72 * In addition to initializing the elements, the compiler reorganizes the tree
73 * to simplify and optimize evaluation. The compiler also evaluates the static
74 * parts of the selection: in the end of the compilation, static parts have
75 * been replaced by the result of the evaluation.
77 * The compiler is invoked using gmx::SelectionCompiler.
78 * The gmx::SelectionCompiler::compile() method does the compilation in several
79 * passes over the gmx::SelectionTreeElement tree.
80 * -# Defaults are set for the position type and flags of position calculation
81 * methods that were not explicitly specified in the user input.
82 * -# Subexpressions are extracted: a separate root is created for each
83 * subexpression, and placed before the expression is first used.
84 * Currently, only variables and expressions used to evaluate parameter
85 * values are extracted, but common subexpression could also be detected
87 * -# A second pass (in fact, multiple passes because of interdependencies)
88 * with simple reordering and initialization is done:
89 * -# Boolean expressions are combined such that one element can evaluate,
90 * e.g., "A and B and C". The subexpressions in boolean expression are
91 * reordered such that static expressions come first without otherwise
92 * altering the relative order of the expressions.
93 * -# The compiler data structure is allocated for each element, and
94 * the fields are initialized, with the exception of the contents of
95 * \c gmax and \c gmin fields. This is the part that needs multiple
96 * passes, because some flags are set recursively based on which elements
97 * refer to an element, and these flags need to be set to initialize
99 * -# The gmx::SelectionTreeElement::evaluate field is set to the correct
100 * evaluation function from evaluate.h.
102 * -# The evaluation function of all elements is replaced with the
103 * analyze_static() function to be able to initialize the element before
104 * the actual evaluation function is called.
105 * The evaluation machinery is then called to initialize the whole tree,
106 * while simultaneously evaluating the static expressions.
107 * During the evaluation, track is kept of the smallest and largest
108 * possible selections, and these are stored in the internal compiler
109 * data structure for each element.
110 * To be able to do this for all possible values of dynamical expressions,
111 * special care needs to be taken with boolean expressions because they
112 * are short-circuiting. This is done through the
113 * \c SEL_CDATA_EVALMAX flag, which makes dynamic child expressions
114 * of \c BOOL_OR expressions evaluate to empty groups, while subexpressions
115 * of \c BOOL_AND are evaluated to largest possible groups.
116 * Memory is also allocated to store the results of the evaluation.
117 * For each element, analyze_static() calls the actual evaluation function
118 * after the element has been properly initialized.
119 * -# Another evaluation pass is done over subexpressions with more than
120 * one reference to them. These cannot be completely processed during the
121 * first pass, because it is not known whether later references require
122 * additional evaluation of static expressions.
123 * -# Unused subexpressions are removed. For efficiency reasons (and to avoid
124 * some checks), this is actually done several times already earlier in
125 * the compilation process.
126 * -# Most of the processing is now done, and the next pass simply sets the
127 * evaluation group of root elements to the largest selection as determined
128 * in pass 4. For root elements of subexpressions that should not be
129 * evaluated before they are referred to, the evaluation group/function is
130 * cleared. At the same time, position calculation data is initialized for
131 * for selection method elements that require it. Compiler data is also
132 * freed as it is no longer needed.
133 * -# A final pass initializes the total masses and charges in the
134 * \c gmx_ana_selection_t data structures.
136 * The actual evaluation of the selection is described in the documentation
137 * of the functions in evaluate.h.
140 * Some combinations of method parameter flags are not yet properly treated by
141 * the compiler or the evaluation functions in evaluate.cpp. All the ones used by
142 * currently implemented methods should work, but new combinations might not.
145 * \section selcompiler_tree Element tree after compilation
147 * After the compilation, the selection element tree is suitable for
148 * gmx_ana_selcollection_evaluate().
149 * Enough memory has been allocated for gmx::SelectionTreeElement::v
150 * (and gmx::SelectionTreeElement::cgrp for \ref SEL_SUBEXPR elements) to allow
151 * the selection to be evaluated without allocating any memory.
154 * \subsection selcompiler_tree_root Root elements
156 * The top level of the tree consists of a chain of \ref SEL_ROOT elements.
157 * These are used for two purposes:
158 * -# A selection that should be evaluated.
159 * These elements appear in the same order as the selections in the input.
160 * For these elements, gmx::SelectionTreeElement::v has been set to the
161 * maximum possible group that the selection can evaluate to (only for
162 * dynamic selections), and gmx::SelectionTreeElement::cgrp has been set to
163 * use a NULL group for evaluation.
164 * -# A subexpression that appears in one or more selections.
165 * Each selection that gives a value for a method parameter is a
166 * potential subexpression, as is any variable value.
167 * Only subexpressions that require evaluation for each frame are left
168 * after the selection is compiled.
169 * Each subexpression appears in the chain before any references to it.
170 * For these elements, gmx::SelectionTreeElement::cgrp has been set to the
171 * group that should be used to evaluate the subexpression.
172 * If gmx::SelectionTreeElement::cgrp is empty, the total evaluation group
173 * is not known in advance or it is more efficient to evaluate the
174 * subexpression only when it is referenced. If this is the case,
175 * gmx::SelectionTreeElement::evaluate is also NULL.
177 * The children of the \ref SEL_ROOT elements can be used to distinguish
178 * the two types of root elements from each other; the rules are the same
179 * as for the parsed tree (see \ref selparser_tree_root).
180 * Subexpressions are treated as if they had been provided through variables.
182 * Selection names are stored as after parsing (see \ref selparser_tree_root).
185 * \subsection selcompiler_tree_const Constant elements
187 * All (sub)selections that do not require particle positions have been
188 * replaced with \ref SEL_CONST elements.
189 * Constant elements from the parser are also retained if present in
190 * dynamic parts of the selections.
191 * Several constant elements with a NULL gmx::SelectionTreeElement::evaluate
192 * are left for debugging purposes; of these, only the ones for \ref BOOL_OR
193 * expressions are used during evaluation.
195 * The value is stored in gmx::SelectionTreeElement::v, and for group values
196 * with an evaluation function set, also in gmx::SelectionTreeElement::cgrp.
197 * For \ref GROUP_VALUE elements, unnecessary atoms (i.e., atoms that
198 * could never be selected) have been removed from the value.
200 * \ref SEL_CONST elements have no children.
203 * \subsection selcompiler_tree_method Method evaluation elements
205 * All selection methods that need to be evaluated dynamically are described
206 * by a \ref SEL_EXPRESSION element. The gmx::SelectionTreeElement::method and
207 * gmx::SelectionTreeElement::mdata fields have already been initialized by the parser,
208 * and the compiler only calls the initialization functions in the method
209 * data structure to do some additional initialization of these fields at
210 * appropriate points. If the gmx::SelectionTreeElement::pc data field has been
211 * created by the parser, the compiler initializes the data structure properly
212 * once the required positions are known. If the gmx::SelectionTreeElement::pc
213 * field is NULL after the parser, but the method provides only
214 * sel_updatefunc_pos(), an appropriate position calculation data structure is
215 * created. If gmx::SelectionTreeElement::pc is not NULL,
216 * gmx::SelectionTreeElement::pos is also initialized to hold the positions
219 * Children of these elements are of type \ref SEL_SUBEXPRREF, and describe
220 * parameter values that need to be evaluated for each frame. See the next
221 * section for more details.
222 * \ref SEL_CONST children can also appear, and stand for parameters that get
223 * their value from a static expression. These elements are present only for
224 * debugging purposes: they always have a NULL evaluation function.
227 * \subsection selcompiler_tree_subexpr Subexpression elements
229 * As described in \ref selcompiler_tree_root, subexpressions are created
230 * for each variable and each expression that gives a value to a selection
231 * method parameter. As the only child of the \ref SEL_ROOT element,
232 * these elements have a \ref SEL_SUBEXPR element. The \ref SEL_SUBEXPR
233 * element has a single child, which evaluates the actual expression.
234 * After compilation, only subexpressions that require particle positions
235 * for evaluation are left.
236 * For non-variable subexpression, automatic names have been generated to
239 * For \ref SEL_SUBEXPR elements, memory has been allocated for
240 * gmx::SelectionTreeElement::cgrp to store the group for which the expression
241 * has been evaluated during the current frame. This is only done if full
242 * subexpression evaluation by _gmx_sel_evaluate_subexpr() is needed; the other
243 * evaluation functions do not require this memory.
245 * \ref SEL_SUBEXPRREF elements are used to describe references to
246 * subexpressions. They have always a single child, which is the
247 * \ref SEL_SUBEXPR element being referenced.
249 * If a subexpression is used only once, the evaluation has been optimized by
250 * setting the child of the \ref SEL_SUBEXPR element to evaluate the value of
251 * \ref SEL_SUBEXPRREF directly (in the case of memory pooling, this is managed
252 * by the evaluation functions). In such cases, the evaluation routines for the
253 * \ref SEL_SUBEXPRREF and \ref SEL_SUBEXPR elements only propagate some status
254 * information, but do not unnecessarily copy the values.
257 * \subsection selcompiler_tree_bool Boolean elements
259 * \ref SEL_BOOLEAN elements have been merged such that one element
260 * may carry out evaluation of more than one operation of the same type.
261 * The static parts of the expressions have been evaluated, and are placed
262 * in the first child. These are followed by the dynamic expressions, in the
263 * order provided by the user.
266 * \subsection selcompiler_tree_arith Arithmetic elements
268 * Constant and static expressions in \ref SEL_ARITHMETIC elements have been
270 * Currently, no other processing is done.
274 #include "compiler.h"
281 #include "gromacs/math/vec.h"
282 #include "gromacs/selection/indexutil.h"
283 #include "gromacs/selection/selection.h"
284 #include "gromacs/utility/exceptions.h"
285 #include "gromacs/utility/smalloc.h"
286 #include "gromacs/utility/stringutil.h"
288 #include "evaluate.h"
289 #include "keywords.h"
292 #include "selectioncollection-impl.h"
294 #include "selmethod.h"
297 using gmx::SelectionTreeElement;
298 using gmx::SelectionTreeElementPointer;
306 * Whether a subexpression needs to evaluated for all atoms.
308 * This flag is set for \ref SEL_SUBEXPR elements that are used to
309 * evaluate non-atom-valued selection method parameters, as well as
310 * those that are used directly as values of selections.
312 SEL_CDATA_FULLEVAL = 1,
314 * Whether the whole subexpression should be treated as static.
316 * This flag is always false if \ref SEL_DYNAMIC is set for the element,
317 * but it is also false for static elements within common subexpressions.
319 SEL_CDATA_STATIC = 2,
320 /** Whether the subexpression will always be evaluated in the same group. */
321 SEL_CDATA_STATICEVAL = 4,
322 /** Whether the compiler evaluation routine should return the maximal selection. */
323 SEL_CDATA_EVALMAX = 8,
324 /** Whether memory has been allocated for \p gmin and \p gmax. */
325 SEL_CDATA_MINMAXALLOC = 16,
326 /** Whether to update \p gmin and \p gmax in static analysis. */
327 SEL_CDATA_DOMINMAX = 256,
328 /** Whether the subexpression uses simple pass evaluation functions. */
329 SEL_CDATA_SIMPLESUBEXPR = 32,
331 * Whether a static subexpression needs to support multiple evaluations.
333 * This flag may only be set on \ref SEL_SUBEXPR elements that also have
334 * SEL_CDATA_SIMPLESUBEXPR.
336 SEL_CDATA_STATICMULTIEVALSUBEXPR = 64,
337 /** Whether this expression is a part of a common subexpression. */
338 SEL_CDATA_COMMONSUBEXPR = 128
342 * Internal data structure used by the compiler.
344 typedef struct t_compiler_data
346 /** The real evaluation method. */
347 gmx::sel_evalfunc evaluate;
348 /** Number of references to a \ref SEL_SUBEXPR element. */
350 /** Flags for specifying how to treat this element during compilation. */
352 /** Smallest selection that can be selected by the subexpression. */
353 gmx_ana_index_t *gmin;
354 /** Largest selection that can be selected by the subexpression. */
355 gmx_ana_index_t *gmax;
359 /********************************************************************
360 * COMPILER UTILITY FUNCTIONS
361 ********************************************************************/
364 * Helper method for printing out debug information about a min/max group.
367 print_group_info(FILE *fp, const char *name,
368 const SelectionTreeElement &sel,
371 fprintf(fp, " %s=", name);
374 fprintf(fp, "(null)");
376 else if (sel.cdata->flags & SEL_CDATA_MINMAXALLOC)
378 fprintf(fp, "(%d atoms, %p)", g->isize, (void*)g);
380 else if (sel.v.type == GROUP_VALUE && g == sel.v.u.g)
382 fprintf(fp, "(static, %p)", (void*)g);
386 fprintf(fp, "%p", (void*)g);
391 * \param[in] fp File handle to receive the output.
392 * \param[in] sel Selection element to print.
393 * \param[in] level Indentation level, starting from zero.
396 _gmx_selelem_print_compiler_info(FILE *fp, const SelectionTreeElement &sel,
403 fprintf(fp, "%*c cdata: flg=", level*2+1, ' ');
404 if (sel.cdata->flags & SEL_CDATA_FULLEVAL)
408 if (!(sel.cdata->flags & SEL_CDATA_STATIC))
412 if (sel.cdata->flags & SEL_CDATA_STATICEVAL)
416 if (sel.cdata->flags & SEL_CDATA_EVALMAX)
420 if (sel.cdata->flags & SEL_CDATA_MINMAXALLOC)
424 if (sel.cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
428 if (sel.cdata->flags & SEL_CDATA_STATICMULTIEVALSUBEXPR)
432 if (sel.cdata->flags & SEL_CDATA_COMMONSUBEXPR)
436 if (!sel.cdata->flags)
440 if (sel.cdata->refcount > 0)
442 fprintf(fp, " refc=%d", sel.cdata->refcount);
444 fprintf(fp, " eval=");
445 _gmx_sel_print_evalfunc_name(fp, sel.cdata->evaluate);
446 print_group_info(fp, "gmin", sel, sel.cdata->gmin);
447 print_group_info(fp, "gmax", sel, sel.cdata->gmax);
454 void SelectionTreeElement::freeCompilerData()
458 evaluate = cdata->evaluate;
459 if (cdata->flags & SEL_CDATA_MINMAXALLOC)
461 gmx_ana_index_deinit(cdata->gmin);
462 gmx_ana_index_deinit(cdata->gmax);
474 * Allocates memory for storing the evaluated value of a selection element.
476 * \param sel Selection element to initialize
477 * \param[in] isize Maximum evaluation group size.
478 * \param[in] bChildEval true if children have already been processed.
480 * If called more than once, memory is (re)allocated to ensure that the
481 * maximum of the \p isize values can be stored.
483 * Allocation of POS_VALUE selection elements is a special case, and is
484 * handled by alloc_selection_pos_data().
487 alloc_selection_data(const SelectionTreeElementPointer &sel,
488 int isize, bool bChildEval)
492 GMX_RELEASE_ASSERT(sel->v.type != POS_VALUE,
493 "Wrong allocation method called");
498 /* Find out the number of elements to allocate */
499 if (sel->flags & SEL_SINGLEVAL)
503 else if (sel->flags & SEL_ATOMVAL)
507 else /* sel->flags should contain SEL_VARNUMVAL */
509 // TODO: Consider whether the bChildEval is any longer necessary.
514 SelectionTreeElementPointer child = sel;
515 if (sel->type == SEL_SUBEXPRREF)
517 GMX_RELEASE_ASSERT(sel->child && sel->child->type == SEL_SUBEXPR,
518 "Subexpression expected for subexpression reference");
519 child = sel->child->child;
520 GMX_RELEASE_ASSERT(child,
521 "Subexpression elements should always have a child element");
523 nalloc = child->v.nr;
525 /* Allocate memory for sel->v.u if needed */
526 if (sel->flags & SEL_ALLOCVAL)
528 _gmx_selvalue_reserve(&sel->v, nalloc);
530 /* Reserve memory inside group structure if SEL_ALLOCDATA is set. */
531 if ((sel->flags & SEL_ALLOCDATA) && sel->v.type == GROUP_VALUE)
533 gmx_ana_index_reserve(sel->v.u.g, isize);
538 * Allocates memory for storing the evaluated value of a selection element.
540 * \param sel Selection element to initialize.
542 * Allocation of POS_VALUE selection elements is a special case, and is
543 * handled by this function instead of by alloc_selection_data().
546 alloc_selection_pos_data(const SelectionTreeElementPointer &sel)
550 GMX_RELEASE_ASSERT(sel->v.type == POS_VALUE,
551 "Wrong allocation method called");
552 GMX_RELEASE_ASSERT(!(sel->flags & SEL_ATOMVAL),
553 "Per-atom evaluated positions not implemented");
559 SelectionTreeElementPointer child = sel;
560 if (sel->type == SEL_SUBEXPRREF)
562 GMX_RELEASE_ASSERT(sel->child && sel->child->type == SEL_SUBEXPR,
563 "Subexpression expected for subexpression reference");
564 child = sel->child->child;
565 GMX_RELEASE_ASSERT(child,
566 "Subexpression elements should always have a child element");
568 nalloc = child->v.u.p->count();
569 isize = child->v.u.p->m.b.nra;
571 /* For positions, we want to allocate just a single structure
572 * for nalloc positions. */
573 if (sel->flags & SEL_ALLOCVAL)
575 _gmx_selvalue_reserve(&sel->v, 1);
578 /* Reserve memory inside position structure if SEL_ALLOCDATA is set. */
579 if (sel->flags & SEL_ALLOCDATA)
581 gmx_ana_pos_reserve(sel->v.u.p, nalloc, isize);
586 * Replace the evaluation function of each element in the subtree.
588 * \param sel Root of the selection subtree to process.
589 * \param[in] eval The new evaluation function.
592 set_evaluation_function(const SelectionTreeElementPointer &sel,
593 gmx::sel_evalfunc eval)
595 sel->evaluate = eval;
596 if (sel->type != SEL_SUBEXPRREF)
598 SelectionTreeElementPointer child = sel->child;
601 set_evaluation_function(child, eval);
608 /********************************************************************
609 * POSITION KEYWORD DEFAULT INITIALIZATION
610 ********************************************************************/
613 * Initializes default values for position keyword evaluation.
615 * \param[in,out] root Root of the element tree to initialize.
616 * \param[in] spost Default output position type.
617 * \param[in] rpost Default reference position type.
618 * \param[in] sel Selection that the element evaluates the positions
619 * for, or NULL if the element is an internal element.
622 init_pos_keyword_defaults(SelectionTreeElement *root,
623 const char *spost, const char *rpost,
624 const gmx::internal::SelectionData *sel)
626 /* Selections use largest static group by default, while
627 * reference positions use the whole residue/molecule. */
628 if (root->type == SEL_EXPRESSION)
630 bool bSelection = (sel != NULL);
631 int flags = bSelection ? POS_COMPLMAX : POS_COMPLWHOLE;
634 if (sel->hasFlag(gmx::efSelection_DynamicMask))
636 flags |= POS_MASKONLY;
638 if (sel->hasFlag(gmx::efSelection_EvaluateVelocities))
640 flags |= POS_VELOCITIES;
642 if (sel->hasFlag(gmx::efSelection_EvaluateForces))
647 _gmx_selelem_set_kwpos_type(root, bSelection ? spost : rpost);
648 _gmx_selelem_set_kwpos_flags(root, flags);
650 /* Change the defaults once we are no longer processing modifiers */
651 if (root->type != SEL_ROOT && root->type != SEL_MODIFIER
652 && root->type != SEL_SUBEXPRREF && root->type != SEL_SUBEXPR)
656 /* Recurse into children */
657 SelectionTreeElementPointer child = root->child;
660 init_pos_keyword_defaults(child.get(), spost, rpost, sel);
666 /********************************************************************
667 * SUBEXPRESSION PROCESSING
668 ********************************************************************/
671 * Reverses the chain of selection elements starting at \p root.
673 * \param root First selection in the whole selection chain.
674 * \returns The new first element for the chain.
676 static SelectionTreeElementPointer
677 reverse_selelem_chain(const SelectionTreeElementPointer &root)
679 SelectionTreeElementPointer prev;
680 SelectionTreeElementPointer item = root;
683 SelectionTreeElementPointer next = item->next;
692 * Removes subexpressions that don't have any references.
694 * \param root First selection in the whole selection chain.
695 * \returns The new first element for the chain.
697 * The elements are processed in reverse order to correctly detect
698 * subexpressions only referred to by other subexpressions.
700 static SelectionTreeElementPointer
701 remove_unused_subexpressions(SelectionTreeElementPointer root)
705 return SelectionTreeElementPointer();
707 root = reverse_selelem_chain(root);
708 while (root->child->type == SEL_SUBEXPR && root->child.unique())
710 // Frees the root element.
713 SelectionTreeElementPointer prev = root;
714 SelectionTreeElementPointer item = root->next;
717 SelectionTreeElementPointer next = item->next;
718 if (item->child->type == SEL_SUBEXPR && item->child.unique())
720 // Frees the current item when it goes out of scope.
729 return reverse_selelem_chain(root);
733 * Creates a name with a running number for a subexpression.
735 * \param[in,out] sel The subexpression to be named.
736 * \param[in] i Running number for the subexpression.
738 * The name of the selection becomes "SubExpr N", where N is \p i;
739 * Memory is allocated for the name and the name is stored both as the
740 * name of the subexpression element and as
741 * gmx::SelectionTreeElement::u::cgrp::name; the latter is freed by
742 * _gmx_selelem_free().
745 create_subexpression_name(const SelectionTreeElementPointer &sel, int i)
747 std::string name(gmx::formatString("SubExpr %d", i));
752 * Processes and extracts subexpressions from a given selection subtree.
754 * \param sel Root of the subtree to process.
755 * \param subexprn Pointer to a subexpression counter.
756 * \returns Pointer to a chain of subselections, or NULL if none were found.
758 * This function finds recursively all \ref SEL_SUBEXPRREF elements below
759 * the given root element and ensures that their children are within
760 * \ref SEL_SUBEXPR elements. It also creates a chain of \ref SEL_ROOT elements
761 * that contain the subexpression as their children and returns the first
762 * of these root elements.
764 static SelectionTreeElementPointer
765 extract_item_subselections(const SelectionTreeElementPointer &sel,
768 SelectionTreeElementPointer root;
769 SelectionTreeElementPointer subexpr;
770 SelectionTreeElementPointer child = sel->child;
776 root = subexpr = extract_item_subselections(child, subexprn);
780 subexpr->next = extract_item_subselections(child, subexprn);
782 while (subexpr && subexpr->next)
784 subexpr = subexpr->next;
786 /* The latter check excludes variable references. */
787 if (child->type == SEL_SUBEXPRREF && child->child->type != SEL_SUBEXPR)
789 /* Create the root element for the subexpression */
792 root.reset(new SelectionTreeElement(SEL_ROOT));
797 subexpr->next.reset(new SelectionTreeElement(SEL_ROOT));
798 subexpr = subexpr->next;
800 /* Create the subexpression element and
801 * move the actual subexpression under the created element. */
802 subexpr->child.reset(new SelectionTreeElement(SEL_SUBEXPR));
803 _gmx_selelem_set_vtype(subexpr->child, child->v.type);
804 subexpr->child->child = child->child;
805 child->child = subexpr->child;
806 create_subexpression_name(subexpr->child, ++*subexprn);
807 /* Set the flags for the created elements */
808 subexpr->flags |= (child->flags & SEL_VALFLAGMASK);
809 subexpr->child->flags |= (child->flags & SEL_VALFLAGMASK);
811 if (child->type == SEL_SUBEXPRREF)
813 child->setName(child->child->name());
822 * Extracts subexpressions of the selection chain.
824 * \param sel First selection in the whole selection chain.
825 * \returns The new first element for the chain.
827 * Finds all the subexpressions (and their subexpressions) in the
828 * selection chain starting from \p sel and creates \ref SEL_SUBEXPR
830 * \ref SEL_ROOT elements are also created for each subexpression
831 * and inserted into the selection chain before the expressions that
834 static SelectionTreeElementPointer
835 extract_subexpressions(SelectionTreeElementPointer sel)
837 SelectionTreeElementPointer root;
838 SelectionTreeElementPointer next = sel;
842 SelectionTreeElementPointer item
843 = extract_item_subselections(next, &subexprn);
871 /********************************************************************
872 * BOOLEAN OPERATION REORDERING
873 ********************************************************************/
876 * Removes redundant boolean selection elements.
878 * \param sel Root of the selection subtree to optimize.
880 * This function merges similar boolean operations (e.g., (A or B) or C becomes
881 * a single OR operation with three operands).
884 optimize_boolean_expressions(const SelectionTreeElementPointer &sel)
886 /* Do recursively for children */
887 if (sel->type != SEL_SUBEXPRREF)
889 SelectionTreeElementPointer prev;
890 SelectionTreeElementPointer child = sel->child;
893 optimize_boolean_expressions(child);
894 /* Remove double negations */
895 if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT
896 && child->child->type == SEL_BOOLEAN && child->child->u.boolt == BOOL_NOT)
898 /* Move the doubly negated expression up two levels */
901 sel->child = child->child->child;
906 prev->next = child->child->child;
909 child->child->child->next = child->next;
910 // Discards the two negations.
917 if (sel->type != SEL_BOOLEAN || sel->u.boolt == BOOL_NOT)
921 /* Merge subsequent binary operations */
922 SelectionTreeElementPointer prev;
923 SelectionTreeElementPointer child = sel->child;
926 if (child->type == SEL_BOOLEAN && child->u.boolt == sel->u.boolt)
930 sel->child = child->child;
935 prev->next = child->child;
941 prev->next = child->next;
942 // Discards the old child.
954 * Reorders children of boolean expressions such that static selections
957 * \param sel Root of the selection subtree to reorder.
959 * The relative order of static expressions does not change.
960 * The same is true for the dynamic expressions.
963 reorder_boolean_static_children(const SelectionTreeElementPointer &sel)
965 /* Do recursively for children */
966 if (sel->type != SEL_SUBEXPRREF)
968 SelectionTreeElementPointer child = sel->child;
971 reorder_boolean_static_children(child);
976 /* Reorder boolean expressions such that static selections come first */
977 if (sel->type == SEL_BOOLEAN && (sel->flags & SEL_DYNAMIC))
979 // Add a dummy head element that precedes the first child.
980 SelectionTreeElementPointer dummy(
981 new SelectionTreeElement(SEL_BOOLEAN));
982 dummy->next = sel->child;
983 SelectionTreeElementPointer prev = dummy;
984 SelectionTreeElementPointer child = dummy;
987 /* child is the last handled static expression */
988 /* prev is the last handled non-static expression */
989 SelectionTreeElementPointer next = prev->next;
990 while (next && (next->flags & SEL_DYNAMIC))
995 /* next is now the first static expression after child */
1000 /* Reorder such that next comes after child */
1003 prev->next = next->next;
1004 next->next = child->next;
1011 /* Advance child by one */
1015 sel->child = dummy->next;
1020 /********************************************************************
1021 * ARITHMETIC EXPRESSION PROCESSING
1022 ********************************************************************/
1025 * Processes arithmetic expressions to simplify and speed up evaluation.
1027 * \param sel Root of the selection subtree to process.
1029 * Currently, this function only converts integer constants to reals
1030 * within arithmetic expressions.
1033 optimize_arithmetic_expressions(const SelectionTreeElementPointer &sel)
1035 /* Do recursively for children. */
1036 if (sel->type != SEL_SUBEXPRREF)
1038 SelectionTreeElementPointer child = sel->child;
1041 optimize_arithmetic_expressions(child);
1042 child = child->next;
1046 if (sel->type != SEL_ARITHMETIC)
1051 /* Convert integer constants to reals. */
1052 SelectionTreeElementPointer child = sel->child;
1055 if (child->v.type == INT_VALUE)
1059 if (child->type != SEL_CONST)
1061 GMX_THROW(gmx::InconsistentInputError("Non-constant integer expressions not implemented in arithmetic evaluation"));
1064 r[0] = child->v.u.i[0];
1065 sfree(child->v.u.i);
1067 child->v.type = REAL_VALUE;
1069 else if (child->v.type != REAL_VALUE)
1071 GMX_THROW(gmx::InternalError("Non-numerical value in arithmetic expression"));
1073 child = child->next;
1078 /********************************************************************
1079 * EVALUATION PREPARATION COMPILER
1080 ********************************************************************/
1083 * Sets the evaluation functions for the selection (sub)tree.
1085 * \param[in,out] sel Root of the selection subtree to process.
1087 * This function sets the evaluation function
1088 * (gmx::SelectionTreeElement::evaluate) for the selection elements.
1091 init_item_evalfunc(const SelectionTreeElementPointer &sel)
1093 /* Process children. */
1094 if (sel->type != SEL_SUBEXPRREF)
1096 SelectionTreeElementPointer child = sel->child;
1099 init_item_evalfunc(child);
1100 child = child->next;
1104 /* Set the evaluation function */
1108 if (sel->v.type == GROUP_VALUE)
1110 sel->evaluate = &_gmx_sel_evaluate_static;
1114 case SEL_EXPRESSION:
1115 if (!(sel->flags & SEL_DYNAMIC) && sel->u.expr.method
1116 && sel->u.expr.method->init_frame)
1118 sel->flags |= SEL_INITFRAME;
1120 sel->evaluate = &_gmx_sel_evaluate_method;
1123 case SEL_ARITHMETIC:
1124 sel->evaluate = &_gmx_sel_evaluate_arithmetic;
1128 if (sel->v.type != NO_VALUE)
1130 sel->evaluate = &_gmx_sel_evaluate_modifier;
1135 switch (sel->u.boolt)
1137 case BOOL_NOT: sel->evaluate = &_gmx_sel_evaluate_not; break;
1138 case BOOL_AND: sel->evaluate = &_gmx_sel_evaluate_and; break;
1139 case BOOL_OR: sel->evaluate = &_gmx_sel_evaluate_or; break;
1141 GMX_THROW(gmx::NotImplementedError("xor expressions not implemented"));
1146 sel->evaluate = &_gmx_sel_evaluate_root;
1150 if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
1151 && !(sel->cdata->flags & SEL_CDATA_STATICMULTIEVALSUBEXPR))
1153 sel->evaluate = &_gmx_sel_evaluate_subexpr_simple;
1157 sel->evaluate = &_gmx_sel_evaluate_subexpr;
1161 case SEL_SUBEXPRREF:
1162 sel->evaluate = ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
1163 ? &_gmx_sel_evaluate_subexprref_simple
1164 : &_gmx_sel_evaluate_subexprref);
1168 GMX_THROW(gmx::APIError("Unresolved group reference in compilation"));
1170 sel->cdata->evaluate = sel->evaluate;
1174 * Sets the memory pool for selection elements that can use it.
1176 * \param sel Root of the selection subtree to process.
1177 * \param[in] mempool Memory pool to use.
1180 setup_memory_pooling(const SelectionTreeElementPointer &sel,
1181 gmx_sel_mempool_t *mempool)
1183 if (sel->type != SEL_SUBEXPRREF)
1185 SelectionTreeElementPointer child = sel->child;
1188 if ((sel->type == SEL_BOOLEAN && (child->flags & SEL_DYNAMIC))
1189 || (sel->type == SEL_ARITHMETIC && child->type != SEL_CONST
1190 && !(child->flags & SEL_SINGLEVAL))
1191 || (sel->type == SEL_SUBEXPR
1192 && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)))
1194 child->mempool = mempool;
1195 if (child->type == SEL_SUBEXPRREF
1196 && (child->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
1198 child->child->child->mempool = mempool;
1201 setup_memory_pooling(child, mempool);
1202 child = child->next;
1208 * Prepares the selection (sub)tree for evaluation.
1210 * \param[in,out] sel Root of the selection subtree to prepare.
1212 * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
1213 * structure if required.
1216 init_item_evaloutput(const SelectionTreeElementPointer &sel)
1218 GMX_ASSERT(!(sel->child == NULL &&
1219 (sel->type == SEL_SUBEXPRREF || sel->type == SEL_SUBEXPR)),
1220 "Subexpression elements should always have a child element");
1222 /* Process children. */
1223 if (sel->type != SEL_SUBEXPRREF)
1225 SelectionTreeElementPointer child = sel->child;
1228 init_item_evaloutput(child);
1229 child = child->next;
1233 if (sel->type == SEL_SUBEXPR
1234 && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
1235 && !(sel->cdata->flags & SEL_CDATA_STATICMULTIEVALSUBEXPR))
1237 sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1238 if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1240 _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
1243 else if (sel->type == SEL_SUBEXPR
1244 && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
1246 sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
1247 sel->cdata->evaluate = sel->evaluate;
1248 sel->child->mempool = NULL;
1249 sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1250 if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1252 _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
1255 else if (sel->type == SEL_SUBEXPRREF
1256 && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
1260 _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
1261 sel->child->child->freeValues();
1262 sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1263 sel->child->child->flags |= (sel->flags & SEL_ALLOCDATA);
1264 _gmx_selvalue_setstore(&sel->child->child->v, sel->v.u.ptr);
1266 else if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1268 _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
1270 sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1273 /* Make sure that the group/position structure is allocated. */
1274 if (!sel->v.u.ptr && (sel->flags & SEL_ALLOCVAL))
1276 if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1278 _gmx_selvalue_reserve(&sel->v, 1);
1285 /********************************************************************
1286 * COMPILER DATA INITIALIZATION
1287 ********************************************************************/
1290 * Allocates memory for the compiler data and initializes the structure.
1292 * \param sel Root of the selection subtree to process.
1295 init_item_compilerdata(const SelectionTreeElementPointer &sel)
1297 /* Allocate the compiler data structure */
1298 snew(sel->cdata, 1);
1300 /* Store the real evaluation method because the compiler will replace it */
1301 sel->cdata->evaluate = sel->evaluate;
1303 /* This will be computed separately. */
1304 sel->cdata->refcount = 0;
1306 /* Initialize the flags */
1307 sel->cdata->flags = SEL_CDATA_STATICEVAL;
1308 if (!(sel->flags & SEL_DYNAMIC))
1310 sel->cdata->flags |= SEL_CDATA_STATIC;
1312 if (sel->type == SEL_SUBEXPR)
1314 sel->cdata->flags |= SEL_CDATA_EVALMAX;
1316 /* Set the full evaluation flag for subexpressions that require it;
1317 * the subexpression has already been initialized, so we can simply
1318 * access its compilation flags.*/
1319 if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
1321 SelectionTreeElementPointer child = sel->child;
1324 if (!(child->flags & SEL_ATOMVAL) && child->child)
1326 child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
1328 child = child->next;
1331 else if (sel->type == SEL_ROOT && sel->child->type == SEL_SUBEXPRREF)
1333 sel->child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
1336 /* Initialize children */
1337 if (sel->type != SEL_SUBEXPRREF)
1339 SelectionTreeElementPointer child = sel->child;
1342 init_item_compilerdata(child);
1343 child = child->next;
1347 /* Determine whether we should evaluate the minimum or the maximum
1348 * for the children of this element. */
1349 if (sel->type == SEL_BOOLEAN)
1353 bEvalMax = (sel->u.boolt == BOOL_AND);
1354 SelectionTreeElementPointer child = sel->child;
1359 child->cdata->flags |= SEL_CDATA_EVALMAX;
1361 else if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT)
1363 child->child->cdata->flags |= SEL_CDATA_EVALMAX;
1365 child = child->next;
1368 else if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER
1369 || sel->type == SEL_SUBEXPR)
1371 SelectionTreeElementPointer child = sel->child;
1374 child->cdata->flags |= SEL_CDATA_EVALMAX;
1375 child = child->next;
1381 * Initializes the static evaluation flag for a selection subtree.
1383 * \param[in,out] sel Root of the selection subtree to process.
1385 * Sets the \c bStaticEval in the compiler data structure:
1386 * for any element for which the evaluation group may depend on the trajectory
1387 * frame, the flag is cleared.
1389 * reorder_boolean_static_children() should have been called.
1392 init_item_staticeval(const SelectionTreeElementPointer &sel)
1394 /* Subexpressions with full evaluation should always have bStaticEval,
1395 * so don't do anything if a reference to them is encountered. */
1396 if (sel->type == SEL_SUBEXPRREF
1397 && (sel->child->cdata->flags & SEL_CDATA_FULLEVAL))
1402 /* Propagate the bStaticEval flag to children if it is not set */
1403 if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
1405 SelectionTreeElementPointer child = sel->child;
1408 if ((sel->type != SEL_EXPRESSION && sel->type != SEL_MODIFIER)
1409 || (child->flags & SEL_ATOMVAL))
1411 if (child->cdata->flags & SEL_CDATA_STATICEVAL)
1413 child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
1414 init_item_staticeval(child);
1417 /* If an expression is evaluated for a dynamic group, then also
1418 * atom-valued parameters need to be evaluated every time. */
1419 if ((sel->flags & SEL_DYNAMIC)
1420 && (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
1421 && (child->flags & SEL_ATOMVAL))
1423 child->flags |= SEL_DYNAMIC;
1424 child->cdata->flags &= ~SEL_CDATA_STATIC;
1426 child = child->next;
1429 else /* bStaticEval is set */
1431 /* For boolean expressions, any expression after the first dynamic
1432 * expression should not have bStaticEval. */
1433 if (sel->type == SEL_BOOLEAN)
1435 SelectionTreeElementPointer child = sel->child;
1436 while (child && !(child->flags & SEL_DYNAMIC))
1438 child = child->next;
1442 child = child->next;
1446 child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
1447 child = child->next;
1451 /* Process the children */
1452 SelectionTreeElementPointer child = sel->child;
1455 init_item_staticeval(child);
1456 child = child->next;
1462 * Compute reference counts for subexpressions.
1464 * \param sel Root of the selection subtree to process.
1467 init_item_subexpr_refcount(const SelectionTreeElementPointer &sel)
1469 // Reset the counter when the subexpression is first encountered.
1470 if (sel->type == SEL_ROOT && sel->child->type == SEL_SUBEXPR
1471 && sel->child->cdata)
1473 sel->child->cdata->refcount = 0;
1476 if (sel->type == SEL_SUBEXPRREF)
1478 ++sel->child->cdata->refcount;
1482 SelectionTreeElementPointer child = sel->child;
1485 init_item_subexpr_refcount(child);
1486 child = child->next;
1492 * Initializes compiler flags for subexpressions.
1494 * \param sel Root of the selection subtree to process.
1497 init_item_subexpr_flags(const SelectionTreeElementPointer &sel)
1499 if (sel->type == SEL_SUBEXPR)
1501 if (sel->cdata->refcount == 1)
1503 sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
1505 else if (!(sel->cdata->flags & SEL_CDATA_FULLEVAL))
1507 sel->cdata->flags |= SEL_CDATA_COMMONSUBEXPR;
1510 else if (sel->type == SEL_SUBEXPRREF
1511 && (sel->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
1513 /* See similar condition in init_item_staticeval(). */
1514 if ((sel->flags & SEL_ATOMVAL)
1515 && (sel->flags & SEL_DYNAMIC)
1516 && !(sel->child->flags & SEL_DYNAMIC))
1518 sel->child->cdata->flags |= SEL_CDATA_STATICMULTIEVALSUBEXPR;
1522 sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
1526 /* Process children, but only follow subexpression references if the
1527 * common subexpression flag needs to be propagated. */
1528 if (sel->type != SEL_SUBEXPRREF
1529 || ((sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
1530 && !(sel->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)))
1532 SelectionTreeElementPointer child = sel->child;
1535 if (!(child->cdata->flags & SEL_CDATA_COMMONSUBEXPR))
1537 if (sel->type != SEL_EXPRESSION || (child->flags & SEL_ATOMVAL))
1539 child->cdata->flags |=
1540 (sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR);
1542 init_item_subexpr_flags(child);
1544 child = child->next;
1550 * Initializes the gmin and gmax fields of the compiler data structure.
1552 * \param sel Root of the selection subtree to process.
1555 init_item_minmax_groups(const SelectionTreeElementPointer &sel)
1557 /* Process children. */
1558 if (sel->type != SEL_SUBEXPRREF)
1560 SelectionTreeElementPointer child = sel->child;
1563 init_item_minmax_groups(child);
1564 child = child->next;
1568 /* Initialize the minimum and maximum evaluation groups. */
1569 if (sel->type != SEL_ROOT && sel->v.type != NO_VALUE)
1571 if (sel->v.type == GROUP_VALUE
1572 && (sel->cdata->flags & SEL_CDATA_STATIC))
1574 sel->cdata->gmin = sel->v.u.g;
1575 sel->cdata->gmax = sel->v.u.g;
1577 else if (sel->type == SEL_SUBEXPR
1578 && ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
1579 || (sel->cdata->flags & SEL_CDATA_FULLEVAL)))
1581 GMX_ASSERT(sel->child,
1582 "Subexpression elements should always have a child element");
1583 sel->cdata->gmin = sel->child->cdata->gmin;
1584 sel->cdata->gmax = sel->child->cdata->gmax;
1588 sel->cdata->flags |= SEL_CDATA_MINMAXALLOC | SEL_CDATA_DOMINMAX;
1589 snew(sel->cdata->gmin, 1);
1590 snew(sel->cdata->gmax, 1);
1596 /********************************************************************
1597 * EVALUATION GROUP INITIALIZATION
1598 ********************************************************************/
1601 * Initializes evaluation groups for root items.
1603 * \param[in,out] sc Selection collection data.
1605 * The evaluation group of each \ref SEL_ROOT element corresponding to a
1606 * selection in \p sc is set to NULL. The evaluation group for \ref SEL_ROOT
1607 * elements corresponding to subexpressions that need full evaluation is set
1611 initialize_evalgrps(gmx_ana_selcollection_t *sc)
1613 SelectionTreeElementPointer root = sc->root;
1616 GMX_RELEASE_ASSERT(root->child,
1617 "Root elements should always have a child");
1618 if (root->child->type != SEL_SUBEXPR
1619 || (root->child->v.type != GROUP_VALUE && !(root->flags & SEL_ATOMVAL)))
1621 gmx_ana_index_set(&root->u.cgrp, -1, 0, 0);
1623 else if (root->child->cdata->flags & SEL_CDATA_FULLEVAL)
1625 gmx_ana_index_set(&root->u.cgrp, sc->gall.isize, sc->gall.index, 0);
1632 /********************************************************************
1634 ********************************************************************/
1637 * Marks a subtree completely dynamic or undoes such a change.
1639 * \param sel Selection subtree to mark.
1640 * \param[in] bDynamic If true, the \p bStatic flag of the whole
1641 * selection subtree is cleared. If false, the flag is restored to
1642 * using \ref SEL_DYNAMIC.
1644 * Does not descend into parameters of methods unless the parameters
1645 * are evaluated for each atom.
1648 mark_subexpr_dynamic(const SelectionTreeElementPointer &sel,
1651 if (!bDynamic && !(sel->flags & SEL_DYNAMIC))
1653 sel->cdata->flags |= SEL_CDATA_STATIC;
1657 sel->cdata->flags &= ~SEL_CDATA_STATIC;
1659 SelectionTreeElementPointer child = sel->child;
1662 if (sel->type != SEL_EXPRESSION || child->type != SEL_SUBEXPRREF
1663 || (child->u.param->flags & SPAR_ATOMVAL))
1665 mark_subexpr_dynamic(child, bDynamic);
1667 child = child->next;
1672 * Frees memory for subexpressions that are no longer needed.
1674 * \param sel Selection subtree to check.
1676 * Checks whether the subtree rooted at \p sel refers to any \ref SEL_SUBEXPR
1677 * elements that are not referred to by anything else except their own root
1678 * element. If such elements are found, all memory allocated for them is freed
1679 * except the actual element. The element is left because otherwise a dangling
1680 * pointer would be left at the root element, which is not traversed by this
1681 * function. Later compilation passes remove the stub elements.
1684 release_subexpr_memory(const SelectionTreeElementPointer &sel)
1686 if (sel->type == SEL_SUBEXPRREF)
1688 const SelectionTreeElementPointer &subexpr = sel->child;
1689 if (subexpr.use_count() == 2)
1691 release_subexpr_memory(subexpr);
1693 subexpr->child.reset();
1694 subexpr->freeValues();
1695 subexpr->freeExpressionData();
1696 subexpr->freeCompilerData();
1701 SelectionTreeElementPointer child = sel->child;
1704 release_subexpr_memory(child);
1705 child = child->next;
1711 * Makes an evaluated selection element static.
1713 * \param sel Selection element to make static.
1715 * The evaluated value becomes the value of the static element.
1716 * The element type is changed to SEL_CONST and the children are
1720 make_static(const SelectionTreeElementPointer &sel)
1722 /* If this is a subexpression reference and the data is stored in the
1723 * child, we transfer data ownership before doing anything else. */
1724 if (sel->type == SEL_SUBEXPRREF
1725 && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
1727 if (sel->child->child->flags & SEL_ALLOCDATA)
1729 sel->flags |= SEL_ALLOCDATA;
1730 sel->child->child->flags &= ~SEL_ALLOCDATA;
1732 if (sel->child->child->flags & SEL_ALLOCVAL)
1734 sel->flags |= SEL_ALLOCVAL;
1735 sel->v.nalloc = sel->child->child->v.nalloc;
1736 sel->child->child->flags &= ~SEL_ALLOCVAL;
1737 sel->child->child->v.nalloc = -1;
1740 /* Free the children. */
1741 release_subexpr_memory(sel);
1743 /* Free the expression data as it is no longer needed */
1744 sel->freeExpressionData();
1745 /* Make the item static */
1746 sel->type = SEL_CONST;
1747 sel->evaluate = NULL;
1748 sel->cdata->evaluate = NULL;
1749 /* Set the group value.
1750 * freeExpressionData() frees the cgrp group, so we can just override it.
1752 if (sel->v.type == GROUP_VALUE)
1754 gmx_ana_index_set(&sel->u.cgrp, sel->v.u.g->isize, sel->v.u.g->index, 0);
1759 * Evaluates a constant expression during analyze_static().
1761 * \param[in] data Evaluation data.
1762 * \param[in,out] sel Selection to process.
1763 * \param[in] g The evaluation group.
1764 * \returns 0 on success, a non-zero error code on error.
1767 process_const(gmx_sel_evaluate_t *data,
1768 const SelectionTreeElementPointer &sel,
1771 if (sel->v.type == GROUP_VALUE)
1773 if (sel->cdata->evaluate)
1775 sel->cdata->evaluate(data, sel, g);
1778 /* Other constant expressions do not need evaluation */
1782 * Sets the parameter value pointer for \ref SEL_SUBEXPRREF params.
1784 * \param[in,out] sel Selection to process.
1786 * Copies the value pointer of \p sel to \c sel->u.param if one is present
1787 * and should receive the value from the compiler
1788 * (most parameter values are handled during parsing).
1789 * If \p sel is not of type \ref SEL_SUBEXPRREF, or if \c sel->u.param is NULL,
1790 * the function does nothing.
1791 * Also, if the \c sel->u.param does not have \ref SPAR_VARNUM or
1792 * \ref SPAR_ATOMVAL, the function returns immediately.
1795 store_param_val(const SelectionTreeElementPointer &sel)
1797 /* Return immediately if there is no parameter. */
1798 if (sel->type != SEL_SUBEXPRREF || !sel->u.param)
1803 /* Or if the value does not need storing. */
1804 if (!(sel->u.param->flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
1809 if (sel->v.type == INT_VALUE || sel->v.type == REAL_VALUE
1810 || sel->v.type == STR_VALUE)
1812 _gmx_selvalue_setstore(&sel->u.param->val, sel->v.u.ptr);
1817 * Handles the initialization of a selection method during analyze_static() pass.
1819 * \param[in,out] sel Selection element to process.
1820 * \param[in] top Topology structure.
1821 * \param[in] isize Size of the evaluation group for the element.
1822 * \returns 0 on success, a non-zero error code on return.
1824 * Calls sel_initfunc() (and possibly sel_outinitfunc()) to initialize the
1826 * If no \ref SPAR_ATOMVAL parameters are present, multiple initialization
1827 * is prevented by using \ref SEL_METHODINIT and \ref SEL_OUTINIT flags.
1830 init_method(const SelectionTreeElementPointer &sel, t_topology *top, int isize)
1832 /* Find out whether there are any atom-valued parameters */
1833 bool bAtomVal = false;
1834 SelectionTreeElementPointer child = sel->child;
1837 if (child->flags & SEL_ATOMVAL)
1841 child = child->next;
1844 /* Initialize the method */
1845 if (sel->u.expr.method->init
1846 && (bAtomVal || !(sel->flags & SEL_METHODINIT)))
1848 sel->flags |= SEL_METHODINIT;
1849 sel->u.expr.method->init(top, sel->u.expr.method->nparams,
1850 sel->u.expr.method->param, sel->u.expr.mdata);
1852 if (bAtomVal || !(sel->flags & SEL_OUTINIT))
1854 sel->flags |= SEL_OUTINIT;
1855 if (sel->u.expr.method->outinit)
1857 sel->u.expr.method->outinit(top, &sel->v, sel->u.expr.mdata);
1858 if (sel->v.type != POS_VALUE && sel->v.type != GROUP_VALUE
1859 && !(sel->flags & SEL_VARNUMVAL))
1861 alloc_selection_data(sel, isize, true);
1866 GMX_RELEASE_ASSERT(sel->v.type != POS_VALUE,
1867 "Output initialization must be provided for "
1868 "position-valued selection methods");
1869 GMX_RELEASE_ASSERT(!(sel->flags & SEL_VARNUMVAL),
1870 "Output initialization must be provided for "
1871 "SMETH_VARNUMVAL selection methods");
1872 alloc_selection_data(sel, isize, true);
1873 if ((sel->flags & SEL_DYNAMIC)
1874 && sel->v.type != GROUP_VALUE && sel->v.type != POS_VALUE)
1878 /* If the method is char-valued, pre-allocate the strings. */
1879 if (sel->u.expr.method->flags & SMETH_CHARVAL)
1883 /* A sanity check */
1884 if (sel->v.type != STR_VALUE)
1886 GMX_THROW(gmx::InternalError("Char-valued selection method in non-string element"));
1888 sel->flags |= SEL_ALLOCDATA;
1889 for (i = 0; i < isize; ++i)
1891 if (sel->v.u.s[i] == NULL)
1893 snew(sel->v.u.s[i], 2);
1898 /* Clear the values for dynamic output to avoid valgrind warnings. */
1899 if ((sel->flags & SEL_DYNAMIC) && sel->v.type == REAL_VALUE)
1903 for (i = 0; i < sel->v.nr; ++i)
1905 sel->v.u.r[i] = 0.0;
1912 * Evaluates the static part of a boolean expression.
1914 * \param[in] data Evaluation data.
1915 * \param[in,out] sel Boolean selection element whose children should be
1917 * \param[in] g The evaluation group.
1918 * \returns 0 on success, a non-zero error code on error.
1920 * reorder_item_static_children() should have been called.
1923 evaluate_boolean_static_part(gmx_sel_evaluate_t *data,
1924 const SelectionTreeElementPointer &sel,
1927 /* Find the last static subexpression */
1928 SelectionTreeElementPointer child = sel->child;
1929 while (child->next && (child->next->cdata->flags & SEL_CDATA_STATIC))
1931 child = child->next;
1933 if (!(child->cdata->flags & SEL_CDATA_STATIC))
1938 /* Evalute the static part if there is more than one expression */
1939 if (child != sel->child)
1941 SelectionTreeElementPointer next = child->next;
1942 child->next.reset();
1943 sel->cdata->evaluate(data, sel, g);
1944 /* Replace the subexpressions with the result */
1945 child.reset(new SelectionTreeElement(SEL_CONST));
1946 child->flags = SEL_FLAGSSET | SEL_SINGLEVAL | SEL_ALLOCVAL | SEL_ALLOCDATA;
1947 _gmx_selelem_set_vtype(child, GROUP_VALUE);
1948 child->evaluate = NULL;
1949 _gmx_selvalue_reserve(&child->v, 1);
1950 gmx_ana_index_copy(child->v.u.g, sel->v.u.g, true);
1951 init_item_compilerdata(child);
1952 init_item_minmax_groups(child);
1953 child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
1954 child->cdata->flags |= sel->cdata->flags & SEL_CDATA_STATICEVAL;
1956 // Frees the old static subexpressions.
1959 else if (child->evaluate)
1961 child->evaluate(data, child, g);
1963 /* Set the evaluation function for the constant element.
1964 * We never need to evaluate the element again during compilation,
1965 * but we may need to evaluate the static part again if the
1966 * expression is not an OR with a static evaluation group.
1967 * If we reach here with a NOT expression, the NOT expression
1968 * is also static, and will be made a constant later, so don't waste
1969 * time copying the group. */
1970 child->evaluate = NULL;
1971 if (sel->u.boolt == BOOL_NOT
1972 || ((sel->cdata->flags & SEL_CDATA_STATICEVAL)
1973 && sel->u.boolt == BOOL_OR))
1975 child->cdata->evaluate = NULL;
1979 child->cdata->evaluate = &_gmx_sel_evaluate_static;
1980 /* The cgrp has only been allocated if it originated from an
1981 * external index group.
1982 * If cgrp has been set in make_static(), it is not allocated,
1983 * and hence we can overwrite it safely. */
1984 if (child->u.cgrp.nalloc_index > 0)
1986 gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, false);
1987 gmx_ana_index_squeeze(&child->u.cgrp);
1991 gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, true);
1997 * Evaluates the minimum and maximum groups for a boolean expression.
1999 * \param[in] sel \ref SEL_BOOLEAN element currently being evaluated.
2000 * \param[in] g Group for which \p sel has been evaluated.
2001 * \param[out] gmin Largest subset of the possible values of \p sel.
2002 * \param[out] gmax Smallest superset of the possible values of \p sel.
2004 * This is a helper function for analyze_static() that is called for
2005 * dynamic \ref SEL_BOOLEAN elements after they have been evaluated.
2006 * It uses the minimum and maximum groups of the children to calculate
2007 * the minimum and maximum groups for \p sel, and also updates the static
2008 * part of \p sel (which is in the first child) if the children give
2011 * This function may allocate some extra memory for \p gmin and \p gmax,
2012 * but as these groups are freed at the end of analyze_static() (which is
2013 * reached shortly after this function returns), this should not be a major
2017 evaluate_boolean_minmax_grps(const SelectionTreeElementPointer &sel,
2019 gmx_ana_index_t *gmin, gmx_ana_index_t *gmax)
2021 SelectionTreeElementPointer child;
2023 switch (sel->u.boolt)
2026 gmx_ana_index_reserve(gmin, g->isize);
2027 gmx_ana_index_reserve(gmax, g->isize);
2028 gmx_ana_index_difference(gmax, g, sel->child->cdata->gmin);
2029 gmx_ana_index_difference(gmin, g, sel->child->cdata->gmax);
2033 gmx_ana_index_copy(gmin, sel->child->cdata->gmin, true);
2034 gmx_ana_index_copy(gmax, sel->child->cdata->gmax, true);
2035 child = sel->child->next;
2036 while (child && gmax->isize > 0)
2038 gmx_ana_index_intersection(gmin, gmin, child->cdata->gmin);
2039 gmx_ana_index_intersection(gmax, gmax, child->cdata->gmax);
2040 child = child->next;
2042 /* Update the static part if other expressions limit it */
2043 if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
2044 && sel->child->v.u.g->isize > gmax->isize)
2046 gmx_ana_index_copy(sel->child->v.u.g, gmax, false);
2047 gmx_ana_index_squeeze(sel->child->v.u.g);
2048 if (sel->child->u.cgrp.isize > 0)
2050 gmx_ana_index_copy(&sel->child->u.cgrp, gmax, false);
2051 gmx_ana_index_squeeze(&sel->child->u.cgrp);
2057 /* We can assume here that the gmin of children do not overlap
2058 * because of the way _gmx_sel_evaluate_or() works. */
2059 gmx_ana_index_reserve(gmin, g->isize);
2060 gmx_ana_index_reserve(gmax, g->isize);
2061 gmx_ana_index_copy(gmin, sel->child->cdata->gmin, false);
2062 gmx_ana_index_copy(gmax, sel->child->cdata->gmax, false);
2063 child = sel->child->next;
2064 while (child && gmin->isize < g->isize)
2066 gmx_ana_index_merge(gmin, gmin, child->cdata->gmin);
2067 gmx_ana_index_union(gmax, gmax, child->cdata->gmax);
2068 child = child->next;
2070 /* Update the static part if other expressions have static parts
2071 * that are not included. */
2072 if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
2073 && sel->child->v.u.g->isize < gmin->isize)
2075 GMX_RELEASE_ASSERT(sel->child->type == SEL_CONST,
2076 "The first child should have already been evaluated "
2077 "to a constant expression");
2078 gmx_ana_index_reserve(sel->child->v.u.g, gmin->isize);
2079 gmx_ana_index_copy(sel->child->v.u.g, gmin, false);
2080 if (sel->child->u.cgrp.nalloc_index > 0)
2082 gmx_ana_index_reserve(&sel->child->u.cgrp, gmin->isize);
2083 gmx_ana_index_copy(&sel->child->u.cgrp, gmin, false);
2087 GMX_RELEASE_ASSERT(sel->child->u.cgrp.index == sel->child->v.u.g->index,
2088 "If not allocated, the static group should equal the value");
2089 sel->child->u.cgrp.isize = sel->child->v.u.g->isize;
2094 case BOOL_XOR: /* Should not be reached */
2095 GMX_THROW(gmx::NotImplementedError("xor expressions not implemented"));
2101 * Evaluates the static parts of \p sel and analyzes the structure.
2103 * \param[in] data Evaluation data.
2104 * \param[in,out] sel Selection currently being evaluated.
2105 * \param[in] g Group for which \p sel should be evaluated.
2106 * \returns 0 on success, a non-zero error code on error.
2108 * This function is used as the replacement for the
2109 * gmx::SelectionTreeElement::evaluate function pointer.
2110 * It does the single most complex task in the compiler: after all elements
2111 * have been processed, the \p gmin and \p gmax fields of \p t_compiler_data
2112 * have been properly initialized, enough memory has been allocated for
2113 * storing the value of each expression, and the static parts of the
2114 * expressions have been evaluated.
2115 * The above is exactly true only for elements other than subexpressions:
2116 * another pass is required for subexpressions that are referred to more than
2117 * once and whose evaluation group is not known in advance.
2120 analyze_static(gmx_sel_evaluate_t *data,
2121 const SelectionTreeElementPointer &sel,
2126 if (sel->type != SEL_ROOT && g)
2128 alloc_selection_data(sel, g->isize, false);
2131 bDoMinMax = (sel->cdata->flags & SEL_CDATA_DOMINMAX);
2132 if (sel->type != SEL_SUBEXPR && bDoMinMax)
2134 gmx_ana_index_deinit(sel->cdata->gmin);
2135 gmx_ana_index_deinit(sel->cdata->gmax);
2138 /* TODO: This switch is awfully long... */
2142 process_const(data, sel, g);
2145 case SEL_EXPRESSION:
2147 _gmx_sel_evaluate_method_params(data, sel, g);
2148 init_method(sel, data->top, g ? g->isize : 0);
2149 if (!(sel->flags & SEL_DYNAMIC))
2151 sel->cdata->evaluate(data, sel, g);
2152 if (sel->cdata->flags & SEL_CDATA_STATIC)
2159 /* Modifiers need to be evaluated even though they process
2160 * positions to get the modified output groups from the
2161 * maximum possible selections. */
2162 if (sel->type == SEL_MODIFIER)
2164 sel->cdata->evaluate(data, sel, g);
2168 gmx_ana_index_copy(sel->cdata->gmax, g, true);
2174 if (!(sel->flags & SEL_DYNAMIC))
2176 sel->cdata->evaluate(data, sel, g);
2177 if (sel->cdata->flags & SEL_CDATA_STATIC)
2184 /* Evalute the static part if there is more than one expression */
2185 evaluate_boolean_static_part(data, sel, g);
2187 /* Evaluate the selection.
2188 * If the type is boolean, we must explicitly handle the
2189 * static part evaluated in evaluate_boolean_static_part()
2190 * here because g may be larger. */
2191 if (sel->u.boolt == BOOL_AND && sel->child->type == SEL_CONST)
2193 sel->cdata->evaluate(data, sel, sel->child->v.u.g);
2197 sel->cdata->evaluate(data, sel, g);
2200 /* Evaluate minimal and maximal selections */
2201 evaluate_boolean_minmax_grps(sel, g, sel->cdata->gmin,
2206 case SEL_ARITHMETIC:
2207 sel->cdata->evaluate(data, sel, g);
2208 if (!(sel->flags & SEL_DYNAMIC))
2210 if (sel->cdata->flags & SEL_CDATA_STATIC)
2217 gmx_ana_index_copy(sel->cdata->gmax, g, true);
2222 sel->cdata->evaluate(data, sel, g);
2226 if (((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR) &&
2227 !(sel->cdata->flags & SEL_CDATA_STATICMULTIEVALSUBEXPR))
2228 || (sel->cdata->flags & SEL_CDATA_FULLEVAL))
2230 sel->cdata->evaluate(data, sel, g);
2231 _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
2233 else if (sel->u.cgrp.isize == 0)
2235 GMX_ASSERT(g, "group cannot be null");
2236 gmx_ana_index_reserve(&sel->u.cgrp, g->isize);
2237 sel->cdata->evaluate(data, sel, g);
2240 gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, true);
2241 gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, true);
2246 int isize = gmx_ana_index_difference_size(g, &sel->u.cgrp);
2249 isize += sel->u.cgrp.isize;
2250 gmx_ana_index_reserve(&sel->u.cgrp, isize);
2251 alloc_selection_data(sel, isize, false);
2253 sel->cdata->evaluate(data, sel, g);
2254 if (isize > 0 && bDoMinMax)
2256 gmx_ana_index_reserve(sel->cdata->gmin,
2257 sel->cdata->gmin->isize
2258 + sel->child->cdata->gmin->isize);
2259 gmx_ana_index_reserve(sel->cdata->gmax,
2260 sel->cdata->gmax->isize
2261 + sel->child->cdata->gmax->isize);
2262 gmx_ana_index_merge(sel->cdata->gmin, sel->cdata->gmin,
2263 sel->child->cdata->gmin);
2264 gmx_ana_index_merge(sel->cdata->gmax, sel->cdata->gmax,
2265 sel->child->cdata->gmax);
2270 case SEL_SUBEXPRREF:
2271 if (!g && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
2273 /* The subexpression should have been evaluated if g is NULL
2274 * (i.e., this is a method parameter or a direct value of a
2276 if (sel->v.type == POS_VALUE)
2278 alloc_selection_pos_data(sel);
2282 alloc_selection_data(sel, sel->child->cdata->gmax->isize, true);
2285 sel->cdata->evaluate(data, sel, g);
2286 if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
2287 && (sel->child->child->flags & SEL_ALLOCVAL))
2289 _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
2291 /* Store the parameter value if required */
2292 store_param_val(sel);
2293 if (!(sel->flags & SEL_DYNAMIC))
2295 if (sel->cdata->flags & SEL_CDATA_STATIC)
2302 if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR) || !g)
2304 gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, true);
2305 gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, true);
2309 gmx_ana_index_reserve(sel->cdata->gmin,
2310 min(g->isize, sel->child->cdata->gmin->isize));
2311 gmx_ana_index_reserve(sel->cdata->gmax,
2312 min(g->isize, sel->child->cdata->gmax->isize));
2313 gmx_ana_index_intersection(sel->cdata->gmin,
2314 sel->child->cdata->gmin, g);
2315 gmx_ana_index_intersection(sel->cdata->gmax,
2316 sel->child->cdata->gmax, g);
2321 case SEL_GROUPREF: /* Should not be reached */
2322 GMX_THROW(gmx::APIError("Unresolved group reference in compilation"));
2325 /* Update the minimal and maximal evaluation groups */
2328 gmx_ana_index_squeeze(sel->cdata->gmin);
2329 gmx_ana_index_squeeze(sel->cdata->gmax);
2332 /* Replace the result of the evaluation */
2333 /* This is not necessary for subexpressions or for boolean negations
2334 * because the evaluation function already has done it properly. */
2335 if (sel->v.type == GROUP_VALUE && (sel->flags & SEL_DYNAMIC)
2336 && sel->type != SEL_SUBEXPR
2337 && !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
2339 if (sel->cdata->flags & SEL_CDATA_EVALMAX)
2341 gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmax, false);
2345 gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmin, false);
2351 /********************************************************************
2352 * EVALUATION GROUP INITIALIZATION
2353 ********************************************************************/
2356 * Initializes the evaluation group for a \ref SEL_ROOT element.
2358 * \param root Root element to initialize.
2359 * \param[in] gall Group of all atoms.
2361 * Checks whether it is necessary to evaluate anything through the root
2362 * element, and either clears the evaluation function or initializes the
2366 init_root_item(const SelectionTreeElementPointer &root,
2367 gmx_ana_index_t *gall)
2369 const SelectionTreeElementPointer &expr = root->child;
2370 /* Subexpressions with non-static evaluation group should not be
2371 * evaluated by the root, and neither should be single-reference
2372 * subexpressions that don't evaluate for all atoms. */
2373 if (expr->type == SEL_SUBEXPR
2374 && (!(root->child->cdata->flags & SEL_CDATA_STATICEVAL)
2375 || ((root->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
2376 && !(root->child->cdata->flags & SEL_CDATA_FULLEVAL))))
2378 root->evaluate = NULL;
2381 root->cdata->evaluate = NULL;
2385 /* Set the evaluation group */
2388 /* Non-atom-valued non-group expressions don't care about the group, so
2389 * don't allocate any memory for it. */
2390 if ((expr->flags & SEL_VARNUMVAL)
2391 || ((expr->flags & SEL_SINGLEVAL) && expr->v.type != GROUP_VALUE))
2393 gmx_ana_index_set(&root->u.cgrp, -1, NULL, 0);
2395 else if (expr->cdata->gmax->isize == gall->isize)
2397 /* Save some memory by only referring to the global group. */
2398 gmx_ana_index_set(&root->u.cgrp, gall->isize, gall->index, 0);
2402 gmx_ana_index_copy(&root->u.cgrp, expr->cdata->gmax, true);
2404 /* For selections, store the maximum group for
2405 * gmx_ana_selcollection_evaluate_fin() as the value of the root
2406 * element (unused otherwise). */
2407 if (expr->type != SEL_SUBEXPR && expr->v.u.p->m.mapb.a != NULL)
2409 SelectionTreeElementPointer child = expr;
2411 /* TODO: This code is copied from parsetree.c; it would be better
2412 * to have this hardcoded only in one place. */
2413 while (child->type == SEL_MODIFIER)
2415 child = child->child;
2416 if (child->type == SEL_SUBEXPRREF)
2418 child = child->child->child;
2421 if (child->type == SEL_SUBEXPRREF)
2423 child = child->child->child;
2425 if (child->child->flags & SEL_DYNAMIC)
2428 gmx_ana_index_set(&g, expr->v.u.p->m.mapb.nra, expr->v.u.p->m.mapb.a, 0);
2429 _gmx_selelem_set_vtype(root, GROUP_VALUE);
2430 root->flags |= (SEL_ALLOCVAL | SEL_ALLOCDATA);
2431 _gmx_selvalue_reserve(&root->v, 1);
2432 gmx_ana_index_copy(root->v.u.g, &g, true);
2438 gmx_ana_index_clear(&root->u.cgrp);
2443 /********************************************************************
2444 * REQUIRED ATOMS ANALYSIS
2445 ********************************************************************/
2448 * Finds the highest atom index required to evaluate a selection subtree.
2450 * \param[in] sel Root of the selection subtree to process.
2451 * \param[in,out] maxAtomIndex The highest atom index required to evaluate the
2452 * subtree. The existing value is never decreased, so multiple calls with
2453 * the same parameter will compute the maximum over several subtrees.
2455 * For evaluation that starts from a \ref SEL_ROOT element with a fixed group,
2456 * children will never extend the evaluation group except for method parameter
2457 * evaluation (which have their own root element), so it is sufficient to check
2458 * the root. However, children of \ref SEL_EXPRESSION elements (i.e., the
2459 * method parameters) may have been independently evaluated to a static group
2460 * that no longer has a separate root, so those need to be checked as well.
2462 * Position calculations are not considered here, but are analyzed through the
2463 * position calculation collection in the main compilation method.
2466 init_required_atoms(const SelectionTreeElementPointer &sel, int *maxAtomIndex)
2468 // Process children.
2469 if (sel->type != SEL_SUBEXPRREF)
2471 SelectionTreeElementPointer child = sel->child;
2474 init_required_atoms(child, maxAtomIndex);
2475 child = child->next;
2479 if (sel->type == SEL_ROOT
2480 || (sel->type == SEL_CONST && sel->v.type == GROUP_VALUE))
2482 if (sel->u.cgrp.isize > 0)
2485 std::max(*maxAtomIndex, gmx_ana_index_get_max_index(&sel->u.cgrp));
2491 /********************************************************************
2492 * FINAL SUBEXPRESSION OPTIMIZATION
2493 ********************************************************************/
2496 * Optimizes subexpression evaluation.
2498 * \param sel Root of the selection subtree to process.
2500 * Optimizes away some unnecessary evaluation of subexpressions that are only
2504 postprocess_item_subexpressions(const SelectionTreeElementPointer &sel)
2506 GMX_ASSERT(!(sel->child == NULL &&
2507 (sel->type == SEL_SUBEXPRREF || sel->type == SEL_SUBEXPR)),
2508 "Subexpression elements should always have a child element");
2510 /* Process children. */
2511 if (sel->type != SEL_SUBEXPRREF)
2513 SelectionTreeElementPointer child = sel->child;
2516 postprocess_item_subexpressions(child);
2517 child = child->next;
2521 /* Replace the evaluation function of statically evaluated subexpressions
2522 * for which the static group was not known in advance. */
2523 if (sel->type == SEL_SUBEXPR && sel->cdata->refcount > 1
2524 && (sel->cdata->flags & SEL_CDATA_STATICEVAL)
2525 && !(sel->cdata->flags & SEL_CDATA_FULLEVAL))
2527 /* We need to free memory allocated for the group, because it is no
2528 * longer needed (and would be lost on next call to the evaluation
2530 gmx_ana_index_deinit(&sel->u.cgrp);
2532 sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
2533 sel->cdata->evaluate = sel->evaluate;
2535 sel->child->freeValues();
2536 sel->child->mempool = NULL;
2537 _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
2538 sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
2541 /* Adjust memory allocation flags for subexpressions that are used only
2542 * once. This is not strictly necessary, but we do it to have the memory
2543 * managed consistently for all types of subexpressions. */
2544 if (sel->type == SEL_SUBEXPRREF
2545 && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
2547 if (sel->child->child->flags & SEL_ALLOCVAL)
2549 sel->flags |= SEL_ALLOCVAL;
2550 sel->flags |= (sel->child->child->flags & SEL_ALLOCDATA);
2551 sel->v.nalloc = sel->child->child->v.nalloc;
2552 sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
2553 sel->child->child->v.nalloc = -1;
2557 /* Do the same for subexpressions that are evaluated at once for all atoms. */
2558 if (sel->type == SEL_SUBEXPR
2559 && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
2560 && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
2562 sel->flags |= SEL_ALLOCVAL;
2563 sel->flags |= (sel->child->flags & SEL_ALLOCDATA);
2564 sel->v.nalloc = sel->child->v.nalloc;
2565 sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
2566 sel->child->v.nalloc = -1;
2569 /* For static subexpressions with a dynamic evaluation group, there is
2570 * no need to evaluate them again, as the SEL_SUBEXPRREF takes care of
2571 * everything during evaluation. */
2572 if (sel->type == SEL_SUBEXPR
2573 && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
2574 && (sel->cdata->flags & SEL_CDATA_STATICMULTIEVALSUBEXPR))
2576 sel->evaluate = NULL;
2577 sel->cdata->evaluate = NULL;
2582 /********************************************************************
2583 * COM CALCULATION INITIALIZATION
2584 ********************************************************************/
2587 * Initializes COM/COG calculation for method expressions that require it.
2589 * \param sel Selection subtree to process.
2590 * \param[in,out] pcc Position calculation collection to use.
2591 * \param[in] type Default position calculation type.
2592 * \param[in] flags Flags for default position calculation.
2594 * Searches recursively through the selection tree for dynamic
2595 * \ref SEL_EXPRESSION elements that define the \c gmx_ana_selmethod_t::pupdate
2597 * For each such element found, position calculation is initialized
2598 * for the maximal evaluation group.
2599 * The type of the calculation is determined by \p type and \p flags.
2600 * No calculation is initialized if \p type equals \ref POS_ATOM and
2601 * the method also defines the \c gmx_ana_selmethod_t::update method.
2604 init_item_comg(const SelectionTreeElementPointer &sel,
2605 gmx::PositionCalculationCollection *pcc,
2606 e_poscalc_t type, int flags)
2608 /* Initialize COM calculation for dynamic selections now that we know the maximal evaluation group */
2609 if (sel->type == SEL_EXPRESSION && sel->u.expr.method
2610 && sel->u.expr.method->pupdate)
2612 if (!sel->u.expr.method->update || type != POS_ATOM)
2614 /* Create a default calculation if one does not yet exist */
2616 if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
2618 cflags |= POS_DYNAMIC;
2620 if (!sel->u.expr.pc)
2623 sel->u.expr.pc = pcc->createCalculation(type, cflags);
2627 gmx_ana_poscalc_set_flags(sel->u.expr.pc, cflags);
2629 gmx_ana_poscalc_set_maxindex(sel->u.expr.pc, sel->cdata->gmax);
2630 sel->u.expr.pos = new gmx_ana_pos_t();
2631 gmx_ana_poscalc_init_pos(sel->u.expr.pc, sel->u.expr.pos);
2635 /* Call recursively for all children unless the children have already been processed */
2636 if (sel->type != SEL_SUBEXPRREF)
2638 SelectionTreeElementPointer child = sel->child;
2641 init_item_comg(child, pcc, type, flags);
2642 child = child->next;
2648 /********************************************************************
2649 * COMPILER DATA FREEING
2650 ********************************************************************/
2653 * Frees the allocated compiler data recursively.
2655 * \param sel Root of the selection subtree to process.
2657 * Frees the data allocated for the compilation process.
2660 free_item_compilerdata(const SelectionTreeElementPointer &sel)
2662 /* Free compilation data */
2663 sel->freeCompilerData();
2665 /* Call recursively for all children unless the children have already been processed */
2666 if (sel->type != SEL_SUBEXPRREF)
2668 SelectionTreeElementPointer child = sel->child;
2671 free_item_compilerdata(child);
2672 child = child->next;
2678 /********************************************************************
2679 * MAIN COMPILATION FUNCTION
2680 ********************************************************************/
2685 SelectionCompiler::SelectionCompiler()
2690 * \param[in,out] coll Selection collection to be compiled.
2691 * \returns 0 on successful compilation, a non-zero error code on error.
2693 * Before compilation, the selection collection should have been initialized
2694 * with gmx_ana_selcollection_parse_*().
2695 * The compiled selection collection can be passed to
2696 * gmx_ana_selcollection_evaluate() to evaluate the selection for a frame.
2697 * If an error occurs, \p sc is cleared.
2699 * The covered fraction information in \p sc is initialized to
2703 SelectionCompiler::compile(SelectionCollection *coll)
2705 gmx_ana_selcollection_t *sc = &coll->impl_->sc_;
2706 gmx_sel_evaluate_t evaldata;
2707 SelectionTreeElementPointer item;
2711 bool bDebug = (coll->impl_->debugLevel_ >= 2
2712 && coll->impl_->debugLevel_ != 3);
2714 /* FIXME: Clean up the collection on exceptions */
2716 sc->mempool = _gmx_sel_mempool_create();
2717 _gmx_sel_evaluate_init(&evaldata, sc->mempool, &sc->gall,
2718 sc->top, NULL, NULL);
2720 /* Clear the symbol table because it is not possible to parse anything
2721 * after compilation, and variable references in the symbol table can
2722 * also mess up the compilation and/or become invalid.
2724 coll->impl_->clearSymbolTable();
2726 /* Loop through selections and initialize position keyword defaults if no
2727 * other value has been provided.
2729 for (i = 0; i < sc->sel.size(); ++i)
2731 gmx::internal::SelectionData &sel = *sc->sel[i];
2732 init_pos_keyword_defaults(&sel.rootElement(),
2733 coll->impl_->spost_.c_str(),
2734 coll->impl_->rpost_.c_str(),
2738 /* Remove any unused variables. */
2739 sc->root = remove_unused_subexpressions(sc->root);
2740 /* Extract subexpressions into separate roots */
2741 sc->root = extract_subexpressions(sc->root);
2743 /* Initialize the evaluation callbacks and process the tree structure
2744 * to conform to the expectations of the callback functions. */
2745 /* Also, initialize and allocate the compiler data structure */
2746 // TODO: Processing the tree in reverse root order would be better,
2747 // as it would make dependency handling easier (all subexpression
2748 // references would be processed before the actual subexpression) and
2749 // could remove the need for most of these extra loops.
2753 /* Process boolean and arithmetic expressions. */
2754 optimize_boolean_expressions(item);
2755 reorder_boolean_static_children(item);
2756 optimize_arithmetic_expressions(item);
2757 /* Initialize the compiler data */
2758 init_item_compilerdata(item);
2761 // Initialize the static evaluation compiler flags.
2762 // Requires the FULLEVAL compiler flag for the whole tree.
2766 init_item_staticeval(item);
2767 init_item_subexpr_refcount(item);
2770 /* Initialize subexpression flags.
2771 * Requires compiler flags for the full tree. */
2775 init_item_subexpr_flags(item);
2778 /* Initialize evaluation.
2779 * Requires subexpression flags. */
2783 init_item_evalfunc(item);
2784 setup_memory_pooling(item, sc->mempool);
2785 init_item_evaloutput(item);
2788 /* Initialize minimum/maximum index groups.
2789 * Requires evaluation output for the full tree. */
2793 init_item_minmax_groups(item);
2796 /* Initialize the evaluation index groups */
2797 initialize_evalgrps(sc);
2801 fprintf(stderr, "\nTree after initial compiler processing:\n");
2802 coll->printTree(stderr, false);
2805 /* Evaluate all static parts of the selection and analyze the tree
2806 * to allocate enough memory to store the value of each dynamic subtree. */
2810 if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
2812 mark_subexpr_dynamic(item->child, true);
2814 set_evaluation_function(item, &analyze_static);
2815 item->evaluate(&evaldata, item, NULL);
2819 /* At this point, static subexpressions no longer have references to them,
2820 * so they can be removed. */
2821 sc->root = remove_unused_subexpressions(sc->root);
2822 // Update the reference counts for consistency (only used for the
2823 // debugging output below).
2827 init_item_subexpr_refcount(item);
2833 fprintf(stderr, "\nTree after first analysis pass:\n");
2834 coll->printTree(stderr, false);
2837 /* Do a second pass to evaluate static parts of common subexpressions */
2841 if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
2843 bool bMinMax = item->child->cdata->flags & SEL_CDATA_DOMINMAX;
2845 mark_subexpr_dynamic(item->child, false);
2846 item->child->u.cgrp.isize = 0;
2847 /* We won't clear item->child->v.u.g here, because it may
2848 * be static, and hence actually point to item->child->cdata->gmax,
2849 * which is used below. We could also check whether this is the
2850 * case and only clear the group otherwise, but because the value
2851 * is actually overwritten immediately in the evaluate call, we
2852 * won't, because similar problems may arise if gmax handling ever
2853 * changes and the check were not updated.
2854 * For the same reason, we clear the min/max flag so that the
2855 * evaluation group doesn't get messed up. */
2856 set_evaluation_function(item, &analyze_static);
2857 item->child->cdata->flags &= ~SEL_CDATA_DOMINMAX;
2858 item->evaluate(&evaldata, item->child, item->child->cdata->gmax);
2861 item->child->cdata->flags |= SEL_CDATA_DOMINMAX;
2867 /* We need a yet another pass of subexpression removal to remove static
2868 * subexpressions referred to by common dynamic subexpressions. */
2869 sc->root = remove_unused_subexpressions(sc->root);
2870 // Update the reference counts, used by postprocess_item_subexpressions().
2874 init_item_subexpr_refcount(item);
2880 fprintf(stderr, "\nTree after second analysis pass:\n");
2881 coll->printTree(stderr, false);
2884 // Initialize evaluation groups, maximum atom index needed for evaluation,
2885 // position calculations for methods, perform some final optimization, and
2886 // free the memory allocated for the compilation.
2887 coll->impl_->maxAtomIndex_ = 0;
2888 /* By default, use whole residues/molecules. */
2889 flags = POS_COMPLWHOLE;
2890 PositionCalculationCollection::typeFromEnum(coll->impl_->rpost_.c_str(),
2895 init_root_item(item, &sc->gall);
2896 postprocess_item_subexpressions(item);
2897 init_required_atoms(item, &coll->impl_->maxAtomIndex_);
2898 init_item_comg(item, &sc->pcc, post, flags);
2899 free_item_compilerdata(item);
2902 coll->impl_->maxAtomIndex_ =
2903 std::max(coll->impl_->maxAtomIndex_,
2904 sc->pcc.getHighestRequiredAtomIndex());
2906 /* Allocate memory for the evaluation memory pool. */
2907 _gmx_sel_mempool_reserve(sc->mempool, 0);
2909 /* Finish up by calculating total masses and charges. */
2910 for (i = 0; i < sc->sel.size(); ++i)
2912 sc->sel[i]->initializeMassesAndCharges(sc->top);