3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
32 * \brief Selection compilation and optimization.
35 * Better error handling and memory management in error situations.
36 * At least, the main compilation function leaves the selection collection in
37 * a bad state if an error occurs.
40 * The memory usage could still be optimized.
41 * Use of memory pooling could still be extended, and a lot of redundant
42 * gmin/gmax data could be eliminated for complex arithmetic expressions.
44 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
45 * \ingroup module_selection
48 * \page page_module_selection_compiler Selection compilation
50 * The compiler takes the selection element tree from the selection parser
51 * (see \ref page_module_selection_parser) as input.
52 * The selection parser is quite independent of selection evaluation details,
53 * and the compiler processes the tree to conform to what the evaluation
55 * For better control and optimization possibilities, the compilation is
56 * done on all selections simultaneously.
57 * Hence, all the selections should be parsed before the compiler can be
60 * The compiler initializes all fields in gmx::SelectionTreeElement not
61 * initialized by the parser: gmx::SelectionTreeElement::v (some fields have
62 * already been initialized by the parser),
63 * gmx::SelectionTreeElement::evaluate, and gmx::SelectionTreeElement::u
64 * (again, some elements have been initialized in the parser).
65 * The gmx::SelectionTreeElement::cdata field is used during the compilation to store
66 * internal data, but the data is freed when the compiler returns.
68 * In addition to initializing the elements, the compiler reorganizes the tree
69 * to simplify and optimize evaluation. The compiler also evaluates the static
70 * parts of the selection: in the end of the compilation, static parts have
71 * been replaced by the result of the evaluation.
73 * The compiler is invoked using gmx::SelectionCompiler.
74 * The gmx::SelectionCompiler::compile() method does the compilation in several
75 * passes over the gmx::SelectionTreeElement tree.
76 * -# Defaults are set for the position type and flags of position calculation
77 * methods that were not explicitly specified in the user input.
78 * -# Subexpressions are extracted: a separate root is created for each
79 * subexpression, and placed before the expression is first used.
80 * Currently, only variables and expressions used to evaluate parameter
81 * values are extracted, but common subexpression could also be detected
83 * -# A second pass (in fact, multiple passes because of interdependencies)
84 * with simple reordering and initialization is done:
85 * -# Boolean expressions are combined such that one element can evaluate,
86 * e.g., "A and B and C". The subexpressions in boolean expression are
87 * reordered such that static expressions come first without otherwise
88 * altering the relative order of the expressions.
89 * -# The compiler data structure is allocated for each element, and
90 * the fields are initialized, with the exception of the contents of
91 * \c gmax and \c gmin fields. This is the part that needs multiple
92 * passes, because some flags are set recursively based on which elements
93 * refer to an element, and these flags need to be set to initialize
95 * -# The gmx::SelectionTreeElement::evaluate field is set to the correct
96 * evaluation function from evaluate.h.
98 * -# The evaluation function of all elements is replaced with the
99 * analyze_static() function to be able to initialize the element before
100 * the actual evaluation function is called.
101 * The evaluation machinery is then called to initialize the whole tree,
102 * while simultaneously evaluating the static expressions.
103 * During the evaluation, track is kept of the smallest and largest
104 * possible selections, and these are stored in the internal compiler
105 * data structure for each element.
106 * To be able to do this for all possible values of dynamical expressions,
107 * special care needs to be taken with boolean expressions because they
108 * are short-circuiting. This is done through the
109 * \c SEL_CDATA_EVALMAX flag, which makes dynamic child expressions
110 * of \c BOOL_OR expressions evaluate to empty groups, while subexpressions
111 * of \c BOOL_AND are evaluated to largest possible groups.
112 * Memory is also allocated to store the results of the evaluation.
113 * For each element, analyze_static() calls the actual evaluation function
114 * after the element has been properly initialized.
115 * -# Another evaluation pass is done over subexpressions with more than
116 * one reference to them. These cannot be completely processed during the
117 * first pass, because it is not known whether later references require
118 * additional evaluation of static expressions.
119 * -# Unused subexpressions are removed. For efficiency reasons (and to avoid
120 * some checks), this is actually done several times already earlier in
121 * the compilation process.
122 * -# Most of the processing is now done, and the next pass simply sets the
123 * evaluation group of root elements to the largest selection as determined
124 * in pass 4. For root elements of subexpressions that should not be
125 * evaluated before they are referred to, the evaluation group/function is
126 * cleared. At the same time, position calculation data is initialized for
127 * for selection method elements that require it. Compiler data is also
128 * freed as it is no longer needed.
129 * -# A final pass initializes the total masses and charges in the
130 * \c gmx_ana_selection_t data structures.
132 * The actual evaluation of the selection is described in the documentation
133 * of the functions in evaluate.h.
136 * Some combinations of method parameter flags are not yet properly treated by
137 * the compiler or the evaluation functions in evaluate.cpp. All the ones used by
138 * currently implemented methods should work, but new combinations might not.
141 * \section selcompiler_tree Element tree after compilation
143 * After the compilation, the selection element tree is suitable for
144 * gmx_ana_selcollection_evaluate().
145 * Enough memory has been allocated for gmx::SelectionTreeElement::v
146 * (and gmx::SelectionTreeElement::cgrp for \ref SEL_SUBEXPR elements) to allow
147 * the selection to be evaluated without allocating any memory.
150 * \subsection selcompiler_tree_root Root elements
152 * The top level of the tree consists of a chain of \ref SEL_ROOT elements.
153 * These are used for two purposes:
154 * -# A selection that should be evaluated.
155 * These elements appear in the same order as the selections in the input.
156 * For these elements, gmx::SelectionTreeElement::v has been set to the
157 * maximum possible group that the selection can evaluate to (only for
158 * dynamic selections), and gmx::SelectionTreeElement::cgrp has been set to
159 * use a NULL group for evaluation.
160 * -# A subexpression that appears in one or more selections.
161 * Each selection that gives a value for a method parameter is a
162 * potential subexpression, as is any variable value.
163 * Only subexpressions that require evaluation for each frame are left
164 * after the selection is compiled.
165 * Each subexpression appears in the chain before any references to it.
166 * For these elements, gmx::SelectionTreeElement::cgrp has been set to the
167 * group that should be used to evaluate the subexpression.
168 * If gmx::SelectionTreeElement::cgrp is empty, the total evaluation group
169 * is not known in advance or it is more efficient to evaluate the
170 * subexpression only when it is referenced. If this is the case,
171 * gmx::SelectionTreeElement::evaluate is also NULL.
173 * The children of the \ref SEL_ROOT elements can be used to distinguish
174 * the two types of root elements from each other; the rules are the same
175 * as for the parsed tree (see \ref selparser_tree_root).
176 * Subexpressions are treated as if they had been provided through variables.
178 * Selection names are stored as after parsing (see \ref selparser_tree_root).
181 * \subsection selcompiler_tree_const Constant elements
183 * All (sub)selections that do not require particle positions have been
184 * replaced with \ref SEL_CONST elements.
185 * Constant elements from the parser are also retained if present in
186 * dynamic parts of the selections.
187 * Several constant elements with a NULL gmx::SelectionTreeElement::evaluate
188 * are left for debugging purposes; of these, only the ones for \ref BOOL_OR
189 * expressions are used during evaluation.
191 * The value is stored in gmx::SelectionTreeElement::v, and for group values
192 * with an evaluation function set, also in gmx::SelectionTreeElement::cgrp.
193 * For \ref GROUP_VALUE elements, unnecessary atoms (i.e., atoms that
194 * could never be selected) have been removed from the value.
196 * \ref SEL_CONST elements have no children.
199 * \subsection selcompiler_tree_method Method evaluation elements
201 * All selection methods that need to be evaluated dynamically are described
202 * by a \ref SEL_EXPRESSION element. The gmx::SelectionTreeElement::method and
203 * gmx::SelectionTreeElement::mdata fields have already been initialized by the parser,
204 * and the compiler only calls the initialization functions in the method
205 * data structure to do some additional initialization of these fields at
206 * appropriate points. If the gmx::SelectionTreeElement::pc data field has been
207 * created by the parser, the compiler initializes the data structure properly
208 * once the required positions are known. If the gmx::SelectionTreeElement::pc
209 * field is NULL after the parser, but the method provides only
210 * sel_updatefunc_pos(), an appropriate position calculation data structure is
211 * created. If gmx::SelectionTreeElement::pc is not NULL,
212 * gmx::SelectionTreeElement::pos is also initialized to hold the positions
215 * Children of these elements are of type \ref SEL_SUBEXPRREF, and describe
216 * parameter values that need to be evaluated for each frame. See the next
217 * section for more details.
218 * \ref SEL_CONST children can also appear, and stand for parameters that get
219 * their value from a static expression. These elements are present only for
220 * debugging purposes: they always have a NULL evaluation function.
223 * \subsection selcompiler_tree_subexpr Subexpression elements
225 * As described in \ref selcompiler_tree_root, subexpressions are created
226 * for each variable and each expression that gives a value to a selection
227 * method parameter. As the only child of the \ref SEL_ROOT element,
228 * these elements have a \ref SEL_SUBEXPR element. The \ref SEL_SUBEXPR
229 * element has a single child, which evaluates the actual expression.
230 * After compilation, only subexpressions that require particle positions
231 * for evaluation are left.
232 * For non-variable subexpression, automatic names have been generated to
235 * For \ref SEL_SUBEXPR elements, memory has been allocated for
236 * gmx::SelectionTreeElement::cgrp to store the group for which the expression
237 * has been evaluated during the current frame. This is only done if full
238 * subexpression evaluation by _gmx_sel_evaluate_subexpr() is needed; the other
239 * evaluation functions do not require this memory.
241 * \ref SEL_SUBEXPRREF elements are used to describe references to
242 * subexpressions. They have always a single child, which is the
243 * \ref SEL_SUBEXPR element being referenced.
245 * If a subexpression is used only once, the evaluation has been optimized by
246 * setting the child of the \ref SEL_SUBEXPR element to evaluate the value of
247 * \ref SEL_SUBEXPRREF directly (in the case of memory pooling, this is managed
248 * by the evaluation functions). In such cases, the evaluation routines for the
249 * \ref SEL_SUBEXPRREF and \ref SEL_SUBEXPR elements only propagate some status
250 * information, but do not unnecessarily copy the values.
253 * \subsection selcompiler_tree_bool Boolean elements
255 * \ref SEL_BOOLEAN elements have been merged such that one element
256 * may carry out evaluation of more than one operation of the same type.
257 * The static parts of the expressions have been evaluated, and are placed
258 * in the first child. These are followed by the dynamic expressions, in the
259 * order provided by the user.
262 * \subsection selcompiler_tree_arith Arithmetic elements
264 * Constant and static expressions in \ref SEL_ARITHMETIC elements have been
266 * Currently, no other processing is done.
268 #include "compiler.h"
275 #include "gromacs/legacyheaders/smalloc.h"
276 #include "gromacs/legacyheaders/string2.h"
277 #include "gromacs/legacyheaders/vec.h"
279 #include "gromacs/selection/indexutil.h"
280 #include "gromacs/selection/poscalc.h"
281 #include "gromacs/selection/selection.h"
282 #include "gromacs/selection/selmethod.h"
283 #include "gromacs/utility/exceptions.h"
284 #include "gromacs/utility/stringutil.h"
286 #include "evaluate.h"
287 #include "keywords.h"
289 #include "selectioncollection-impl.h"
293 using gmx::SelectionTreeElement;
294 using gmx::SelectionTreeElementPointer;
302 * Whether a subexpression needs to evaluated for all atoms.
304 * This flag is set for \ref SEL_SUBEXPR elements that are used to
305 * evaluate non-atom-valued selection method parameters, as well as
306 * those that are used directly as values of selections.
308 SEL_CDATA_FULLEVAL = 1,
310 * Whether the whole subexpression should be treated as static.
312 * This flag is always false if \ref SEL_DYNAMIC is set for the element,
313 * but it is also false for static elements within common subexpressions.
315 SEL_CDATA_STATIC = 2,
316 /** Whether the subexpression will always be evaluated in the same group. */
317 SEL_CDATA_STATICEVAL = 4,
318 /** Whether the compiler evaluation routine should return the maximal selection. */
319 SEL_CDATA_EVALMAX = 8,
320 /** Whether memory has been allocated for \p gmin and \p gmax. */
321 SEL_CDATA_MINMAXALLOC = 16,
322 /** Whether to update \p gmin and \p gmax in static analysis. */
323 SEL_CDATA_DOMINMAX = 128,
324 /** Whether the subexpression uses simple pass evaluation functions. */
325 SEL_CDATA_SIMPLESUBEXPR = 32,
326 /** Whether this expression is a part of a common subexpression. */
327 SEL_CDATA_COMMONSUBEXPR = 64
331 * Internal data structure used by the compiler.
333 typedef struct t_compiler_data
335 /** The real evaluation method. */
336 gmx::sel_evalfunc evaluate;
337 /** Number of references to a \ref SEL_SUBEXPR element. */
339 /** Flags for specifying how to treat this element during compilation. */
341 /** Smallest selection that can be selected by the subexpression. */
342 gmx_ana_index_t *gmin;
343 /** Largest selection that can be selected by the subexpression. */
344 gmx_ana_index_t *gmax;
348 /********************************************************************
349 * COMPILER UTILITY FUNCTIONS
350 ********************************************************************/
353 * Helper method for printing out debug information about a min/max group.
356 print_group_info(FILE *fp, const char *name,
357 const SelectionTreeElement &sel,
360 fprintf(fp, " %s=", name);
363 fprintf(fp, "(null)");
365 else if (sel.cdata->flags & SEL_CDATA_MINMAXALLOC)
367 fprintf(fp, "(%d atoms, %p)", g->isize, (void*)g);
369 else if (sel.v.type == GROUP_VALUE && g == sel.v.u.g)
371 fprintf(fp, "(static, %p)", (void*)g);
375 fprintf(fp, "%p", (void*)g);
380 * \param[in] fp File handle to receive the output.
381 * \param[in] sel Selection element to print.
382 * \param[in] level Indentation level, starting from zero.
385 _gmx_selelem_print_compiler_info(FILE *fp, const SelectionTreeElement &sel,
392 fprintf(fp, "%*c cdata: flg=", level*2+1, ' ');
393 if (sel.cdata->flags & SEL_CDATA_FULLEVAL)
397 if (!(sel.cdata->flags & SEL_CDATA_STATIC))
401 if (sel.cdata->flags & SEL_CDATA_STATICEVAL)
405 if (sel.cdata->flags & SEL_CDATA_EVALMAX)
409 if (sel.cdata->flags & SEL_CDATA_MINMAXALLOC)
413 if (sel.cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
417 if (sel.cdata->flags & SEL_CDATA_COMMONSUBEXPR)
421 if (!sel.cdata->flags)
425 if (sel.cdata->refcount > 0)
427 fprintf(fp, " refc=%d", sel.cdata->refcount);
429 fprintf(fp, " eval=");
430 _gmx_sel_print_evalfunc_name(fp, sel.cdata->evaluate);
431 print_group_info(fp, "gmin", sel, sel.cdata->gmin);
432 print_group_info(fp, "gmax", sel, sel.cdata->gmax);
439 void SelectionTreeElement::freeCompilerData()
443 evaluate = cdata->evaluate;
444 if (cdata->flags & SEL_CDATA_MINMAXALLOC)
446 cdata->gmin->name = NULL;
447 cdata->gmax->name = NULL;
448 gmx_ana_index_deinit(cdata->gmin);
449 gmx_ana_index_deinit(cdata->gmax);
461 * Allocates memory for storing the evaluated value of a selection element.
463 * \param sel Selection element to initialize
464 * \param[in] isize Maximum evaluation group size.
465 * \param[in] bChildEval true if children have already been processed.
467 * If called more than once, memory is (re)allocated to ensure that the
468 * maximum of the \p isize values can be stored.
470 * Allocation of POS_VALUE selection elements is a special case, and is
471 * handled by alloc_selection_pos_data().
474 alloc_selection_data(const SelectionTreeElementPointer &sel,
475 int isize, bool bChildEval)
479 GMX_RELEASE_ASSERT(sel->v.type != POS_VALUE,
480 "Wrong allocation method called");
485 /* Find out the number of elements to allocate */
486 if (sel->flags & SEL_SINGLEVAL)
490 else if (sel->flags & SEL_ATOMVAL)
494 else /* sel->flags should contain SEL_VARNUMVAL */
496 // TODO: Consider whether the bChildEval is any longer necessary.
501 SelectionTreeElementPointer child = sel;
502 if (sel->type == SEL_SUBEXPRREF)
504 GMX_RELEASE_ASSERT(sel->child && sel->child->type == SEL_SUBEXPR,
505 "Subexpression expected for subexpression reference");
506 child = sel->child->child;
507 GMX_RELEASE_ASSERT(child,
508 "Subexpression elements should always have a child element");
510 nalloc = child->v.nr;
512 /* Allocate memory for sel->v.u if needed */
513 if (sel->flags & SEL_ALLOCVAL)
515 _gmx_selvalue_reserve(&sel->v, nalloc);
517 /* Reserve memory inside group structure if SEL_ALLOCDATA is set. */
518 if ((sel->flags & SEL_ALLOCDATA) && sel->v.type == GROUP_VALUE)
520 gmx_ana_index_reserve(sel->v.u.g, isize);
525 * Allocates memory for storing the evaluated value of a selection element.
527 * \param sel Selection element to initialize.
529 * Allocation of POS_VALUE selection elements is a special case, and is
530 * handled by this function instead of by alloc_selection_data().
533 alloc_selection_pos_data(const SelectionTreeElementPointer &sel)
537 GMX_RELEASE_ASSERT(sel->v.type == POS_VALUE,
538 "Wrong allocation method called");
539 GMX_RELEASE_ASSERT(!(sel->flags & SEL_ATOMVAL),
540 "Per-atom evaluated positions not implemented");
546 SelectionTreeElementPointer child = sel;
547 if (sel->type == SEL_SUBEXPRREF)
549 GMX_RELEASE_ASSERT(sel->child && sel->child->type == SEL_SUBEXPR,
550 "Subexpression expected for subexpression reference");
551 child = sel->child->child;
552 GMX_RELEASE_ASSERT(child,
553 "Subexpression elements should always have a child element");
555 nalloc = child->v.u.p->nr;
556 isize = child->v.u.p->m.b.nra;
558 /* For positions, we want to allocate just a single structure
559 * for nalloc positions. */
560 if (sel->flags & SEL_ALLOCVAL)
562 _gmx_selvalue_reserve(&sel->v, 1);
565 /* Reserve memory inside position structure if SEL_ALLOCDATA is set. */
566 if (sel->flags & SEL_ALLOCDATA)
568 gmx_ana_pos_reserve(sel->v.u.p, nalloc, isize);
573 * Replace the evaluation function of each element in the subtree.
575 * \param sel Root of the selection subtree to process.
576 * \param[in] eval The new evaluation function.
579 set_evaluation_function(const SelectionTreeElementPointer &sel,
580 gmx::sel_evalfunc eval)
582 sel->evaluate = eval;
583 if (sel->type != SEL_SUBEXPRREF)
585 SelectionTreeElementPointer child = sel->child;
588 set_evaluation_function(child, eval);
595 /********************************************************************
596 * POSITION KEYWORD DEFAULT INITIALIZATION
597 ********************************************************************/
600 * Initializes default values for position keyword evaluation.
602 * \param[in,out] root Root of the element tree to initialize.
603 * \param[in] spost Default output position type.
604 * \param[in] rpost Default reference position type.
605 * \param[in] sel Selection that the element evaluates the positions
606 * for, or NULL if the element is an internal element.
609 init_pos_keyword_defaults(SelectionTreeElement *root,
610 const char *spost, const char *rpost,
611 const gmx::internal::SelectionData *sel)
613 /* Selections use largest static group by default, while
614 * reference positions use the whole residue/molecule. */
615 if (root->type == SEL_EXPRESSION)
617 bool bSelection = (sel != NULL);
618 int flags = bSelection ? POS_COMPLMAX : POS_COMPLWHOLE;
621 if (sel->hasFlag(gmx::efSelection_DynamicMask))
623 flags |= POS_MASKONLY;
625 if (sel->hasFlag(gmx::efSelection_EvaluateVelocities))
627 flags |= POS_VELOCITIES;
629 if (sel->hasFlag(gmx::efSelection_EvaluateForces))
634 _gmx_selelem_set_kwpos_type(root, bSelection ? spost : rpost);
635 _gmx_selelem_set_kwpos_flags(root, flags);
637 /* Change the defaults once we are no longer processing modifiers */
638 if (root->type != SEL_ROOT && root->type != SEL_MODIFIER
639 && root->type != SEL_SUBEXPRREF && root->type != SEL_SUBEXPR)
643 /* Recurse into children */
644 SelectionTreeElementPointer child = root->child;
647 init_pos_keyword_defaults(child.get(), spost, rpost, sel);
653 /********************************************************************
654 * SUBEXPRESSION PROCESSING
655 ********************************************************************/
658 * Reverses the chain of selection elements starting at \p root.
660 * \param root First selection in the whole selection chain.
661 * \returns The new first element for the chain.
663 static SelectionTreeElementPointer
664 reverse_selelem_chain(const SelectionTreeElementPointer &root)
666 SelectionTreeElementPointer prev;
667 SelectionTreeElementPointer item = root;
670 SelectionTreeElementPointer next = item->next;
679 * Removes subexpressions that don't have any references.
681 * \param root First selection in the whole selection chain.
682 * \returns The new first element for the chain.
684 * The elements are processed in reverse order to correctly detect
685 * subexpressions only referred to by other subexpressions.
687 static SelectionTreeElementPointer
688 remove_unused_subexpressions(SelectionTreeElementPointer root)
692 return SelectionTreeElementPointer();
694 root = reverse_selelem_chain(root);
695 while (root->child->type == SEL_SUBEXPR && root->child.unique())
697 // Frees the root element.
700 SelectionTreeElementPointer prev = root;
701 SelectionTreeElementPointer item = root->next;
704 SelectionTreeElementPointer next = item->next;
705 if (item->child->type == SEL_SUBEXPR && item->child.unique())
707 // Frees the current item when it goes out of scope.
716 return reverse_selelem_chain(root);
720 * Creates a name with a running number for a subexpression.
722 * \param[in,out] sel The subexpression to be named.
723 * \param[in] i Running number for the subexpression.
725 * The name of the selection becomes "SubExpr N", where N is \p i;
726 * Memory is allocated for the name and the name is stored both as the
727 * name of the subexpression element and as
728 * gmx::SelectionTreeElement::u::cgrp::name; the latter is freed by
729 * _gmx_selelem_free().
732 create_subexpression_name(const SelectionTreeElementPointer &sel, int i)
734 std::string name(gmx::formatString("SubExpr %d", i));
736 sel->u.cgrp.name = strdup(name.c_str());
740 * Processes and extracts subexpressions from a given selection subtree.
742 * \param sel Root of the subtree to process.
743 * \param subexprn Pointer to a subexpression counter.
744 * \returns Pointer to a chain of subselections, or NULL if none were found.
746 * This function finds recursively all \ref SEL_SUBEXPRREF elements below
747 * the given root element and ensures that their children are within
748 * \ref SEL_SUBEXPR elements. It also creates a chain of \ref SEL_ROOT elements
749 * that contain the subexpression as their children and returns the first
750 * of these root elements.
752 static SelectionTreeElementPointer
753 extract_item_subselections(const SelectionTreeElementPointer &sel,
756 SelectionTreeElementPointer root;
757 SelectionTreeElementPointer subexpr;
758 SelectionTreeElementPointer child = sel->child;
764 root = subexpr = extract_item_subselections(child, subexprn);
768 subexpr->next = extract_item_subselections(child, subexprn);
770 while (subexpr && subexpr->next)
772 subexpr = subexpr->next;
774 /* The latter check excludes variable references. */
775 if (child->type == SEL_SUBEXPRREF && child->child->type != SEL_SUBEXPR)
777 /* Create the root element for the subexpression */
780 root.reset(new SelectionTreeElement(SEL_ROOT));
785 subexpr->next.reset(new SelectionTreeElement(SEL_ROOT));
786 subexpr = subexpr->next;
788 /* Create the subexpression element and
789 * move the actual subexpression under the created element. */
790 subexpr->child.reset(new SelectionTreeElement(SEL_SUBEXPR));
791 _gmx_selelem_set_vtype(subexpr->child, child->v.type);
792 subexpr->child->child = child->child;
793 child->child = subexpr->child;
794 create_subexpression_name(subexpr->child, ++*subexprn);
795 /* Set the flags for the created elements */
796 subexpr->flags |= (child->flags & SEL_VALFLAGMASK);
797 subexpr->child->flags |= (child->flags & SEL_VALFLAGMASK);
799 if (child->type == SEL_SUBEXPRREF)
801 child->setName(child->child->name());
810 * Extracts subexpressions of the selection chain.
812 * \param sel First selection in the whole selection chain.
813 * \returns The new first element for the chain.
815 * Finds all the subexpressions (and their subexpressions) in the
816 * selection chain starting from \p sel and creates \ref SEL_SUBEXPR
818 * \ref SEL_ROOT elements are also created for each subexpression
819 * and inserted into the selection chain before the expressions that
822 static SelectionTreeElementPointer
823 extract_subexpressions(SelectionTreeElementPointer sel)
825 SelectionTreeElementPointer root;
826 SelectionTreeElementPointer next = sel;
830 SelectionTreeElementPointer item
831 = extract_item_subselections(next, &subexprn);
859 /********************************************************************
860 * BOOLEAN OPERATION REORDERING
861 ********************************************************************/
864 * Removes redundant boolean selection elements.
866 * \param sel Root of the selection subtree to optimize.
868 * This function merges similar boolean operations (e.g., (A or B) or C becomes
869 * a single OR operation with three operands).
872 optimize_boolean_expressions(const SelectionTreeElementPointer &sel)
874 /* Do recursively for children */
875 if (sel->type != SEL_SUBEXPRREF)
877 SelectionTreeElementPointer prev;
878 SelectionTreeElementPointer child = sel->child;
881 optimize_boolean_expressions(child);
882 /* Remove double negations */
883 if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT
884 && child->child->type == SEL_BOOLEAN && child->child->u.boolt == BOOL_NOT)
886 /* Move the doubly negated expression up two levels */
889 sel->child = child->child->child;
894 prev->next = child->child->child;
897 child->child->child->next = child->next;
898 // Discards the two negations.
905 if (sel->type != SEL_BOOLEAN || sel->u.boolt == BOOL_NOT)
909 /* Merge subsequent binary operations */
910 SelectionTreeElementPointer prev;
911 SelectionTreeElementPointer child = sel->child;
914 if (child->type == SEL_BOOLEAN && child->u.boolt == sel->u.boolt)
918 sel->child = child->child;
923 prev->next = child->child;
929 prev->next = child->next;
930 // Discards the old child.
942 * Reorders children of boolean expressions such that static selections
945 * \param sel Root of the selection subtree to reorder.
947 * The relative order of static expressions does not change.
948 * The same is true for the dynamic expressions.
951 reorder_boolean_static_children(const SelectionTreeElementPointer &sel)
953 /* Do recursively for children */
954 if (sel->type != SEL_SUBEXPRREF)
956 SelectionTreeElementPointer child = sel->child;
959 reorder_boolean_static_children(child);
964 /* Reorder boolean expressions such that static selections come first */
965 if (sel->type == SEL_BOOLEAN && (sel->flags & SEL_DYNAMIC))
967 // Add a dummy head element that precedes the first child.
968 SelectionTreeElementPointer dummy(
969 new SelectionTreeElement(SEL_BOOLEAN));
970 dummy->next = sel->child;
971 SelectionTreeElementPointer prev = dummy;
972 SelectionTreeElementPointer child = dummy;
975 /* child is the last handled static expression */
976 /* prev is the last handled non-static expression */
977 SelectionTreeElementPointer next = prev->next;
978 while (next && (next->flags & SEL_DYNAMIC))
983 /* next is now the first static expression after child */
988 /* Reorder such that next comes after child */
991 prev->next = next->next;
992 next->next = child->next;
999 /* Advance child by one */
1003 sel->child = dummy->next;
1008 /********************************************************************
1009 * ARITHMETIC EXPRESSION PROCESSING
1010 ********************************************************************/
1013 * Processes arithmetic expressions to simplify and speed up evaluation.
1015 * \param sel Root of the selection subtree to process.
1017 * Currently, this function only converts integer constants to reals
1018 * within arithmetic expressions.
1021 optimize_arithmetic_expressions(const SelectionTreeElementPointer &sel)
1023 /* Do recursively for children. */
1024 if (sel->type != SEL_SUBEXPRREF)
1026 SelectionTreeElementPointer child = sel->child;
1029 optimize_arithmetic_expressions(child);
1030 child = child->next;
1034 if (sel->type != SEL_ARITHMETIC)
1039 /* Convert integer constants to reals. */
1040 SelectionTreeElementPointer child = sel->child;
1043 if (child->v.type == INT_VALUE)
1047 if (child->type != SEL_CONST)
1049 GMX_THROW(gmx::InconsistentInputError("Non-constant integer expressions not implemented in arithmetic evaluation"));
1052 r[0] = child->v.u.i[0];
1053 sfree(child->v.u.i);
1055 child->v.type = REAL_VALUE;
1057 else if (child->v.type != REAL_VALUE)
1059 GMX_THROW(gmx::InternalError("Non-numerical value in arithmetic expression"));
1061 child = child->next;
1066 /********************************************************************
1067 * EVALUATION PREPARATION COMPILER
1068 ********************************************************************/
1071 * Sets the evaluation functions for the selection (sub)tree.
1073 * \param[in,out] sel Root of the selection subtree to process.
1075 * This function sets the evaluation function
1076 * (gmx::SelectionTreeElement::evaluate) for the selection elements.
1079 init_item_evalfunc(const SelectionTreeElementPointer &sel)
1081 /* Process children. */
1082 if (sel->type != SEL_SUBEXPRREF)
1084 SelectionTreeElementPointer child = sel->child;
1087 init_item_evalfunc(child);
1088 child = child->next;
1092 /* Set the evaluation function */
1096 if (sel->v.type == GROUP_VALUE)
1098 sel->evaluate = &_gmx_sel_evaluate_static;
1102 case SEL_EXPRESSION:
1103 if (!(sel->flags & SEL_DYNAMIC) && sel->u.expr.method
1104 && sel->u.expr.method->init_frame)
1106 sel->flags |= SEL_INITFRAME;
1108 sel->evaluate = &_gmx_sel_evaluate_method;
1111 case SEL_ARITHMETIC:
1112 sel->evaluate = &_gmx_sel_evaluate_arithmetic;
1116 if (sel->v.type != NO_VALUE)
1118 sel->evaluate = &_gmx_sel_evaluate_modifier;
1123 switch (sel->u.boolt)
1125 case BOOL_NOT: sel->evaluate = &_gmx_sel_evaluate_not; break;
1126 case BOOL_AND: sel->evaluate = &_gmx_sel_evaluate_and; break;
1127 case BOOL_OR: sel->evaluate = &_gmx_sel_evaluate_or; break;
1129 GMX_THROW(gmx::NotImplementedError("xor expressions not implemented"));
1134 sel->evaluate = &_gmx_sel_evaluate_root;
1138 sel->evaluate = ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
1139 ? &_gmx_sel_evaluate_subexpr_simple
1140 : &_gmx_sel_evaluate_subexpr);
1143 case SEL_SUBEXPRREF:
1144 sel->evaluate = ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
1145 ? &_gmx_sel_evaluate_subexprref_simple
1146 : &_gmx_sel_evaluate_subexprref);
1150 GMX_THROW(gmx::APIError("Unresolved group reference in compilation"));
1152 sel->cdata->evaluate = sel->evaluate;
1156 * Sets the memory pool for selection elements that can use it.
1158 * \param sel Root of the selection subtree to process.
1159 * \param[in] mempool Memory pool to use.
1162 setup_memory_pooling(const SelectionTreeElementPointer &sel,
1163 gmx_sel_mempool_t *mempool)
1165 if (sel->type != SEL_SUBEXPRREF)
1167 SelectionTreeElementPointer child = sel->child;
1170 if ((sel->type == SEL_BOOLEAN && (child->flags & SEL_DYNAMIC))
1171 || (sel->type == SEL_ARITHMETIC && child->type != SEL_CONST
1172 && !(child->flags & SEL_SINGLEVAL))
1173 || (sel->type == SEL_SUBEXPR
1174 && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)))
1176 child->mempool = mempool;
1177 if (child->type == SEL_SUBEXPRREF
1178 && (child->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
1180 child->child->child->mempool = mempool;
1183 setup_memory_pooling(child, mempool);
1184 child = child->next;
1190 * Prepares the selection (sub)tree for evaluation.
1192 * \param[in,out] sel Root of the selection subtree to prepare.
1194 * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
1195 * structure if required.
1198 init_item_evaloutput(const SelectionTreeElementPointer &sel)
1200 GMX_ASSERT(!(sel->child == NULL &&
1201 (sel->type == SEL_SUBEXPRREF || sel->type == SEL_SUBEXPR)),
1202 "Subexpression elements should always have a child element");
1204 /* Process children. */
1205 if (sel->type != SEL_SUBEXPRREF)
1207 SelectionTreeElementPointer child = sel->child;
1210 init_item_evaloutput(child);
1211 child = child->next;
1215 if (sel->type == SEL_SUBEXPR
1216 && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
1218 sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1219 if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1221 _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
1224 else if (sel->type == SEL_SUBEXPR
1225 && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
1227 sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
1228 sel->cdata->evaluate = sel->evaluate;
1229 sel->child->mempool = NULL;
1230 sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1231 if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1233 _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
1236 else if (sel->type == SEL_SUBEXPRREF
1237 && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
1241 _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
1242 sel->child->child->freeValues();
1243 sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1244 sel->child->child->flags |= (sel->flags & SEL_ALLOCDATA);
1245 _gmx_selvalue_setstore(&sel->child->child->v, sel->v.u.ptr);
1247 else if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1249 _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
1251 sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1254 /* Make sure that the group/position structure is allocated. */
1255 if (!sel->v.u.ptr && (sel->flags & SEL_ALLOCVAL))
1257 if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1259 _gmx_selvalue_reserve(&sel->v, 1);
1266 /********************************************************************
1267 * COMPILER DATA INITIALIZATION
1268 ********************************************************************/
1271 * Allocates memory for the compiler data and initializes the structure.
1273 * \param sel Root of the selection subtree to process.
1276 init_item_compilerdata(const SelectionTreeElementPointer &sel)
1278 /* Allocate the compiler data structure */
1279 snew(sel->cdata, 1);
1281 /* Store the real evaluation method because the compiler will replace it */
1282 sel->cdata->evaluate = sel->evaluate;
1284 /* This will be computed separately. */
1285 sel->cdata->refcount = 0;
1287 /* Initialize the flags */
1288 sel->cdata->flags = SEL_CDATA_STATICEVAL;
1289 if (!(sel->flags & SEL_DYNAMIC))
1291 sel->cdata->flags |= SEL_CDATA_STATIC;
1293 if (sel->type == SEL_SUBEXPR)
1295 sel->cdata->flags |= SEL_CDATA_EVALMAX;
1297 /* Set the full evaluation flag for subexpressions that require it;
1298 * the subexpression has already been initialized, so we can simply
1299 * access its compilation flags.*/
1300 if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
1302 SelectionTreeElementPointer child = sel->child;
1305 if (!(child->flags & SEL_ATOMVAL) && child->child)
1307 child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
1309 child = child->next;
1312 else if (sel->type == SEL_ROOT && sel->child->type == SEL_SUBEXPRREF)
1314 sel->child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
1317 /* Initialize children */
1318 if (sel->type != SEL_SUBEXPRREF)
1320 SelectionTreeElementPointer child = sel->child;
1323 init_item_compilerdata(child);
1324 child = child->next;
1328 /* Determine whether we should evaluate the minimum or the maximum
1329 * for the children of this element. */
1330 if (sel->type == SEL_BOOLEAN)
1334 bEvalMax = (sel->u.boolt == BOOL_AND);
1335 SelectionTreeElementPointer child = sel->child;
1340 child->cdata->flags |= SEL_CDATA_EVALMAX;
1342 else if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT)
1344 child->child->cdata->flags |= SEL_CDATA_EVALMAX;
1346 child = child->next;
1349 else if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER
1350 || sel->type == SEL_SUBEXPR)
1352 SelectionTreeElementPointer child = sel->child;
1355 child->cdata->flags |= SEL_CDATA_EVALMAX;
1356 child = child->next;
1362 * Initializes the static evaluation flag for a selection subtree.
1364 * \param[in,out] sel Root of the selection subtree to process.
1366 * Sets the \c bStaticEval in the compiler data structure:
1367 * for any element for which the evaluation group may depend on the trajectory
1368 * frame, the flag is cleared.
1370 * reorder_boolean_static_children() should have been called.
1373 init_item_staticeval(const SelectionTreeElementPointer &sel)
1375 /* Subexpressions with full evaluation should always have bStaticEval,
1376 * so don't do anything if a reference to them is encountered. */
1377 if (sel->type == SEL_SUBEXPRREF
1378 && (sel->child->cdata->flags & SEL_CDATA_FULLEVAL))
1383 /* Propagate the bStaticEval flag to children if it is not set */
1384 if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
1386 SelectionTreeElementPointer child = sel->child;
1389 if ((sel->type != SEL_EXPRESSION && sel->type != SEL_MODIFIER)
1390 || (child->flags & SEL_ATOMVAL))
1392 if (child->cdata->flags & SEL_CDATA_STATICEVAL)
1394 child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
1395 init_item_staticeval(child);
1398 child = child->next;
1401 else /* bStaticEval is set */
1403 /* For boolean expressions, any expression after the first dynamic
1404 * expression should not have bStaticEval. */
1405 if (sel->type == SEL_BOOLEAN)
1407 SelectionTreeElementPointer child = sel->child;
1408 while (child && !(child->flags & SEL_DYNAMIC))
1410 child = child->next;
1414 child = child->next;
1418 child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
1419 child = child->next;
1423 /* Process the children */
1424 SelectionTreeElementPointer child = sel->child;
1427 init_item_staticeval(child);
1428 child = child->next;
1434 * Compute reference counts for subexpressions.
1436 * \param sel Root of the selection subtree to process.
1439 init_item_subexpr_refcount(const SelectionTreeElementPointer &sel)
1441 // Reset the counter when the subexpression is first encountered.
1442 if (sel->type == SEL_ROOT && sel->child->type == SEL_SUBEXPR
1443 && sel->child->cdata)
1445 sel->child->cdata->refcount = 0;
1448 if (sel->type == SEL_SUBEXPRREF)
1450 ++sel->child->cdata->refcount;
1454 SelectionTreeElementPointer child = sel->child;
1457 init_item_subexpr_refcount(child);
1458 child = child->next;
1464 * Initializes compiler flags for subexpressions.
1466 * \param sel Root of the selection subtree to process.
1469 init_item_subexpr_flags(const SelectionTreeElementPointer &sel)
1471 if (sel->type == SEL_SUBEXPR)
1473 if (sel->cdata->refcount == 1)
1475 sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
1477 else if (!(sel->cdata->flags & SEL_CDATA_FULLEVAL))
1479 sel->cdata->flags |= SEL_CDATA_COMMONSUBEXPR;
1482 else if (sel->type == SEL_SUBEXPRREF
1483 && (sel->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
1485 sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
1488 /* Process children, but only follow subexpression references if the
1489 * common subexpression flag needs to be propagated. */
1490 if (sel->type != SEL_SUBEXPRREF
1491 || ((sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
1492 && !(sel->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)))
1494 SelectionTreeElementPointer child = sel->child;
1497 if (!(child->cdata->flags & SEL_CDATA_COMMONSUBEXPR))
1499 if (sel->type != SEL_EXPRESSION || (child->flags & SEL_ATOMVAL))
1501 child->cdata->flags |=
1502 (sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR);
1504 init_item_subexpr_flags(child);
1506 child = child->next;
1512 * Initializes the gmin and gmax fields of the compiler data structure.
1514 * \param sel Root of the selection subtree to process.
1517 init_item_minmax_groups(const SelectionTreeElementPointer &sel)
1519 /* Process children. */
1520 if (sel->type != SEL_SUBEXPRREF)
1522 SelectionTreeElementPointer child = sel->child;
1525 init_item_minmax_groups(child);
1526 child = child->next;
1530 /* Initialize the minimum and maximum evaluation groups. */
1531 if (sel->type != SEL_ROOT && sel->v.type != NO_VALUE)
1533 if (sel->v.type == GROUP_VALUE
1534 && (sel->cdata->flags & SEL_CDATA_STATIC))
1536 sel->cdata->gmin = sel->v.u.g;
1537 sel->cdata->gmax = sel->v.u.g;
1539 else if (sel->type == SEL_SUBEXPR
1540 && ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
1541 || (sel->cdata->flags & SEL_CDATA_FULLEVAL)))
1543 GMX_ASSERT(sel->child,
1544 "Subexpression elements should always have a child element");
1545 sel->cdata->gmin = sel->child->cdata->gmin;
1546 sel->cdata->gmax = sel->child->cdata->gmax;
1550 sel->cdata->flags |= SEL_CDATA_MINMAXALLOC | SEL_CDATA_DOMINMAX;
1551 snew(sel->cdata->gmin, 1);
1552 snew(sel->cdata->gmax, 1);
1558 /********************************************************************
1559 * EVALUATION GROUP INITIALIZATION
1560 ********************************************************************/
1563 * Initializes evaluation groups for root items.
1565 * \param[in,out] sc Selection collection data.
1567 * The evaluation group of each \ref SEL_ROOT element corresponding to a
1568 * selection in \p sc is set to NULL. The evaluation grop for \ref SEL_ROOT
1569 * elements corresponding to subexpressions that need full evaluation is set
1573 initialize_evalgrps(gmx_ana_selcollection_t *sc)
1575 SelectionTreeElementPointer root = sc->root;
1578 GMX_RELEASE_ASSERT(root->child,
1579 "Root elements should always have a child");
1580 if (root->child->type != SEL_SUBEXPR
1581 || (root->child->v.type != GROUP_VALUE && !(root->flags & SEL_ATOMVAL)))
1583 gmx_ana_index_set(&root->u.cgrp, -1, 0, root->u.cgrp.name, 0);
1585 else if (root->child->cdata->flags & SEL_CDATA_FULLEVAL)
1587 gmx_ana_index_set(&root->u.cgrp, sc->gall.isize, sc->gall.index,
1588 root->u.cgrp.name, 0);
1595 /********************************************************************
1597 ********************************************************************/
1600 * Marks a subtree completely dynamic or undoes such a change.
1602 * \param sel Selection subtree to mark.
1603 * \param[in] bDynamic If true, the \p bStatic flag of the whole
1604 * selection subtree is cleared. If false, the flag is restored to
1605 * using \ref SEL_DYNAMIC.
1607 * Does not descend into parameters of methods unless the parameters
1608 * are evaluated for each atom.
1611 mark_subexpr_dynamic(const SelectionTreeElementPointer &sel,
1614 if (!bDynamic && !(sel->flags & SEL_DYNAMIC))
1616 sel->cdata->flags |= SEL_CDATA_STATIC;
1620 sel->cdata->flags &= ~SEL_CDATA_STATIC;
1622 SelectionTreeElementPointer child = sel->child;
1625 if (sel->type != SEL_EXPRESSION || child->type != SEL_SUBEXPRREF
1626 || (child->u.param->flags & SPAR_ATOMVAL))
1628 mark_subexpr_dynamic(child, bDynamic);
1630 child = child->next;
1635 * Frees memory for subexpressions that are no longer needed.
1637 * \param sel Selection subtree to check.
1639 * Checks whether the subtree rooted at \p sel refers to any \ref SEL_SUBEXPR
1640 * elements that are not referred to by anything else except their own root
1641 * element. If such elements are found, all memory allocated for them is freed
1642 * except the actual element. The element is left because otherwise a dangling
1643 * pointer would be left at the root element, which is not traversed by this
1644 * function. Later compilation passes remove the stub elements.
1647 release_subexpr_memory(const SelectionTreeElementPointer &sel)
1649 if (sel->type == SEL_SUBEXPRREF)
1651 const SelectionTreeElementPointer &subexpr = sel->child;
1652 if (subexpr.use_count() == 2)
1654 release_subexpr_memory(subexpr);
1656 subexpr->child.reset();
1657 subexpr->freeValues();
1658 subexpr->freeExpressionData();
1659 subexpr->freeCompilerData();
1664 SelectionTreeElementPointer child = sel->child;
1667 release_subexpr_memory(child);
1668 child = child->next;
1674 * Makes an evaluated selection element static.
1676 * \param sel Selection element to make static.
1678 * The evaluated value becomes the value of the static element.
1679 * The element type is changed to SEL_CONST and the children are
1683 make_static(const SelectionTreeElementPointer &sel)
1685 /* If this is a subexpression reference and the data is stored in the
1686 * child, we transfer data ownership before doing anything else. */
1687 if (sel->type == SEL_SUBEXPRREF
1688 && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
1690 if (sel->child->child->flags & SEL_ALLOCDATA)
1692 sel->flags |= SEL_ALLOCDATA;
1693 sel->child->child->flags &= ~SEL_ALLOCDATA;
1695 if (sel->child->child->flags & SEL_ALLOCVAL)
1697 sel->flags |= SEL_ALLOCVAL;
1698 sel->v.nalloc = sel->child->child->v.nalloc;
1699 sel->child->child->flags &= ~SEL_ALLOCVAL;
1700 sel->child->child->v.nalloc = -1;
1703 /* Free the children. */
1704 release_subexpr_memory(sel);
1706 /* Free the expression data as it is no longer needed */
1707 sel->freeExpressionData();
1708 /* Make the item static */
1709 sel->type = SEL_CONST;
1710 sel->evaluate = NULL;
1711 sel->cdata->evaluate = NULL;
1712 /* Set the group value.
1713 * freeExpressionData() frees the cgrp group, so we can just override it.
1715 if (sel->v.type == GROUP_VALUE)
1717 gmx_ana_index_set(&sel->u.cgrp, sel->v.u.g->isize, sel->v.u.g->index, NULL, 0);
1722 * Evaluates a constant expression during analyze_static().
1724 * \param[in] data Evaluation data.
1725 * \param[in,out] sel Selection to process.
1726 * \param[in] g The evaluation group.
1727 * \returns 0 on success, a non-zero error code on error.
1730 process_const(gmx_sel_evaluate_t *data,
1731 const SelectionTreeElementPointer &sel,
1734 if (sel->v.type == GROUP_VALUE)
1736 if (sel->cdata->evaluate)
1738 sel->cdata->evaluate(data, sel, g);
1741 /* Other constant expressions do not need evaluation */
1745 * Sets the parameter value pointer for \ref SEL_SUBEXPRREF params.
1747 * \param[in,out] sel Selection to process.
1749 * Copies the value pointer of \p sel to \c sel->u.param if one is present
1750 * and should receive the value from the compiler
1751 * (most parameter values are handled during parsing).
1752 * If \p sel is not of type \ref SEL_SUBEXPRREF, or if \c sel->u.param is NULL,
1753 * the function does nothing.
1754 * Also, if the \c sel->u.param does not have \ref SPAR_VARNUM or
1755 * \ref SPAR_ATOMVAL, the function returns immediately.
1758 store_param_val(const SelectionTreeElementPointer &sel)
1760 /* Return immediately if there is no parameter. */
1761 if (sel->type != SEL_SUBEXPRREF || !sel->u.param)
1766 /* Or if the value does not need storing. */
1767 if (!(sel->u.param->flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
1772 if (sel->v.type == INT_VALUE || sel->v.type == REAL_VALUE
1773 || sel->v.type == STR_VALUE)
1775 _gmx_selvalue_setstore(&sel->u.param->val, sel->v.u.ptr);
1780 * Handles the initialization of a selection method during analyze_static() pass.
1782 * \param[in,out] sel Selection element to process.
1783 * \param[in] top Topology structure.
1784 * \param[in] isize Size of the evaluation group for the element.
1785 * \returns 0 on success, a non-zero error code on return.
1787 * Calls sel_initfunc() (and possibly sel_outinitfunc()) to initialize the
1789 * If no \ref SPAR_ATOMVAL parameters are present, multiple initialization
1790 * is prevented by using \ref SEL_METHODINIT and \ref SEL_OUTINIT flags.
1793 init_method(const SelectionTreeElementPointer &sel, t_topology *top, int isize)
1795 /* Find out whether there are any atom-valued parameters */
1796 bool bAtomVal = false;
1797 SelectionTreeElementPointer child = sel->child;
1800 if (child->flags & SEL_ATOMVAL)
1804 child = child->next;
1807 /* Initialize the method */
1808 if (sel->u.expr.method->init
1809 && (bAtomVal || !(sel->flags & SEL_METHODINIT)))
1811 sel->flags |= SEL_METHODINIT;
1812 sel->u.expr.method->init(top, sel->u.expr.method->nparams,
1813 sel->u.expr.method->param, sel->u.expr.mdata);
1815 if (bAtomVal || !(sel->flags & SEL_OUTINIT))
1817 sel->flags |= SEL_OUTINIT;
1818 if (sel->u.expr.method->outinit)
1820 sel->u.expr.method->outinit(top, &sel->v, sel->u.expr.mdata);
1821 if (sel->v.type != POS_VALUE && sel->v.type != GROUP_VALUE
1822 && !(sel->flags & SEL_VARNUMVAL))
1824 alloc_selection_data(sel, isize, true);
1829 GMX_RELEASE_ASSERT(sel->v.type != POS_VALUE,
1830 "Output initialization must be provided for "
1831 "position-valued selection methods");
1832 GMX_RELEASE_ASSERT(!(sel->flags & SEL_VARNUMVAL),
1833 "Output initialization must be provided for "
1834 "SMETH_VARNUMVAL selection methods");
1835 alloc_selection_data(sel, isize, true);
1836 if ((sel->flags & SEL_DYNAMIC)
1837 && sel->v.type != GROUP_VALUE && sel->v.type != POS_VALUE)
1841 /* If the method is char-valued, pre-allocate the strings. */
1842 if (sel->u.expr.method->flags & SMETH_CHARVAL)
1846 /* A sanity check */
1847 if (sel->v.type != STR_VALUE)
1849 GMX_THROW(gmx::InternalError("Char-valued selection method in non-string element"));
1851 sel->flags |= SEL_ALLOCDATA;
1852 for (i = 0; i < isize; ++i)
1854 if (sel->v.u.s[i] == NULL)
1856 snew(sel->v.u.s[i], 2);
1861 /* Clear the values for dynamic output to avoid valgrind warnings. */
1862 if ((sel->flags & SEL_DYNAMIC) && sel->v.type == REAL_VALUE)
1866 for (i = 0; i < sel->v.nr; ++i)
1868 sel->v.u.r[i] = 0.0;
1875 * Evaluates the static part of a boolean expression.
1877 * \param[in] data Evaluation data.
1878 * \param[in,out] sel Boolean selection element whose children should be
1880 * \param[in] g The evaluation group.
1881 * \returns 0 on success, a non-zero error code on error.
1883 * reorder_item_static_children() should have been called.
1886 evaluate_boolean_static_part(gmx_sel_evaluate_t *data,
1887 const SelectionTreeElementPointer &sel,
1890 /* Find the last static subexpression */
1891 SelectionTreeElementPointer child = sel->child;
1892 while (child->next && (child->next->cdata->flags & SEL_CDATA_STATIC))
1894 child = child->next;
1896 if (!(child->cdata->flags & SEL_CDATA_STATIC))
1901 /* Evalute the static part if there is more than one expression */
1902 if (child != sel->child)
1904 SelectionTreeElementPointer next = child->next;
1905 child->next.reset();
1906 sel->cdata->evaluate(data, sel, g);
1907 /* Replace the subexpressions with the result */
1908 child.reset(new SelectionTreeElement(SEL_CONST));
1909 child->flags = SEL_FLAGSSET | SEL_SINGLEVAL | SEL_ALLOCVAL | SEL_ALLOCDATA;
1910 _gmx_selelem_set_vtype(child, GROUP_VALUE);
1911 child->evaluate = NULL;
1912 _gmx_selvalue_reserve(&child->v, 1);
1913 gmx_ana_index_copy(child->v.u.g, sel->v.u.g, true);
1914 init_item_compilerdata(child);
1915 init_item_minmax_groups(child);
1916 child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
1917 child->cdata->flags |= sel->cdata->flags & SEL_CDATA_STATICEVAL;
1919 // Frees the old static subexpressions.
1922 else if (child->evaluate)
1924 child->evaluate(data, child, g);
1926 /* Set the evaluation function for the constant element.
1927 * We never need to evaluate the element again during compilation,
1928 * but we may need to evaluate the static part again if the
1929 * expression is not an OR with a static evaluation group.
1930 * If we reach here with a NOT expression, the NOT expression
1931 * is also static, and will be made a constant later, so don't waste
1932 * time copying the group. */
1933 child->evaluate = NULL;
1934 if (sel->u.boolt == BOOL_NOT
1935 || ((sel->cdata->flags & SEL_CDATA_STATICEVAL)
1936 && sel->u.boolt == BOOL_OR))
1938 child->cdata->evaluate = NULL;
1942 child->cdata->evaluate = &_gmx_sel_evaluate_static;
1943 /* The cgrp has only been allocated if it originated from an
1944 * external index group. In that case, we need special handling
1945 * to preserve the name of the group and to not leak memory.
1946 * If cgrp has been set in make_static(), it is not allocated,
1947 * and hence we can overwrite it safely. */
1948 if (child->u.cgrp.nalloc_index > 0)
1950 char *name = child->u.cgrp.name;
1951 gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, false);
1952 gmx_ana_index_squeeze(&child->u.cgrp);
1953 child->u.cgrp.name = name;
1957 gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, true);
1963 * Evaluates the minimum and maximum groups for a boolean expression.
1965 * \param[in] sel \ref SEL_BOOLEAN element currently being evaluated.
1966 * \param[in] g Group for which \p sel has been evaluated.
1967 * \param[out] gmin Largest subset of the possible values of \p sel.
1968 * \param[out] gmax Smallest superset of the possible values of \p sel.
1970 * This is a helper function for analyze_static() that is called for
1971 * dynamic \ref SEL_BOOLEAN elements after they have been evaluated.
1972 * It uses the minimum and maximum groups of the children to calculate
1973 * the minimum and maximum groups for \p sel, and also updates the static
1974 * part of \p sel (which is in the first child) if the children give
1977 * This function may allocate some extra memory for \p gmin and \p gmax,
1978 * but as these groups are freed at the end of analyze_static() (which is
1979 * reached shortly after this function returns), this should not be a major
1983 evaluate_boolean_minmax_grps(const SelectionTreeElementPointer &sel,
1985 gmx_ana_index_t *gmin, gmx_ana_index_t *gmax)
1987 SelectionTreeElementPointer child;
1989 switch (sel->u.boolt)
1992 gmx_ana_index_reserve(gmin, g->isize);
1993 gmx_ana_index_reserve(gmax, g->isize);
1994 gmx_ana_index_difference(gmax, g, sel->child->cdata->gmin);
1995 gmx_ana_index_difference(gmin, g, sel->child->cdata->gmax);
1999 gmx_ana_index_copy(gmin, sel->child->cdata->gmin, true);
2000 gmx_ana_index_copy(gmax, sel->child->cdata->gmax, true);
2001 child = sel->child->next;
2002 while (child && gmax->isize > 0)
2004 gmx_ana_index_intersection(gmin, gmin, child->cdata->gmin);
2005 gmx_ana_index_intersection(gmax, gmax, child->cdata->gmax);
2006 child = child->next;
2008 /* Update the static part if other expressions limit it */
2009 if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
2010 && sel->child->v.u.g->isize > gmax->isize)
2012 gmx_ana_index_copy(sel->child->v.u.g, gmax, false);
2013 gmx_ana_index_squeeze(sel->child->v.u.g);
2014 if (sel->child->u.cgrp.isize > 0)
2016 gmx_ana_index_copy(&sel->child->u.cgrp, gmax, false);
2017 gmx_ana_index_squeeze(&sel->child->u.cgrp);
2023 /* We can assume here that the gmin of children do not overlap
2024 * because of the way _gmx_sel_evaluate_or() works. */
2025 gmx_ana_index_reserve(gmin, g->isize);
2026 gmx_ana_index_reserve(gmax, g->isize);
2027 gmx_ana_index_copy(gmin, sel->child->cdata->gmin, false);
2028 gmx_ana_index_copy(gmax, sel->child->cdata->gmax, false);
2029 child = sel->child->next;
2030 while (child && gmin->isize < g->isize)
2032 gmx_ana_index_merge(gmin, gmin, child->cdata->gmin);
2033 gmx_ana_index_union(gmax, gmax, child->cdata->gmax);
2034 child = child->next;
2036 /* Update the static part if other expressions have static parts
2037 * that are not included. */
2038 if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
2039 && sel->child->v.u.g->isize < gmin->isize)
2041 GMX_RELEASE_ASSERT(sel->child->type == SEL_CONST,
2042 "The first child should have already been evaluated "
2043 "to a constant expression");
2044 gmx_ana_index_reserve(sel->child->v.u.g, gmin->isize);
2045 gmx_ana_index_copy(sel->child->v.u.g, gmin, false);
2046 if (sel->child->u.cgrp.nalloc_index > 0)
2048 /* Keep the name as in evaluate_boolean_static_part(). */
2049 char *name = sel->child->u.cgrp.name;
2050 gmx_ana_index_reserve(&sel->child->u.cgrp, gmin->isize);
2051 gmx_ana_index_copy(&sel->child->u.cgrp, gmin, false);
2052 sel->child->u.cgrp.name = name;
2056 GMX_RELEASE_ASSERT(sel->child->u.cgrp.index == sel->child->v.u.g->index,
2057 "If not allocated, the static group should equal the value");
2058 sel->child->u.cgrp.isize = sel->child->v.u.g->isize;
2063 case BOOL_XOR: /* Should not be reached */
2064 GMX_THROW(gmx::NotImplementedError("xor expressions not implemented"));
2070 * Evaluates the static parts of \p sel and analyzes the structure.
2072 * \param[in] data Evaluation data.
2073 * \param[in,out] sel Selection currently being evaluated.
2074 * \param[in] g Group for which \p sel should be evaluated.
2075 * \returns 0 on success, a non-zero error code on error.
2077 * This function is used as the replacement for the
2078 * gmx::SelectionTreeElement::evaluate function pointer.
2079 * It does the single most complex task in the compiler: after all elements
2080 * have been processed, the \p gmin and \p gmax fields of \p t_compiler_data
2081 * have been properly initialized, enough memory has been allocated for
2082 * storing the value of each expression, and the static parts of the
2083 * expressions have been evaluated.
2084 * The above is exactly true only for elements other than subexpressions:
2085 * another pass is required for subexpressions that are referred to more than
2086 * once and whose evaluation group is not known in advance.
2089 analyze_static(gmx_sel_evaluate_t *data,
2090 const SelectionTreeElementPointer &sel,
2095 if (sel->type != SEL_ROOT && g)
2097 alloc_selection_data(sel, g->isize, false);
2100 bDoMinMax = (sel->cdata->flags & SEL_CDATA_DOMINMAX);
2101 if (sel->type != SEL_SUBEXPR && bDoMinMax)
2103 gmx_ana_index_deinit(sel->cdata->gmin);
2104 gmx_ana_index_deinit(sel->cdata->gmax);
2107 /* TODO: This switch is awfully long... */
2111 process_const(data, sel, g);
2114 case SEL_EXPRESSION:
2116 _gmx_sel_evaluate_method_params(data, sel, g);
2117 init_method(sel, data->top, g ? g->isize : 0);
2118 if (!(sel->flags & SEL_DYNAMIC))
2120 sel->cdata->evaluate(data, sel, g);
2121 if (sel->cdata->flags & SEL_CDATA_STATIC)
2128 /* Modifiers need to be evaluated even though they process
2129 * positions to get the modified output groups from the
2130 * maximum possible selections. */
2131 if (sel->type == SEL_MODIFIER)
2133 sel->cdata->evaluate(data, sel, g);
2137 gmx_ana_index_copy(sel->cdata->gmax, g, true);
2143 if (!(sel->flags & SEL_DYNAMIC))
2145 sel->cdata->evaluate(data, sel, g);
2146 if (sel->cdata->flags & SEL_CDATA_STATIC)
2153 /* Evalute the static part if there is more than one expression */
2154 evaluate_boolean_static_part(data, sel, g);
2156 /* Evaluate the selection.
2157 * If the type is boolean, we must explicitly handle the
2158 * static part evaluated in evaluate_boolean_static_part()
2159 * here because g may be larger. */
2160 if (sel->u.boolt == BOOL_AND && sel->child->type == SEL_CONST)
2162 sel->cdata->evaluate(data, sel, sel->child->v.u.g);
2166 sel->cdata->evaluate(data, sel, g);
2169 /* Evaluate minimal and maximal selections */
2170 evaluate_boolean_minmax_grps(sel, g, sel->cdata->gmin,
2175 case SEL_ARITHMETIC:
2176 sel->cdata->evaluate(data, sel, g);
2177 if (!(sel->flags & SEL_DYNAMIC))
2179 if (sel->cdata->flags & SEL_CDATA_STATIC)
2186 gmx_ana_index_copy(sel->cdata->gmax, g, true);
2191 sel->cdata->evaluate(data, sel, g);
2195 if (sel->cdata->flags & (SEL_CDATA_SIMPLESUBEXPR | SEL_CDATA_FULLEVAL))
2197 sel->cdata->evaluate(data, sel, g);
2198 _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
2200 else if (sel->u.cgrp.isize == 0)
2202 GMX_ASSERT(g, "group cannot be null");
2203 gmx_ana_index_reserve(&sel->u.cgrp, g->isize);
2204 sel->cdata->evaluate(data, sel, g);
2207 gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, true);
2208 gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, true);
2213 int isize = gmx_ana_index_difference_size(g, &sel->u.cgrp);
2216 isize += sel->u.cgrp.isize;
2217 gmx_ana_index_reserve(&sel->u.cgrp, isize);
2218 alloc_selection_data(sel, isize, false);
2220 sel->cdata->evaluate(data, sel, g);
2221 if (isize > 0 && bDoMinMax)
2223 gmx_ana_index_reserve(sel->cdata->gmin,
2224 sel->cdata->gmin->isize
2225 + sel->child->cdata->gmin->isize);
2226 gmx_ana_index_reserve(sel->cdata->gmax,
2227 sel->cdata->gmax->isize
2228 + sel->child->cdata->gmax->isize);
2229 gmx_ana_index_merge(sel->cdata->gmin, sel->cdata->gmin,
2230 sel->child->cdata->gmin);
2231 gmx_ana_index_merge(sel->cdata->gmax, sel->cdata->gmax,
2232 sel->child->cdata->gmax);
2237 case SEL_SUBEXPRREF:
2238 if (!g && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
2240 /* The subexpression should have been evaluated if g is NULL
2241 * (i.e., this is a method parameter or a direct value of a
2243 if (sel->v.type == POS_VALUE)
2245 alloc_selection_pos_data(sel);
2249 alloc_selection_data(sel, sel->child->cdata->gmax->isize, true);
2252 sel->cdata->evaluate(data, sel, g);
2253 if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
2254 && (sel->child->child->flags & SEL_ALLOCVAL))
2256 _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
2258 /* Store the parameter value if required */
2259 store_param_val(sel);
2260 if (!(sel->flags & SEL_DYNAMIC))
2262 if (sel->cdata->flags & SEL_CDATA_STATIC)
2269 if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR) || !g)
2271 gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, true);
2272 gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, true);
2276 gmx_ana_index_reserve(sel->cdata->gmin,
2277 min(g->isize, sel->child->cdata->gmin->isize));
2278 gmx_ana_index_reserve(sel->cdata->gmax,
2279 min(g->isize, sel->child->cdata->gmax->isize));
2280 gmx_ana_index_intersection(sel->cdata->gmin,
2281 sel->child->cdata->gmin, g);
2282 gmx_ana_index_intersection(sel->cdata->gmax,
2283 sel->child->cdata->gmax, g);
2288 case SEL_GROUPREF: /* Should not be reached */
2289 GMX_THROW(gmx::APIError("Unresolved group reference in compilation"));
2292 /* Update the minimal and maximal evaluation groups */
2295 gmx_ana_index_squeeze(sel->cdata->gmin);
2296 gmx_ana_index_squeeze(sel->cdata->gmax);
2297 sfree(sel->cdata->gmin->name);
2298 sfree(sel->cdata->gmax->name);
2299 sel->cdata->gmin->name = NULL;
2300 sel->cdata->gmax->name = NULL;
2303 /* Replace the result of the evaluation */
2304 /* This is not necessary for subexpressions or for boolean negations
2305 * because the evaluation function already has done it properly. */
2306 if (sel->v.type == GROUP_VALUE && (sel->flags & SEL_DYNAMIC)
2307 && sel->type != SEL_SUBEXPR
2308 && !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
2310 if (sel->cdata->flags & SEL_CDATA_EVALMAX)
2312 gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmax, false);
2316 gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmin, false);
2322 /********************************************************************
2323 * EVALUATION GROUP INITIALIZATION
2324 ********************************************************************/
2327 * Initializes the evaluation group for a \ref SEL_ROOT element.
2329 * \param root Root element to initialize.
2330 * \param[in] gall Group of all atoms.
2332 * Checks whether it is necessary to evaluate anything through the root
2333 * element, and either clears the evaluation function or initializes the
2337 init_root_item(const SelectionTreeElementPointer &root,
2338 gmx_ana_index_t *gall)
2340 const SelectionTreeElementPointer &expr = root->child;
2341 /* Subexpressions with non-static evaluation group should not be
2342 * evaluated by the root, and neither should be single-reference
2343 * subexpressions that don't evaluate for all atoms. */
2344 if (expr->type == SEL_SUBEXPR
2345 && (!(root->child->cdata->flags & SEL_CDATA_STATICEVAL)
2346 || ((root->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
2347 && !(root->child->cdata->flags & SEL_CDATA_FULLEVAL))))
2349 root->evaluate = NULL;
2352 root->cdata->evaluate = NULL;
2356 /* Set the evaluation group */
2357 char *name = root->u.cgrp.name;
2360 /* Non-atom-valued non-group expressions don't care about the group, so
2361 * don't allocate any memory for it. */
2362 if ((expr->flags & SEL_VARNUMVAL)
2363 || ((expr->flags & SEL_SINGLEVAL) && expr->v.type != GROUP_VALUE))
2365 gmx_ana_index_set(&root->u.cgrp, -1, NULL, NULL, 0);
2367 else if (expr->cdata->gmax->isize == gall->isize)
2369 /* Save some memory by only referring to the global group. */
2370 gmx_ana_index_set(&root->u.cgrp, gall->isize, gall->index, NULL, 0);
2374 gmx_ana_index_copy(&root->u.cgrp, expr->cdata->gmax, true);
2376 /* For selections, store the maximum group for
2377 * gmx_ana_selcollection_evaluate_fin() as the value of the root
2378 * element (unused otherwise). */
2379 if (expr->type != SEL_SUBEXPR && expr->v.u.p->g)
2381 SelectionTreeElementPointer child = expr;
2383 /* TODO: This code is copied from parsetree.c; it would be better
2384 * to have this hardcoded only in one place. */
2385 while (child->type == SEL_MODIFIER)
2387 child = child->child;
2388 if (child->type == SEL_SUBEXPRREF)
2390 child = child->child->child;
2393 if (child->type == SEL_SUBEXPRREF)
2395 child = child->child->child;
2397 if (child->child->flags & SEL_DYNAMIC)
2399 _gmx_selelem_set_vtype(root, GROUP_VALUE);
2400 root->flags |= (SEL_ALLOCVAL | SEL_ALLOCDATA);
2401 _gmx_selvalue_reserve(&root->v, 1);
2402 gmx_ana_index_copy(root->v.u.g, expr->v.u.p->g, true);
2408 gmx_ana_index_clear(&root->u.cgrp);
2410 root->u.cgrp.name = name;
2414 /********************************************************************
2415 * FINAL SUBEXPRESSION OPTIMIZATION
2416 ********************************************************************/
2419 * Optimizes subexpression evaluation.
2421 * \param sel Root of the selection subtree to process.
2423 * Optimizes away some unnecessary evaluation of subexpressions that are only
2427 postprocess_item_subexpressions(const SelectionTreeElementPointer &sel)
2429 GMX_ASSERT(!(sel->child == NULL &&
2430 (sel->type == SEL_SUBEXPRREF || sel->type == SEL_SUBEXPR)),
2431 "Subexpression elements should always have a child element");
2433 /* Process children. */
2434 if (sel->type != SEL_SUBEXPRREF)
2436 SelectionTreeElementPointer child = sel->child;
2439 postprocess_item_subexpressions(child);
2440 child = child->next;
2444 /* Replace the evaluation function of statically evaluated subexpressions
2445 * for which the static group was not known in advance. */
2446 if (sel->type == SEL_SUBEXPR && sel->cdata->refcount > 1
2447 && (sel->cdata->flags & SEL_CDATA_STATICEVAL)
2448 && !(sel->cdata->flags & SEL_CDATA_FULLEVAL))
2452 /* We need to free memory allocated for the group, because it is no
2453 * longer needed (and would be lost on next call to the evaluation
2454 * function). But we need to preserve the name. */
2455 name = sel->u.cgrp.name;
2456 gmx_ana_index_deinit(&sel->u.cgrp);
2457 sel->u.cgrp.name = name;
2459 sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
2460 sel->cdata->evaluate = sel->evaluate;
2462 sel->child->freeValues();
2463 sel->child->mempool = NULL;
2464 _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
2465 sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
2468 /* Adjust memory allocation flags for subexpressions that are used only
2469 * once. This is not strictly necessary, but we do it to have the memory
2470 * managed consistently for all types of subexpressions. */
2471 if (sel->type == SEL_SUBEXPRREF
2472 && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
2474 if (sel->child->child->flags & SEL_ALLOCVAL)
2476 sel->flags |= SEL_ALLOCVAL;
2477 sel->flags |= (sel->child->child->flags & SEL_ALLOCDATA);
2478 sel->v.nalloc = sel->child->child->v.nalloc;
2479 sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
2480 sel->child->child->v.nalloc = -1;
2484 /* Do the same for subexpressions that are evaluated at once for all atoms. */
2485 if (sel->type == SEL_SUBEXPR
2486 && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
2487 && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
2489 sel->flags |= SEL_ALLOCVAL;
2490 sel->flags |= (sel->child->flags & SEL_ALLOCDATA);
2491 sel->v.nalloc = sel->child->v.nalloc;
2492 sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
2493 sel->child->v.nalloc = -1;
2498 /********************************************************************
2499 * COM CALCULATION INITIALIZATION
2500 ********************************************************************/
2503 * Initializes COM/COG calculation for method expressions that require it.
2505 * \param sel Selection subtree to process.
2506 * \param[in,out] pcc Position calculation collection to use.
2507 * \param[in] type Default position calculation type.
2508 * \param[in] flags Flags for default position calculation.
2510 * Searches recursively through the selection tree for dynamic
2511 * \ref SEL_EXPRESSION elements that define the \c gmx_ana_selmethod_t::pupdate
2513 * For each such element found, position calculation is initialized
2514 * for the maximal evaluation group.
2515 * The type of the calculation is determined by \p type and \p flags.
2516 * No calculation is initialized if \p type equals \ref POS_ATOM and
2517 * the method also defines the \c gmx_ana_selmethod_t::update method.
2520 init_item_comg(const SelectionTreeElementPointer &sel,
2521 gmx::PositionCalculationCollection *pcc,
2522 e_poscalc_t type, int flags)
2524 /* Initialize COM calculation for dynamic selections now that we know the maximal evaluation group */
2525 if (sel->type == SEL_EXPRESSION && sel->u.expr.method
2526 && sel->u.expr.method->pupdate)
2528 if (!sel->u.expr.method->update || type != POS_ATOM)
2530 /* Create a default calculation if one does not yet exist */
2532 if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
2534 cflags |= POS_DYNAMIC;
2536 if (!sel->u.expr.pc)
2539 sel->u.expr.pc = pcc->createCalculation(type, cflags);
2543 gmx_ana_poscalc_set_flags(sel->u.expr.pc, cflags);
2545 gmx_ana_poscalc_set_maxindex(sel->u.expr.pc, sel->cdata->gmax);
2546 snew(sel->u.expr.pos, 1);
2547 gmx_ana_poscalc_init_pos(sel->u.expr.pc, sel->u.expr.pos);
2551 /* Call recursively for all children unless the children have already been processed */
2552 if (sel->type != SEL_SUBEXPRREF)
2554 SelectionTreeElementPointer child = sel->child;
2557 init_item_comg(child, pcc, type, flags);
2558 child = child->next;
2564 /********************************************************************
2565 * COMPILER DATA FREEING
2566 ********************************************************************/
2569 * Frees the allocated compiler data recursively.
2571 * \param sel Root of the selection subtree to process.
2573 * Frees the data allocated for the compilation process.
2576 free_item_compilerdata(const SelectionTreeElementPointer &sel)
2578 /* Free compilation data */
2579 sel->freeCompilerData();
2581 /* Call recursively for all children unless the children have already been processed */
2582 if (sel->type != SEL_SUBEXPRREF)
2584 SelectionTreeElementPointer child = sel->child;
2587 free_item_compilerdata(child);
2588 child = child->next;
2594 /********************************************************************
2595 * MAIN COMPILATION FUNCTION
2596 ********************************************************************/
2601 SelectionCompiler::SelectionCompiler()
2606 * \param[in,out] coll Selection collection to be compiled.
2607 * \returns 0 on successful compilation, a non-zero error code on error.
2609 * Before compilation, the selection collection should have been initialized
2610 * with gmx_ana_selcollection_parse_*().
2611 * The compiled selection collection can be passed to
2612 * gmx_ana_selcollection_evaluate() to evaluate the selection for a frame.
2613 * If an error occurs, \p sc is cleared.
2615 * The covered fraction information in \p sc is initialized to
2619 SelectionCompiler::compile(SelectionCollection *coll)
2621 gmx_ana_selcollection_t *sc = &coll->impl_->sc_;
2622 gmx_sel_evaluate_t evaldata;
2623 SelectionTreeElementPointer item;
2627 bool bDebug = (coll->impl_->debugLevel_ >= 2
2628 && coll->impl_->debugLevel_ != 3);
2630 /* FIXME: Clean up the collection on exceptions */
2632 sc->mempool = _gmx_sel_mempool_create();
2633 _gmx_sel_evaluate_init(&evaldata, sc->mempool, &sc->gall,
2634 sc->top, NULL, NULL);
2636 /* Clear the symbol table because it is not possible to parse anything
2637 * after compilation, and variable references in the symbol table can
2638 * also mess up the compilation and/or become invalid.
2640 coll->impl_->clearSymbolTable();
2642 /* Loop through selections and initialize position keyword defaults if no
2643 * other value has been provided.
2645 for (i = 0; i < sc->sel.size(); ++i)
2647 gmx::internal::SelectionData &sel = *sc->sel[i];
2648 init_pos_keyword_defaults(&sel.rootElement(),
2649 coll->impl_->spost_.c_str(),
2650 coll->impl_->rpost_.c_str(),
2654 /* Remove any unused variables. */
2655 sc->root = remove_unused_subexpressions(sc->root);
2656 /* Extract subexpressions into separate roots */
2657 sc->root = extract_subexpressions(sc->root);
2659 /* Initialize the evaluation callbacks and process the tree structure
2660 * to conform to the expectations of the callback functions. */
2661 /* Also, initialize and allocate the compiler data structure */
2665 /* Process boolean and arithmetic expressions. */
2666 optimize_boolean_expressions(item);
2667 reorder_boolean_static_children(item);
2668 optimize_arithmetic_expressions(item);
2669 /* Initialize the compiler data */
2670 init_item_compilerdata(item);
2671 init_item_staticeval(item);
2672 init_item_subexpr_refcount(item);
2675 /* Initialize subexpression flags.
2676 * Requires compiler flags for the full tree. */
2680 init_item_subexpr_flags(item);
2683 /* Initialize evaluation.
2684 * Requires subexpression flags. */
2688 init_item_evalfunc(item);
2689 setup_memory_pooling(item, sc->mempool);
2690 init_item_evaloutput(item);
2693 /* Initialize minimum/maximum index groups.
2694 * Requires evaluation output for the full tree. */
2698 init_item_minmax_groups(item);
2701 /* Initialize the evaluation index groups */
2702 initialize_evalgrps(sc);
2706 fprintf(stderr, "\nTree after initial compiler processing:\n");
2707 coll->printTree(stderr, false);
2710 /* Evaluate all static parts of the selection and analyze the tree
2711 * to allocate enough memory to store the value of each dynamic subtree. */
2715 if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
2717 mark_subexpr_dynamic(item->child, true);
2719 set_evaluation_function(item, &analyze_static);
2720 item->evaluate(&evaldata, item, NULL);
2724 /* At this point, static subexpressions no longer have references to them,
2725 * so they can be removed. */
2726 sc->root = remove_unused_subexpressions(sc->root);
2727 // Update the reference counts for consistency (only used for the
2728 // debugging output below).
2732 init_item_subexpr_refcount(item);
2738 fprintf(stderr, "\nTree after first analysis pass:\n");
2739 coll->printTree(stderr, false);
2742 /* Do a second pass to evaluate static parts of common subexpressions */
2746 if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
2748 bool bMinMax = item->child->cdata->flags & SEL_CDATA_DOMINMAX;
2750 mark_subexpr_dynamic(item->child, false);
2751 item->child->u.cgrp.isize = 0;
2752 /* We won't clear item->child->v.u.g here, because it may
2753 * be static, and hence actually point to item->child->cdata->gmax,
2754 * which is used below. We could also check whether this is the
2755 * case and only clear the group otherwise, but because the value
2756 * is actually overwritten immediately in the evaluate call, we
2757 * won't, because similar problems may arise if gmax handling ever
2758 * changes and the check were not updated.
2759 * For the same reason, we clear the min/max flag so that the
2760 * evaluation group doesn't get messed up. */
2761 set_evaluation_function(item, &analyze_static);
2762 item->child->cdata->flags &= ~SEL_CDATA_DOMINMAX;
2763 item->evaluate(&evaldata, item->child, item->child->cdata->gmax);
2766 item->child->cdata->flags |= SEL_CDATA_DOMINMAX;
2772 /* We need a yet another pass of subexpression removal to remove static
2773 * subexpressions referred to by common dynamic subexpressions. */
2774 sc->root = remove_unused_subexpressions(sc->root);
2775 // Update the reference counts, used by postprocess_item_subexpressions().
2779 init_item_subexpr_refcount(item);
2785 fprintf(stderr, "\nTree after second analysis pass:\n");
2786 coll->printTree(stderr, false);
2789 /* Initialize evaluation groups, position calculations for methods, perform
2790 * some final optimization, and free the memory allocated for the
2792 /* By default, use whole residues/molecules. */
2793 flags = POS_COMPLWHOLE;
2794 PositionCalculationCollection::typeFromEnum(coll->impl_->rpost_.c_str(),
2799 init_root_item(item, &sc->gall);
2800 postprocess_item_subexpressions(item);
2801 init_item_comg(item, &sc->pcc, post, flags);
2802 free_item_compilerdata(item);
2806 /* Allocate memory for the evaluation memory pool. */
2807 _gmx_sel_mempool_reserve(sc->mempool, 0);
2809 /* Finish up by calculating total masses and charges. */
2810 for (i = 0; i < sc->sel.size(); ++i)
2812 sc->sel[i]->initializeMassesAndCharges(sc->top);