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 * For example, memory handling in atom-valued method parameters within common
37 * subexpressions may currently result in memory leaks.
38 * Also, the main compilation function leaves the selection collection in
39 * a bad state if an error occurs.
42 * The memory usage could be optimized.
45 * \page selcompiler Selection compilation
47 * The compiler takes the selection element tree from the selection parser
48 * (see \ref selparser) as input. It initializes missing fields, reorganizes,
49 * simplifies and optimizes the tree, and evaluates static parts of the
51 * The compilation is a global process, i.e., all selections are compiled
52 * and optimized simultaneously. Hence, all the selections should be parsed
53 * before the compiler can be called.
56 * Write documentation for the overall structure of the compiler and
57 * the optimizations that the compiler does.
60 * Describe the selection element tree after compilation in more detail.
63 * \section selcompiler_tree Element tree after compilation
65 * After the compilation, the selection element tree is suitable for
66 * gmx_ana_selcollection_evaluate(). Here, the structure of the tree
68 * Enough memory has been allocated for \ref t_selelem::v
69 * (and \ref t_selelem::cgrp for \ref SEL_SUBEXPR elements) to allow the
70 * selection to be evaluated without allocating any memory.
73 * \subsection selcompiler_tree_root Root elements
75 * The top level of the tree consists of a chain of \ref SEL_ROOT elements.
76 * These are used for two purposes:
77 * -# A selection that should be evaluated.
78 * These elements appear in the same order as the selections in the input.
79 * For these elements, \ref t_selelem::v has been set to the maximum
80 * possible group that the selection can evaluate to, and
81 * \ref t_selelem::cgrp has been set to use a NULL group for evaluation.
82 * -# A subexpression that appears in one or more selections.
83 * Each selection that gives a value for a method parameter is a
84 * potential subexpression, as is any variable value.
85 * Only subexpressions that require evaluation for each frame are left
86 * after the selection is compiled.
87 * Each subexpression appears in the chain before any references to it.
88 * For these elements, \c t_selelem::cgrp has been set to the group
89 * that should be used to evaluate the subexpression.
90 * If \c t_selelem::cgrp is empty, the total evaluation group is not known
91 * in advance. If this is the case, \c t_selelem::evaluate is also NULL.
93 * The children of the \ref SEL_ROOT elements can be used to distinguish
94 * the two types of root elements from each other; the rules are the same
95 * as for the parsed tree (see \ref selparser_tree_root).
96 * Subexpressions are treated as if they had been provided through variables.
98 * Selection names are stored as after parsing (see \ref selparser_tree_root),
99 * with the exception that default names have been generated for selections
100 * that did not have an explicit name.
103 * \subsection selcompiler_tree_const Constant elements
105 * All (sub)selections that do not require particle positions have been
106 * replaced with \ref SEL_CONST elements.
107 * Constant elements from the parser are also retained if present in
108 * dynamic parts of the selections.
109 * Several constant elements with a NULL \c t_selelem::evaluate are left for
110 * debugging purposes; only the ones for \ref BOOL_OR expressions are used
113 * The value is stored in \c t_selelem::v, and for group values with an
114 * evaluation function set, also in \c t_selelem::cgrp.
115 * For \ref GROUP_VALUE elements, unnecessary atoms (i.e., atoms that
116 * could never be selected) have been removed from the value.
118 * \ref SEL_CONST elements have no children.
121 * \subsection selcompiler_tree_method Method evaluation elements
126 * \subsection selcompiler_tree_subexpr Subexpression elements
128 * As described in \ref selcompiler_tree_root, subexpressions are created
129 * for each variable and each expression that gives a value to a selection
130 * method parameter. As the only child of the \ref SEL_ROOT element,
131 * these elements have a \ref SEL_SUBEXPR element. The \ref SEL_SUBEXPR
132 * element has a single child, which evaluates the actual expression.
133 * After compilation, only subexpressions that require particle positions
134 * for evaluation are left.
135 * For non-variable subexpression, automatic names have been generated to
138 * (write about the contents of \ref SEL_SUBEXPR elements)
140 * \ref SEL_SUBEXPRREF elements are used to describe references to
141 * subexpressions. They have always a single child, which is the
142 * \ref SEL_SUBEXPR element being referenced.
144 * If a subexpression is used only once and can be evaluated statically,
145 * the evaluation has been optimized by setting the child of the
146 * \ref SEL_SUBEXPR element to evaluate the value of \ref SEL_SUBEXPRREF
147 * directly. In this case, the evaluation routines for the \ref SEL_SUBEXPRREF
148 * and \ref SEL_SUBEXPR elements only propagate some status information,
149 * but do not unnecessarily copy the values.
152 * \subsection selcompiler_tree_bool Boolean elements
154 * \ref SEL_BOOLEAN elements have been merged such that one element
155 * may carry out evaluation of more than one operation of the same type.
156 * The static parts of the expressions have been evaluated, and are placed
157 * in the first child. These are followed by the dynamic expressions, in the
158 * order provided by the user.
170 #include <indexutil.h>
172 #include <selection.h>
173 #include <selmethod.h>
175 #include "evaluate.h"
176 #include "keywords.h"
177 #include "selcollection.h"
181 * Internal data structure used by the compiler.
183 typedef struct t_compiler_data
185 /** The real evaluation method. */
186 sel_evalfunc evaluate
;
188 * Whether the element is a method parameter.
190 * This flag is set for \ref SEL_SUBEXPR elements that are used to
191 * evaluate non-atom-valued selection method parameters.
195 * TRUE if the whole subexpression should be treated static.
197 * This flag is always FALSE if \ref SEL_DYNAMIC is set for the element,
198 * but it is also FALSE for static elements within common subexpressions.
201 /** TRUE if the subexpression will always be evaluated with the same group. */
203 /** TRUE if the compiler evaluation routine should return the maximal selection. */
205 /** Smallest selection that can be selected by the subexpression. */
206 gmx_ana_index_t
*gmin
;
207 /** Largest selection that can be selected by the subexpression. */
208 gmx_ana_index_t
*gmax
;
209 /** TRUE if memory has been allocated for \p gmin and \p gmax. */
214 /********************************************************************
215 * COMPILER UTILITY FUNCTIONS
216 ********************************************************************/
219 * \param sel Selection to free.
221 * This function only frees the data for the given selection, not its children.
222 * It is safe to call the function when compiler data has not been allocated
223 * or has already been freed; in such a case, nothing is done.
226 _gmx_selelem_free_compiler_data(t_selelem
*sel
)
230 sel
->evaluate
= sel
->cdata
->evaluate
;
231 if (sel
->cdata
->bMinMaxAlloc
)
233 sel
->cdata
->gmin
->name
= NULL
;
234 sel
->cdata
->gmax
->name
= NULL
;
235 gmx_ana_index_deinit(sel
->cdata
->gmin
);
236 gmx_ana_index_deinit(sel
->cdata
->gmax
);
237 sfree(sel
->cdata
->gmin
);
238 sfree(sel
->cdata
->gmax
);
246 * Allocates memory for storing the evaluated value of a selection element.
248 * \param sel Selection element to initialize
249 * \param[in] isize Maximum evaluation group size.
250 * \param[in] bChildEval TRUE if children have already been processed.
251 * \returns TRUE if the memory was allocated, FALSE if children need to
252 * be processed first.
254 * If called more than once, memory is (re)allocated to ensure that the
255 * maximum of the \p isize values can be stored.
258 alloc_selection_data(t_selelem
*sel
, int isize
, bool bChildEval
)
262 /* Find out the number of elements to allocate */
263 if (sel
->flags
& SEL_SINGLEVAL
)
267 else if (sel
->flags
& SEL_ATOMVAL
)
271 else /* sel->flags should contain SEL_VARNUMVAL */
279 child
= (sel
->type
== SEL_SUBEXPRREF
? sel
->child
: sel
);
280 if (child
->type
== SEL_SUBEXPR
)
282 child
= child
->child
;
284 nalloc
= (sel
->v
.type
== POS_VALUE
) ? child
->v
.u
.p
->nr
: child
->v
.nr
;
286 /* For positions, we actually want to allocate just a single structure
287 * for nalloc positions. */
288 if (sel
->v
.type
== POS_VALUE
)
293 /* Allocate memory for sel->v.u if needed */
294 if ((sel
->flags
& SEL_ALLOCVAL
)
295 || (sel
->type
== SEL_SUBEXPRREF
&& sel
->u
.param
296 && (sel
->u
.param
->flags
& (SPAR_VARNUM
| SPAR_ATOMVAL
))))
298 _gmx_selvalue_reserve(&sel
->v
, nalloc
);
300 /* Reserve memory inside group and position structures if
301 * SEL_ALLOCDATA is set. */
302 if (sel
->flags
& SEL_ALLOCDATA
)
304 if (sel
->v
.type
== GROUP_VALUE
)
306 gmx_ana_index_reserve(sel
->v
.u
.g
, isize
);
308 else if (sel
->v
.type
== POS_VALUE
)
310 gmx_ana_pos_reserve(sel
->v
.u
.p
, isize
, 0);
317 * Replace the evaluation function of each element in the subtree.
319 * \param sel Root of the selection subtree to process.
320 * \param[in] eval The new evaluation function.
323 set_evaluation_function(t_selelem
*sel
, sel_evalfunc eval
)
325 sel
->evaluate
= eval
;
326 if (sel
->type
!= SEL_SUBEXPRREF
)
328 t_selelem
*child
= sel
->child
;
331 set_evaluation_function(child
, eval
);
337 /********************************************************************
338 * SUBEXPRESSION EXTRACTION COMPILER PASS
339 ********************************************************************/
342 * Creates a name with a running number for a subexpression.
344 * \param[in,out] sel The subexpression to be named.
345 * \param[in] i Running number for the subexpression.
347 * The name of the selection becomes "SubExpr N", where N is \p i;
348 * Memory is allocated for the name and the name is stored both in
349 * \c t_selelem::name and \c t_selelem::u::cgrp::name; the latter
350 * is freed by _gmx_selelem_free().
353 create_subexpression_name(t_selelem
*sel
, int i
)
360 ret
= snprintf(name
, len
+1, "SubExpr %d", i
);
361 if (ret
< 0 || ret
> len
)
367 sel
->u
.cgrp
.name
= name
;
371 * Processes and extracts subexpressions from a given selection subtree.
373 * \param sel Root of the subtree to process.
374 * \param[in] gall Index group that contains all the input atoms.
375 * \param subexprn Pointer to a subexpression counter.
376 * \returns Pointer to a chain of subselections, or NULL if none were found.
378 * This function finds recursively all \ref SEL_SUBEXPRREF elements below
379 * the given root element and ensures that their children are within
380 * \ref SEL_SUBEXPR elements. It also creates a chain of \ref SEL_ROOT elements
381 * that contain the subexpression as their children and returns the first
382 * of these root elements.
385 extract_item_subselections(t_selelem
*sel
, gmx_ana_index_t
*gall
, int *subexprn
)
391 root
= subexpr
= NULL
;
397 root
= subexpr
= extract_item_subselections(child
, gall
, subexprn
);
401 subexpr
->next
= extract_item_subselections(child
, gall
, subexprn
);
403 while (subexpr
&& subexpr
->next
)
405 subexpr
= subexpr
->next
;
407 /* The latter check excludes variable references */
408 if (child
->type
== SEL_SUBEXPRREF
&& child
->child
->type
!= SEL_SUBEXPR
)
410 /* Create the root element for the subexpression */
413 root
= subexpr
= _gmx_selelem_create(SEL_ROOT
);
417 subexpr
->next
= _gmx_selelem_create(SEL_ROOT
);
418 subexpr
= subexpr
->next
;
420 /* Set the evaluation group to all atoms */
421 if (!(child
->flags
& SEL_ATOMVAL
))
423 gmx_ana_index_set(&subexpr
->u
.cgrp
, gall
->isize
, gall
->index
, NULL
, 0);
425 /* Create the subexpression element */
426 subexpr
->child
= _gmx_selelem_create(SEL_SUBEXPR
);
427 _gmx_selelem_set_vtype(subexpr
->child
, child
->v
.type
);
428 create_subexpression_name(subexpr
->child
, ++*subexprn
);
429 /* Move the actual subexpression under the created element */
430 subexpr
->child
->child
= child
->child
;
431 child
->child
= subexpr
->child
;
432 subexpr
->child
->refcount
= 2;
433 /* Set the flags for the created elements */
434 subexpr
->flags
|= (child
->flags
& SEL_VALFLAGMASK
);
435 subexpr
->child
->flags
|= (child
->flags
& SEL_VALFLAGMASK
);
444 * Extracts subexpressions of the selection chain.
446 * \param sel First selection in the whole selection chain.
447 * \param[in] gall Index group that contains all the input atoms.
448 * \returns The new first element for the chain.
450 * Finds all the subexpressions (and their subexpressions) in the
451 * selection chain starting from \p sel and creates \ref SEL_SUBEXPR
453 * \ref SEL_ROOT elements are also created for each subexpression
454 * and inserted into the selection chain before the expressions that
458 extract_subexpressions(t_selelem
*sel
, gmx_ana_index_t
*gall
)
460 t_selelem
*root
, *item
, *next
;
468 item
= extract_item_subselections(next
, gall
, &subexprn
);
495 /********************************************************************
496 * BOOLEAN OPERATION REORDERING COMPILER PASS
497 ********************************************************************/
500 * Removes redundant boolean selection elements.
502 * \param sel Root of the selection subtree to optimize.
504 * This function merges similar boolean operations (e.g., (A or B) or C becomes
505 * a single OR operation with three operands).
508 optimize_boolean_expressions(t_selelem
*sel
)
510 t_selelem
*child
, *prev
;
512 /* Do recursively for children */
513 if (sel
->type
!= SEL_SUBEXPRREF
)
519 optimize_boolean_expressions(child
);
520 /* Remove double negations */
521 if (child
->type
== SEL_BOOLEAN
&& child
->u
.boolt
== BOOL_NOT
522 && child
->child
->type
== SEL_BOOLEAN
&& child
->child
->u
.boolt
== BOOL_NOT
)
524 /* Move the doubly negated expression up two levels */
527 sel
->child
= child
->child
->child
;
532 prev
->next
= child
->child
->child
;
535 child
->child
->child
->next
= child
->next
;
536 /* Remove the two negations */
537 child
->child
->child
= NULL
;
539 _gmx_selelem_free(child
);
546 if (sel
->type
!= SEL_BOOLEAN
|| sel
->u
.boolt
== BOOL_NOT
)
550 /* Merge subsequent binary operations */
555 if (child
->type
== SEL_BOOLEAN
&& child
->u
.boolt
== sel
->u
.boolt
)
559 sel
->child
= child
->child
;
564 prev
->next
= child
->child
;
570 prev
->next
= child
->next
;
584 * Reorders children of boolean expressions such that static selections
587 * \param sel Root of the selection subtree to reorder.
589 * The relative order of static expressions does not change.
590 * The same is true for the dynamic expressions.
593 reorder_boolean_static_children(t_selelem
*sel
)
595 t_selelem
*child
, *prev
, *next
;
597 /* Do recursively for children */
598 if (sel
->type
!= SEL_SUBEXPRREF
)
603 reorder_boolean_static_children(child
);
608 /* Reorder boolean expressions such that static selections come first */
609 if (sel
->type
== SEL_BOOLEAN
&& (sel
->flags
& SEL_DYNAMIC
))
613 start
.next
= sel
->child
;
618 /* child is the last handled static expression */
619 /* prev is the last handled non-static expression */
621 while (next
&& (next
->flags
& SEL_DYNAMIC
))
626 /* next is now the first static expression after child */
631 /* Reorder such that next comes after child */
634 prev
->next
= next
->next
;
635 next
->next
= child
->next
;
642 /* Advance child by one */
646 sel
->child
= start
.next
;
650 /********************************************************************
651 * EVALUATION PREPARATION COMPILER PASS
652 ********************************************************************/
655 * Initializes the evaluation groups for the selections.
657 * \param[in,out] sc Selection collection data.
659 * The evaluation group of each \ref SEL_ROOT element corresponding to a
660 * selection in \p sc is set to \p gall.
663 initialize_evalgrps(gmx_ana_selcollection_t
*sc
)
668 /* Initialize the output */
669 for (i
= 0; i
< sc
->nr
; ++i
)
671 item
= sc
->sel
[i
]->selelem
;
672 /* Set the evaluation group to all atoms */
673 gmx_ana_index_set(&item
->u
.cgrp
, sc
->gall
.isize
, sc
->gall
.index
,
674 item
->u
.cgrp
.name
, 0);
679 * Prepares the selection (sub)tree for evaluation.
681 * \param[in,out] sel Root of the selection subtree to prepare.
682 * \returns TRUE on success, FALSE if any subexpression fails.
684 * This function sets the evaluation function (\c t_selelem::evaluate)
685 * for the selection elements.
686 * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
687 * structure if required.
690 init_item_evaluation(t_selelem
*sel
)
694 /* Process children */
695 if (sel
->type
!= SEL_SUBEXPRREF
)
700 if (!init_item_evaluation(child
))
708 /* Make sure that the group/position structure is allocated */
709 if (!sel
->v
.u
.ptr
&& (sel
->flags
& SEL_ALLOCVAL
))
711 if (sel
->v
.type
== GROUP_VALUE
|| sel
->v
.type
== POS_VALUE
)
713 _gmx_selvalue_reserve(&sel
->v
, 1);
718 /* Set the evaluation function */
722 if (sel
->v
.type
== GROUP_VALUE
)
724 sel
->evaluate
= &_gmx_sel_evaluate_static
;
729 sel
->evaluate
= &_gmx_sel_evaluate_method
;
733 if (sel
->v
.type
!= NO_VALUE
)
735 sel
->evaluate
= &_gmx_sel_evaluate_modifier
;
740 switch (sel
->u
.boolt
)
742 case BOOL_NOT
: sel
->evaluate
= &_gmx_sel_evaluate_not
; break;
743 case BOOL_AND
: sel
->evaluate
= &_gmx_sel_evaluate_and
; break;
744 case BOOL_OR
: sel
->evaluate
= &_gmx_sel_evaluate_or
; break;
746 gmx_impl("xor expressions not implemented");
752 sel
->evaluate
= &_gmx_sel_evaluate_root
;
756 sel
->evaluate
= &_gmx_sel_evaluate_subexpr
;
760 sel
->name
= sel
->child
->name
;
761 sel
->evaluate
= &_gmx_sel_evaluate_subexprref
;
769 /********************************************************************
770 * COMPILER DATA INITIALIZATION PASS
771 ********************************************************************/
774 * Allocates memory for the compiler data and initializes the structure.
776 * \param sel Root of the selection subtree to process.
779 init_item_compilerdata(t_selelem
*sel
)
783 /* Allocate the compiler data structure */
786 /* Store the real evaluation method because the compiler will replace it */
787 sel
->cdata
->evaluate
= sel
->evaluate
;
789 /* Initialize the flags */
790 sel
->cdata
->bMethodParam
= FALSE
;
791 sel
->cdata
->bStatic
= !(sel
->flags
& SEL_DYNAMIC
);
792 sel
->cdata
->bStaticEval
= TRUE
;
793 sel
->cdata
->bEvalMax
= (sel
->type
== SEL_SUBEXPR
? TRUE
: FALSE
);
794 /* Set the method parameter flag for non-atom-valued parameters */
795 if (sel
->type
== SEL_EXPRESSION
|| sel
->type
== SEL_MODIFIER
)
800 if (!(child
->flags
& SEL_ATOMVAL
))
802 child
->child
->cdata
->bMethodParam
= TRUE
;
808 /* Initialize children */
809 if (sel
->type
!= SEL_SUBEXPRREF
)
814 init_item_compilerdata(child
);
819 /* Determine whether we should evaluate the minimum or the maximum
820 * for the children of this element. */
821 if (sel
->type
== SEL_BOOLEAN
)
825 bEvalMax
= (sel
->u
.boolt
== BOOL_AND
);
829 child
->cdata
->bEvalMax
= bEvalMax
;
830 if (child
->type
== SEL_BOOLEAN
&& child
->u
.boolt
== BOOL_NOT
)
832 child
->child
->cdata
->bEvalMax
= !bEvalMax
;
837 else if (sel
->type
== SEL_EXPRESSION
|| sel
->type
== SEL_MODIFIER
838 || sel
->type
== SEL_SUBEXPR
)
843 child
->cdata
->bEvalMax
= TRUE
;
848 /* Initialize the minimum and maximum evaluation groups */
849 sel
->cdata
->bMinMaxAlloc
= FALSE
;
850 if (sel
->type
!= SEL_ROOT
&& sel
->v
.type
!= NO_VALUE
)
852 if (sel
->type
== SEL_SUBEXPR
)
854 sel
->cdata
->gmin
= sel
->child
->cdata
->gmin
;
855 sel
->cdata
->gmax
= sel
->child
->cdata
->gmax
;
857 else if (sel
->v
.type
== GROUP_VALUE
&& sel
->cdata
->bStatic
)
859 sel
->cdata
->gmin
= sel
->v
.u
.g
;
860 sel
->cdata
->gmax
= sel
->v
.u
.g
;
864 sel
->cdata
->bMinMaxAlloc
= TRUE
;
865 snew(sel
->cdata
->gmin
, 1);
866 snew(sel
->cdata
->gmax
, 1);
872 * Initializes the static evaluation flag for a selection subtree.
874 * \param[in,out] sel Root of the selection subtree to process.
876 * Sets the \c bStaticEval in the compiler data structure:
877 * for any element for which the evaluation group may depend on the trajectory
878 * frame, the flag is cleared.
880 * reorder_boolean_static_children() should have been called.
883 init_item_staticeval(t_selelem
*sel
)
887 /* Non-atom-valued method parameters should always have bStaticEval,
888 * so don't do anything if a reference to them is encountered. */
889 if (sel
->type
== SEL_SUBEXPRREF
&& sel
->child
->cdata
->bMethodParam
)
894 /* Propagate the bStaticEval flag to children if it is not set */
895 if (!sel
->cdata
->bStaticEval
)
900 if ((sel
->type
!= SEL_EXPRESSION
&& sel
->type
!= SEL_MODIFIER
)
901 || (child
->flags
& SEL_ATOMVAL
))
903 if (child
->cdata
->bStaticEval
)
905 child
->cdata
->bStaticEval
= FALSE
;
906 init_item_staticeval(child
);
912 else /* bStaticEval is set */
914 /* For boolean expressions, any expression after the first dynamic
915 * expression should not have bStaticEval. */
916 if (sel
->type
== SEL_BOOLEAN
)
919 while (child
&& !(child
->flags
& SEL_DYNAMIC
))
929 child
->cdata
->bStaticEval
= FALSE
;
934 /* Process the children */
938 init_item_staticeval(child
);
945 /********************************************************************
946 * STATIC ANALYSIS COMPILER PASS
947 ********************************************************************/
950 * Marks a subtree completely dynamic or undoes such a change.
952 * \param sel Selection subtree to mark.
953 * \param[in] bDynamic If TRUE, the \p bStatic flag of the whole
954 * selection subtree is cleared. If FALSE, the flag is restored to
955 * using \ref SEL_DYNAMIC.
957 * Does not descend into parameters of methods unless the parameters
958 * are evaluated for each atom.
961 mark_subexpr_dynamic(t_selelem
*sel
, bool bDynamic
)
965 sel
->cdata
->bStatic
= (!bDynamic
&& !(sel
->flags
& SEL_DYNAMIC
));
969 if (sel
->type
!= SEL_EXPRESSION
|| child
->type
!= SEL_SUBEXPRREF
970 || (child
->u
.param
->flags
& SPAR_ATOMVAL
))
972 mark_subexpr_dynamic(child
, bDynamic
);
979 * Makes an evaluated selection element static.
981 * \param sel Selection element to make static.
983 * The evaluated value becomes the value of the static element.
984 * The element type is changed to SEL_CONST and the children are
988 make_static(t_selelem
*sel
)
990 /* Free the expression data as it is no longer needed */
991 _gmx_selelem_free_exprdata(sel
);
992 /* Make the item static */
994 sel
->type
= SEL_CONST
;
995 sel
->evaluate
= NULL
;
996 sel
->cdata
->evaluate
= NULL
;
997 /* Free the children */
998 _gmx_selelem_free_chain(sel
->child
);
1000 /* Set the group value.
1001 * None of the elements for which this function may be called uses
1002 * the cgrp group, so we can simply overwrite the contents without
1003 * worrying about memory leaks. */
1004 if (sel
->v
.type
== GROUP_VALUE
)
1006 gmx_ana_index_set(&sel
->u
.cgrp
, sel
->v
.u
.g
->isize
, sel
->v
.u
.g
->index
, NULL
, 0);
1011 * Evaluates a constant expression during analyze_static() and analyze_static2().
1013 * \param[in] data Evaluation data.
1014 * \param[in,out] sel Selection to process.
1015 * \param[in] g The evaluation group.
1016 * \returns 0 on success, a non-zero error code on error.
1019 process_const(gmx_sel_evaluate_t
*data
, t_selelem
*sel
, gmx_ana_index_t
*g
)
1024 if (sel
->v
.type
== GROUP_VALUE
)
1026 if (sel
->cdata
->evaluate
)
1028 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1031 /* Other constant expressions do not need evaluation */
1036 * Sets the parameter value pointer for \ref SEL_SUBEXPRREF params.
1038 * \param[in,out] sel Selection to process.
1040 * Copies the value pointer of \p sel to \c sel->u.param if one is present
1041 * and should receive the value from the compiler
1042 * (most parameter values are handled during parsing).
1043 * If \p sel is not of type \ref SEL_SUBEXPRREF, or if \c sel->u.param is NULL,
1044 * the function does nothing.
1045 * Also, if the \c sel->u.param does not have \ref SPAR_VARNUM or
1046 * \ref SPAR_ATOMVAL, the function returns immediately.
1049 store_param_val(t_selelem
*sel
)
1051 /* Return immediately if there is no parameter. */
1052 if (sel
->type
!= SEL_SUBEXPRREF
|| !sel
->u
.param
)
1057 /* Or if the value does not need storing. */
1058 if (!(sel
->u
.param
->flags
& (SPAR_VARNUM
| SPAR_ATOMVAL
)))
1063 if (sel
->v
.type
== INT_VALUE
|| sel
->v
.type
== REAL_VALUE
1064 || sel
->v
.type
== STR_VALUE
)
1066 _gmx_selvalue_setstore(&sel
->u
.param
->val
, sel
->v
.u
.ptr
);
1071 * Handles the initialization of a selection method during analyze_static() pass.
1073 * \param[in,out] sel Selection element to process.
1074 * \param[in] top Topology structure.
1075 * \param[in] isize Size of the evaluation group for the element.
1076 * \returns 0 on success, a non-zero error code on return.
1078 * Calls sel_initfunc() (and possibly sel_outinitfunc()) to initialize the
1080 * If no \ref SPAR_ATOMVAL parameters are present, multiple initialization
1081 * is prevented by using \ref SEL_METHODINIT and \ref SEL_OUTINIT flags.
1084 init_method(t_selelem
*sel
, t_topology
*top
, int isize
)
1090 /* Find out whether there are any atom-valued parameters */
1095 if (child
->flags
& SEL_ATOMVAL
)
1099 child
= child
->next
;
1102 /* Initialize the method */
1103 if (sel
->u
.expr
.method
->init
1104 && (bAtomVal
|| !(sel
->flags
& SEL_METHODINIT
)))
1106 sel
->flags
|= SEL_METHODINIT
;
1107 /* The allocation flags are cleared first to not to free anything if
1108 * initialization fails. */
1110 if (sel
->type
== SEL_MODIFIER
&& sel
->v
.type
!= NO_VALUE
)
1112 child
= child
->next
;
1116 child
->flags
&= ~(SEL_ALLOCVAL
| SEL_ALLOCDATA
);
1117 child
= child
->next
;
1119 rc
= sel
->u
.expr
.method
->init(top
, sel
->u
.expr
.method
->nparams
,
1120 sel
->u
.expr
.method
->param
, sel
->u
.expr
.mdata
);
1126 if (bAtomVal
|| !(sel
->flags
& SEL_OUTINIT
))
1128 sel
->flags
|= SEL_OUTINIT
;
1129 if (sel
->u
.expr
.method
->outinit
)
1131 rc
= sel
->u
.expr
.method
->outinit(top
, &sel
->v
, sel
->u
.expr
.mdata
);
1139 alloc_selection_data(sel
, isize
, TRUE
);
1140 if ((sel
->flags
& SEL_DYNAMIC
)
1141 && sel
->v
.type
!= GROUP_VALUE
&& sel
->v
.type
!= POS_VALUE
)
1145 /* If the method is char-valued, pre-allocate the strings. */
1146 if (sel
->u
.expr
.method
->flags
& SMETH_CHARVAL
)
1150 /* A sanity check */
1151 if (sel
->v
.type
!= STR_VALUE
)
1153 gmx_bug("internal error");
1156 sel
->flags
|= SEL_ALLOCDATA
;
1157 for (i
= 0; i
< isize
; ++i
)
1159 if (sel
->v
.u
.s
[i
] == NULL
)
1161 snew(sel
->v
.u
.s
[i
], 2);
1172 * Evaluates the static part of a boolean expression.
1174 * \param[in] data Evaluation data.
1175 * \param[in,out] sel Boolean selection element whose children should be
1177 * \param[in] g The evaluation group.
1178 * \returns 0 on success, a non-zero error code on error.
1180 * reorder_item_static_children() should have been called.
1183 evaluate_boolean_static_part(gmx_sel_evaluate_t
*data
, t_selelem
*sel
,
1186 t_selelem
*child
, *next
;
1189 /* Find the last static subexpression */
1191 while (child
->next
&& child
->next
->cdata
->bStatic
)
1193 child
= child
->next
;
1195 if (!child
->cdata
->bStatic
)
1200 /* Evalute the static part if there is more than one expression */
1201 if (child
!= sel
->child
)
1205 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1210 /* Replace the subexpressions with the result */
1211 _gmx_selelem_free_chain(sel
->child
);
1213 child
->type
= SEL_CONST
;
1214 child
->flags
= SEL_FLAGSSET
| SEL_SINGLEVAL
| SEL_ALLOCVAL
| SEL_ALLOCDATA
;
1215 _gmx_selelem_set_vtype(child
, GROUP_VALUE
);
1216 child
->evaluate
= NULL
;
1217 _gmx_selvalue_reserve(&child
->v
, 1);
1218 gmx_ana_index_copy(child
->v
.u
.g
, sel
->v
.u
.g
, TRUE
);
1219 init_item_compilerdata(child
);
1220 child
->cdata
->bStaticEval
= sel
->cdata
->bStaticEval
;
1224 else if (child
->evaluate
)
1226 rc
= child
->evaluate(data
, child
, g
);
1232 /* Set the evaluation function for the constant element.
1233 * We never need to evaluate the element again during compilation,
1234 * but we may need to evaluate the static part again if the
1235 * expression is not an OR with a static evaluation group.
1236 * If we reach here with a NOT expression, the NOT expression
1237 * is also static, and will be made a constant later, so don't waste
1238 * time copying the group. */
1239 child
->evaluate
= NULL
;
1240 if (sel
->u
.boolt
== BOOL_NOT
1241 || (sel
->cdata
->bStaticEval
&& sel
->u
.boolt
== BOOL_OR
))
1243 child
->cdata
->evaluate
= NULL
;
1247 child
->cdata
->evaluate
= &_gmx_sel_evaluate_static
;
1248 /* The cgrp has only been allocated if it originated from an
1249 * external index group. In that case, we need special handling
1250 * to preserve the name of the group and to not leak memory.
1251 * If cgrp has been set in make_static(), it is not allocated,
1252 * and hence we can overwrite it safely. */
1253 if (child
->u
.cgrp
.nalloc_index
> 0)
1255 char *name
= child
->u
.cgrp
.name
;
1256 gmx_ana_index_copy(&child
->u
.cgrp
, child
->v
.u
.g
, FALSE
);
1257 gmx_ana_index_squeeze(&child
->u
.cgrp
);
1258 child
->u
.cgrp
.name
= name
;
1262 gmx_ana_index_copy(&child
->u
.cgrp
, child
->v
.u
.g
, TRUE
);
1269 * Evaluates the minimum and maximum groups for a boolean expression.
1271 * \param[in] sel \ref SEL_BOOLEAN element currently being evaluated.
1272 * \param[in] g Group for which \p sel has been evaluated.
1273 * \param[out] gmin Largest subset of the possible values of \p sel.
1274 * \param[out] gmax Smallest superset of the possible values of \p sel.
1276 * This is a helper function for analyze_static() that is called for
1277 * dynamic \ref SEL_BOOLEAN elements after they have been evaluated.
1278 * It uses the minimum and maximum groups of the children to calculate
1279 * the minimum and maximum groups for \p sel, and also updates the static
1280 * part of \p sel (which is in the first child) if the children give
1283 * This function may allocate some extra memory for \p gmin and \p gmax,
1284 * but as these groups are freed at the end of analyze_static() (which is
1285 * reached shortly after this function returns), this should not be a major
1289 evaluate_boolean_minmax_grps(t_selelem
*sel
, gmx_ana_index_t
*g
,
1290 gmx_ana_index_t
*gmin
, gmx_ana_index_t
*gmax
)
1294 switch (sel
->u
.boolt
)
1297 gmx_ana_index_reserve(gmin
, g
->isize
);
1298 gmx_ana_index_reserve(gmax
, g
->isize
);
1299 gmx_ana_index_difference(gmax
, g
, sel
->child
->cdata
->gmin
);
1300 gmx_ana_index_difference(gmin
, g
, sel
->child
->cdata
->gmax
);
1304 gmx_ana_index_copy(gmin
, sel
->child
->cdata
->gmin
, TRUE
);
1305 gmx_ana_index_copy(gmax
, sel
->child
->cdata
->gmax
, TRUE
);
1306 child
= sel
->child
->next
;
1307 while (child
&& gmax
->isize
> 0)
1309 gmx_ana_index_intersection(gmin
, gmin
, child
->cdata
->gmin
);
1310 gmx_ana_index_intersection(gmax
, gmax
, child
->cdata
->gmax
);
1311 child
= child
->next
;
1313 /* Update the static part if other expressions limit it */
1314 if (sel
->child
->cdata
->bStatic
1315 && sel
->child
->v
.u
.g
->isize
> gmax
->isize
)
1317 gmx_ana_index_copy(sel
->child
->v
.u
.g
, gmax
, FALSE
);
1318 gmx_ana_index_squeeze(sel
->child
->v
.u
.g
);
1319 if (sel
->child
->u
.cgrp
.isize
> 0)
1321 gmx_ana_index_copy(&sel
->child
->u
.cgrp
, gmax
, FALSE
);
1322 gmx_ana_index_squeeze(&sel
->child
->u
.cgrp
);
1328 /* We can assume here that the gmin of children do not overlap
1329 * because of the way _gmx_sel_evaluate_or() works. */
1330 gmx_ana_index_reserve(gmin
, g
->isize
);
1331 gmx_ana_index_reserve(gmax
, g
->isize
);
1332 gmx_ana_index_copy(gmin
, sel
->child
->cdata
->gmin
, FALSE
);
1333 gmx_ana_index_copy(gmax
, sel
->child
->cdata
->gmax
, FALSE
);
1334 child
= sel
->child
->next
;
1335 while (child
&& gmin
->isize
< g
->isize
)
1337 gmx_ana_index_merge(gmin
, gmin
, child
->cdata
->gmin
);
1338 gmx_ana_index_union(gmax
, gmax
, child
->cdata
->gmax
);
1339 child
= child
->next
;
1341 /* Update the static part if other expressions have static parts
1342 * that are not included. */
1343 if (sel
->child
->cdata
->bStatic
1344 && sel
->child
->v
.u
.g
->isize
< gmin
->isize
)
1346 gmx_ana_index_reserve(sel
->child
->v
.u
.g
, gmin
->isize
);
1347 gmx_ana_index_copy(sel
->child
->v
.u
.g
, gmin
, FALSE
);
1348 if (sel
->child
->u
.cgrp
.isize
> 0)
1350 gmx_ana_index_reserve(&sel
->child
->u
.cgrp
, gmin
->isize
);
1351 gmx_ana_index_copy(&sel
->child
->u
.cgrp
, gmin
, FALSE
);
1356 case BOOL_XOR
: /* Should not be reached */
1357 gmx_impl("xor expressions not implemented");
1363 * Evaluates the static parts of \p sel and analyzes the structure.
1365 * \param[in] data Evaluation data.
1366 * \param[in,out] sel Selection currently being evaluated.
1367 * \param[in] g Group for which \p sel should be evaluated.
1368 * \returns 0 on success, a non-zero error code on error.
1370 * This function is used as the replacement for the \c t_selelem::evaluate
1372 * It does the single most complex task in the compiler: after all elements
1373 * have been processed, the \p gmin and \p gmax fields of \p t_compiler_data
1374 * have been properly initialized, enough memory has been allocated for
1375 * storing the value of each expression, and the static parts of the
1376 * expressions have been evaluated.
1377 * The above is exactly true only for elements other than subexpressions:
1378 * another pass is required for subexpressions that are referred to more than
1379 * once to evaluate the static parts.
1380 * This second pass is performed by analyze_static2().
1382 * \see analyze_static2()
1385 analyze_static(gmx_sel_evaluate_t
*data
, t_selelem
*sel
, gmx_ana_index_t
*g
)
1387 t_selelem
*child
, *next
;
1388 gmx_ana_index_t gmin
, gmax
;
1392 gmx_ana_index_clear(&gmin
);
1393 gmx_ana_index_clear(&gmax
);
1394 bDelayAlloc
= FALSE
;
1396 if (sel
->type
!= SEL_ROOT
&& g
)
1398 bDelayAlloc
= !alloc_selection_data(sel
, g
->isize
, FALSE
);
1401 /* TODO: This switch is awfully long... */
1406 rc
= process_const(data
, sel
, g
);
1409 case SEL_EXPRESSION
:
1411 rc
= _gmx_sel_evaluate_method_params(data
, sel
, g
);
1416 rc
= init_method(sel
, data
->top
, g
->isize
);
1421 if (sel
->type
== SEL_MODIFIER
|| !(sel
->flags
& SEL_DYNAMIC
))
1423 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1424 if (rc
== 0 && sel
->cdata
->bStatic
)
1431 gmx_ana_index_copy(&gmax
, g
, TRUE
);
1436 if (!(sel
->flags
& SEL_DYNAMIC
))
1438 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1439 if (rc
== 0 && sel
->cdata
->bStatic
)
1446 /* Evalute the static part if there is more than one expression */
1447 rc
= evaluate_boolean_static_part(data
, sel
, g
);
1453 /* Evaluate the selection.
1454 * If the type is boolean, we must explicitly handle the
1455 * static part evaluated in evaluate_boolean_static_part()
1456 * here because g may be larger. */
1457 if (sel
->u
.boolt
== BOOL_AND
&& sel
->child
->type
== SEL_CONST
)
1459 rc
= sel
->cdata
->evaluate(data
, sel
, sel
->child
->v
.u
.g
);
1463 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1470 /* Evaluate minimal and maximal selections */
1471 evaluate_boolean_minmax_grps(sel
, g
, &gmin
, &gmax
);
1476 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1480 if (sel
->u
.cgrp
.isize
== 0)
1482 gmx_ana_index_reserve(&sel
->u
.cgrp
, g
->isize
);
1485 /* We need to evaluate the child before we can allocate the
1487 rc
= sel
->child
->evaluate(data
, sel
->child
, g
);
1492 alloc_selection_data(sel
, g
->isize
, TRUE
);
1493 /* Do not evaluate the child again */
1494 sel
->child
->evaluate
= NULL
;
1495 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1496 sel
->child
->evaluate
= &analyze_static
;
1500 alloc_selection_data(sel
->child
, g
->isize
, FALSE
);
1501 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1506 int isize
= gmx_ana_index_difference_size(g
, &sel
->u
.cgrp
);
1509 isize
+= sel
->u
.cgrp
.isize
;
1510 gmx_ana_index_reserve(&sel
->u
.cgrp
, isize
);
1511 if (sel
->v
.type
== GROUP_VALUE
|| (sel
->flags
& SEL_ATOMVAL
))
1513 alloc_selection_data(sel
->child
, isize
, FALSE
);
1514 alloc_selection_data(sel
, isize
, FALSE
);
1516 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1520 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1525 case SEL_SUBEXPRREF
:
1526 /* Evaluate the subexpression if it is not yet evaluated.
1527 * Can happen when a variable is passed as a parameter or as
1529 if (sel
->child
->u
.cgrp
.isize
== 0)
1531 rc
= sel
->child
->evaluate(data
, sel
->child
, g
? g
: data
->gall
);
1536 /* Prevent another evaluation of the child. */
1537 sel
->child
->evaluate
= NULL
;
1538 alloc_selection_data(sel
, sel
->child
->cdata
->gmax
->isize
, TRUE
);
1542 alloc_selection_data(sel
, sel
->child
->cdata
->gmax
->isize
, TRUE
);
1544 /* TODO: This is not general enough if/when position references
1545 * can be evaluated more than once (that is, if there are position
1546 * methods that do not have SMETH_SINGLEVAL or SMETH_VARNUMVAL). */
1547 if (sel
->v
.type
== POS_VALUE
&& !(sel
->flags
& SEL_OUTINIT
))
1549 gmx_ana_indexmap_copy(&sel
->v
.u
.p
->m
, &sel
->child
->child
->v
.u
.p
->m
, TRUE
);
1550 sel
->flags
|= SEL_OUTINIT
;
1552 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1553 sel
->child
->evaluate
= &analyze_static
;
1558 /* Store the parameter value if required */
1559 store_param_val(sel
);
1560 if (!(sel
->flags
& SEL_DYNAMIC
))
1562 if (sel
->cdata
->bStatic
)
1569 if (sel
->child
->refcount
<= 2 || !g
)
1571 gmx_ana_index_copy(&gmin
, sel
->child
->cdata
->gmin
, TRUE
);
1572 gmx_ana_index_copy(&gmax
, sel
->child
->cdata
->gmax
, TRUE
);
1576 gmx_ana_index_reserve(&gmin
, min(g
->isize
, sel
->child
->cdata
->gmin
->isize
));
1577 gmx_ana_index_reserve(&gmax
, min(g
->isize
, sel
->child
->cdata
->gmax
->isize
));
1578 gmx_ana_index_intersection(&gmin
, sel
->child
->cdata
->gmin
, g
);
1579 gmx_ana_index_intersection(&gmax
, sel
->child
->cdata
->gmax
, g
);
1584 /* Exit if there was some problem */
1590 /* Update the minimal and maximal evaluation groups */
1591 if (sel
->cdata
->bMinMaxAlloc
)
1593 gmx_ana_index_reserve(sel
->cdata
->gmin
, sel
->cdata
->gmin
->isize
+ gmin
.isize
);
1594 gmx_ana_index_reserve(sel
->cdata
->gmax
, sel
->cdata
->gmax
->isize
+ gmax
.isize
);
1595 gmx_ana_index_merge(sel
->cdata
->gmin
, sel
->cdata
->gmin
, &gmin
);
1596 gmx_ana_index_merge(sel
->cdata
->gmax
, sel
->cdata
->gmax
, &gmax
);
1598 /* Replace the result of the evaluation */
1599 /* This is not necessary for subexpressions or for boolean negations
1600 * because the evaluation function already has done it properly. */
1601 if (sel
->v
.type
== GROUP_VALUE
&& (sel
->flags
& SEL_DYNAMIC
)
1602 && sel
->type
!= SEL_SUBEXPR
1603 && !(sel
->type
== SEL_BOOLEAN
&& sel
->u
.boolt
== BOOL_NOT
))
1605 if (sel
->cdata
->bEvalMax
)
1607 gmx_ana_index_copy(sel
->v
.u
.g
, &gmax
, FALSE
);
1611 gmx_ana_index_copy(sel
->v
.u
.g
, &gmin
, FALSE
);
1614 gmx_ana_index_deinit(&gmin
);
1615 gmx_ana_index_deinit(&gmax
);
1617 /* Make sure that enough data storage has been allocated */
1618 /* TODO: Constant expressions could be handled here more intelligently */
1619 if (sel
->type
!= SEL_ROOT
&& sel
->cdata
->bStaticEval
)
1621 alloc_selection_data(sel
, sel
->cdata
->gmax
->isize
, TRUE
);
1622 /* Make sure that the new value pointer is stored if required */
1623 store_param_val(sel
);
1630 * Evaluates the static parts of \p sel and analyzes the structure.
1632 * \param[in] data Evaluation data.
1633 * \param[in,out] sel Selection currently being evaluated.
1634 * \param[in] g Group for which \p sel should be evaluated.
1635 * \returns 0 on success, a non-zero error code on error.
1637 * This function is a simpler version of analyze_static() that is used
1638 * during a second evaluation round, and can thus use information calculated
1639 * by analyze_static().
1640 * It is also used as the replacement for the \c t_selelem::evaluate
1642 * It is used to evaluate the static parts of subexpressions that could not
1643 * be evaluated during the analyze_static() pass.
1645 * \see analyze_static()
1648 analyze_static2(gmx_sel_evaluate_t
*data
, t_selelem
*sel
, gmx_ana_index_t
*g
)
1656 rc
= process_const(data
, sel
, g
);
1659 case SEL_EXPRESSION
:
1661 case SEL_SUBEXPRREF
:
1662 if (sel
->cdata
->bStatic
)
1664 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1670 else if (sel
->type
== SEL_BOOLEAN
)
1672 rc
= evaluate_boolean_static_part(data
, sel
, g
);
1675 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1680 case SEL_ROOT
: /* Roots should not be present here */
1681 case SEL_MODIFIER
: /* Modifiers should not be present here */
1683 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1686 /* Exit if there was some problem */
1692 /* Replace the result of the evaluation */
1693 /* This is not necessary for subexpressions or for boolean negations
1694 * because the evaluation function already has done it properly. */
1695 if (sel
->v
.type
== GROUP_VALUE
&& !sel
->cdata
->bStatic
1696 && sel
->type
!= SEL_SUBEXPR
1697 && !(sel
->type
== SEL_BOOLEAN
&& sel
->u
.boolt
== BOOL_NOT
))
1699 if (sel
->cdata
->bEvalMax
)
1701 gmx_ana_index_copy(sel
->v
.u
.g
, sel
->cdata
->gmax
, FALSE
);
1705 gmx_ana_index_copy(sel
->v
.u
.g
, sel
->cdata
->gmin
, FALSE
);
1713 /********************************************************************
1714 * ROOT ITEM INITIALIZATION COMPILER PASS
1715 ********************************************************************/
1718 * Initializes a \ref SEL_ROOT element.
1720 * \param root Root element to initialize.
1721 * \returns Pointer to the selection element that should replace \p root.
1722 * Can be \p root itself or NULL if the selection should be removed.
1724 * Checks whether it is necessary to evaluate anything through the root
1725 * element, and either clears the evaluation function or initializes the
1728 * If the function returns NULL, the memory allocated for \p root is
1729 * automatically freed.
1732 init_root_item(t_selelem
*root
)
1737 /* Get the name for constant expressions if it is not yet there */
1740 if (root
->child
->type
== SEL_CONST
1741 || root
->child
->type
== SEL_SUBEXPRREF
)
1743 root
->name
= root
->child
->name
;
1745 else if (root
->child
->type
== SEL_EXPRESSION
1746 && root
->child
->child
->type
== SEL_CONST
)
1748 root
->name
= root
->child
->child
->name
;
1752 /* Process subexpressions */
1753 if (root
->child
->type
== SEL_SUBEXPR
)
1755 if (root
->child
->refcount
== 1)
1757 /* Free subexpressions that are no longer used */
1758 _gmx_selelem_free(root
);
1761 else if (root
->child
->v
.type
== POS_VALUE
)
1763 /* Position values only need to be evaluated once, by the root */
1765 else if (!root
->child
->cdata
->bStaticEval
)
1767 /* Subexpressions with non-static evaluation group should not be
1768 * evaluated by the root. */
1769 root
->evaluate
= NULL
;
1772 root
->cdata
->evaluate
= NULL
;
1777 /* Set the evaluation group */
1778 name
= root
->u
.cgrp
.name
;
1782 if (expr
->type
== SEL_SUBEXPR
)
1784 gmx_ana_index_copy(&root
->u
.cgrp
, expr
->cdata
->gmax
, TRUE
);
1788 /* expr should evaluate the positions for a selection */
1791 _gmx_selelem_set_vtype(root
, GROUP_VALUE
);
1792 root
->flags
|= (SEL_ALLOCVAL
| SEL_ALLOCDATA
);
1793 _gmx_selvalue_reserve(&root
->v
, 1);
1794 gmx_ana_index_copy(root
->v
.u
.g
, expr
->v
.u
.p
->g
, TRUE
);
1796 gmx_ana_index_set(&root
->u
.cgrp
, -1, NULL
, NULL
, 0);
1801 gmx_ana_index_clear(&root
->u
.cgrp
);
1803 root
->u
.cgrp
.name
= name
;
1808 * Initializes the evaluation groups for \ref SEL_ROOT items.
1810 * \param root First selection in the whole selection chain.
1811 * \returns The new first element for the chain.
1813 * The function also removes static subexpressions that are no longer used.
1816 process_roots(t_selelem
*root
)
1824 root
= init_root_item(root
);
1830 while (root
== next
);
1832 while (item
&& item
->next
)
1834 next
= item
->next
->next
;
1835 item
->next
= init_root_item(item
->next
);
1849 /********************************************************************
1850 * SUBEXPRESSION OPTIMIZATION PASS
1851 ********************************************************************/
1854 * Optimizes subexpression evaluation.
1856 * \param sel Root of the selection subtree to process.
1858 * Optimizes away some unnecessary evaluation of subexpressions that are only
1862 optimize_item_subexpressions(t_selelem
*sel
)
1866 /* Call recursively for all children unless the children have already been processed */
1867 if (sel
->type
!= SEL_SUBEXPRREF
)
1872 optimize_item_subexpressions(child
);
1873 child
= child
->next
;
1877 /* Optimize the evaluation of subexpressions that are used only once */
1878 if (sel
->type
== SEL_SUBEXPRREF
&& sel
->cdata
->bStaticEval
&& sel
->child
->refcount
== 2)
1880 /* The evaluation functions are not always needed, and they do some
1881 * extra work, but it should be neglible compared to other factors
1882 * in the evaluation, so set them always for simplicity. */
1883 sel
->evaluate
= &_gmx_sel_evaluate_subexprref_pass
;
1886 sel
->cdata
->evaluate
= sel
->evaluate
;
1888 /* Replace the value of the child */
1889 _gmx_selelem_free_values(sel
->child
);
1890 sel
->child
->flags
&= ~(SEL_ALLOCVAL
| SEL_ALLOCDATA
);
1891 _gmx_selvalue_setstore(&sel
->child
->v
, sel
->v
.u
.ptr
);
1892 sel
->child
->evaluate
= &_gmx_sel_evaluate_subexpr_pass
;
1893 if (sel
->child
->cdata
)
1895 sel
->child
->cdata
->evaluate
= sel
->child
->evaluate
;
1897 /* Replace the value of the grandchild */
1898 _gmx_selelem_free_values(sel
->child
->child
);
1899 sel
->child
->child
->flags
&= ~(SEL_ALLOCVAL
| SEL_ALLOCDATA
);
1900 _gmx_selvalue_setstore(&sel
->child
->child
->v
, sel
->v
.u
.ptr
);
1905 /********************************************************************
1906 * COM CALCULATION COMPILER PASS
1907 ********************************************************************/
1910 * Initializes COM/COG calculation for method expressions that require it.
1912 * \param sel Selection subtree to process.
1913 * \param[in,out] pcc Position calculation collection to use.
1914 * \param[in] type Default position calculation type.
1915 * \param[in] flags Flags for default position calculation.
1916 * \returns 0 on success, a non-zero error code on error.
1918 * Searches recursively through the selection tree for dynamic
1919 * \ref SEL_EXPRESSION elements that define the \c gmx_ana_selmethod_t::pupdate
1921 * For each such element found, position calculation is initialized
1922 * for the maximal evaluation group.
1923 * The type of the calculation is determined by \p type and \p flags.
1924 * No calculation is initialized if \p type equals \ref POS_ATOM and
1925 * the method also defines the \c gmx_ana_selmethod_t::update method.
1928 init_item_comg(t_selelem
*sel
, gmx_ana_poscalc_coll_t
*pcc
,
1929 e_poscalc_t type
, int flags
)
1934 /* Initialize COM calculation for dynamic selections now that we know the maximal evaluation group */
1935 if (sel
->type
== SEL_EXPRESSION
&& sel
->u
.expr
.method
1936 && sel
->u
.expr
.method
->pupdate
)
1938 if (!sel
->u
.expr
.method
->update
|| type
!= POS_ATOM
)
1940 /* Create a default calculation if one does not yet exist */
1943 if (!sel
->cdata
->bStaticEval
)
1945 cflags
|= POS_DYNAMIC
;
1947 if (!sel
->u
.expr
.pc
)
1950 rc
= gmx_ana_poscalc_create(&sel
->u
.expr
.pc
, pcc
, type
, cflags
);
1958 gmx_ana_poscalc_set_flags(sel
->u
.expr
.pc
, cflags
);
1960 gmx_ana_poscalc_set_maxindex(sel
->u
.expr
.pc
, sel
->cdata
->gmax
);
1961 snew(sel
->u
.expr
.pos
, 1);
1962 gmx_ana_poscalc_init_pos(sel
->u
.expr
.pc
, sel
->u
.expr
.pos
);
1966 /* Call recursively for all children unless the children have already been processed */
1967 if (sel
->type
!= SEL_SUBEXPRREF
)
1972 rc
= init_item_comg(child
, pcc
, type
, flags
);
1977 child
= child
->next
;
1984 /********************************************************************
1985 * FREE COMPILER DATA PASS
1986 ********************************************************************/
1989 * Frees the allocated compiler data recursively.
1991 * \param sel Root of the selection subtree to process.
1993 * Frees the data allocated for the compilation process.
1996 free_item_compilerdata(t_selelem
*sel
)
2000 /* Free compilation data */
2001 _gmx_selelem_free_compiler_data(sel
);
2003 /* Call recursively for all children unless the children have already been processed */
2004 if (sel
->type
!= SEL_SUBEXPRREF
)
2009 free_item_compilerdata(child
);
2010 child
= child
->next
;
2016 /********************************************************************
2017 * INFORMATION UPDATE
2018 ********************************************************************/
2021 * Updates the information about the selection.
2023 * \param[in] top Topology information.
2024 * \param[in] ngrps Number of elements in the \p sel array.
2025 * \param[in,out] sel Array of selections to update.
2026 * \param[in] bMaskOnly TRUE if the positions will always be calculated
2027 * for all atoms, i.e., the masses/charges do not change.
2029 * Initializes total masses and charges.
2032 update_info(t_topology
*top
, int ngrps
, gmx_ana_selection_t
*sel
[],
2037 for (g
= 0; g
< ngrps
; ++g
)
2039 sel
[g
]->g
= sel
[g
]->p
.g
;
2040 snew(sel
[g
]->orgm
, sel
[g
]->p
.nr
);
2041 snew(sel
[g
]->orgq
, sel
[g
]->p
.nr
);
2042 for (b
= 0; b
< sel
[g
]->p
.nr
; ++b
)
2044 sel
[g
]->orgq
[b
] = 0;
2047 sel
[g
]->orgm
[b
] = 0;
2048 for (i
= sel
[g
]->p
.m
.mapb
.index
[b
]; i
< sel
[g
]->p
.m
.mapb
.index
[b
+1]; ++i
)
2050 sel
[g
]->orgm
[b
] += top
->atoms
.atom
[sel
[g
]->g
->index
[i
]].m
;
2051 sel
[g
]->orgq
[b
] += top
->atoms
.atom
[sel
[g
]->g
->index
[i
]].q
;
2056 sel
[g
]->orgm
[b
] = 1;
2059 if (sel
[g
]->bDynamic
&& !bMaskOnly
)
2061 snew(sel
[g
]->m
, sel
[g
]->p
.nr
);
2062 snew(sel
[g
]->q
, sel
[g
]->p
.nr
);
2063 for (b
= 0; b
< sel
[g
]->p
.nr
; ++b
)
2065 sel
[g
]->m
[b
] = sel
[g
]->orgm
[b
];
2066 sel
[g
]->q
[b
] = sel
[g
]->orgq
[b
];
2071 sel
[g
]->m
= sel
[g
]->orgm
;
2072 sel
[g
]->q
= sel
[g
]->orgq
;
2078 /********************************************************************
2079 * GROUP NAME INITIALIZATION
2080 ********************************************************************/
2083 * Initializes the names of the output index groups.
2085 * \param[in] ngrps Number of elements in the \p sel array.
2086 * \param[in,out] sel Output selections.
2088 * The name for the index group is either taken from the \p name field
2089 * of the root selection element, or set to "Selection N" (for the N'th
2092 static void set_group_names(int ngrps
, gmx_ana_selection_t
*sel
[])
2096 for (g
= 0; g
< ngrps
; ++g
)
2100 if (sel
[g
]->selelem
->name
)
2102 name
= strdup(sel
[g
]->selelem
->name
);
2107 snprintf(name
, 14, "Selection %d", g
+1);
2109 if (!sel
[g
]->selelem
->name
)
2111 sel
[g
]->selelem
->name
= name
;
2113 sel
[g
]->name
= name
;
2118 /********************************************************************
2119 * MAIN COMPILATION FUNCTION
2120 ********************************************************************/
2123 * \param[in,out] sc Selection collection to be compiled.
2124 * \returns 0 on successful compilation, a non-zero error code on error.
2126 * Before compilation, the selection collection should have been initialized
2127 * with gmx_ana_selcollection_parse_*().
2128 * The compiled selection collection can be passed to
2129 * gmx_ana_selcollection_evaluate() to evaluate the selection for a frame.
2130 * If an error occurs, \p sc is cleared.
2132 * The covered fraction information in \p sc is initialized to
2136 gmx_ana_selcollection_compile(gmx_ana_selcollection_t
*sc
)
2138 gmx_sel_evaluate_t evaldata
;
2144 _gmx_sel_evaluate_init(&evaldata
, &sc
->gall
, sc
->top
, NULL
, NULL
);
2146 /* Clear the symbol table because it is not possible to parse anything
2147 * after compilation, and variable references in the symbol table can
2148 * also mess up the compilation and/or become invalid.
2150 _gmx_selcollection_clear_symtab(sc
);
2152 /* Extract subexpressions into separate roots */
2153 sc
->root
= extract_subexpressions(sc
->root
, &sc
->gall
);
2155 /* Initialize the evaluation callbacks and process the tree structure
2156 * to conform to the expectations of the callback functions. */
2157 /* Also, initialize and allocate the compiler data structure */
2161 /* Process boolean expressions */
2162 optimize_boolean_expressions(item
);
2163 reorder_boolean_static_children(item
);
2164 /* Initialize evaluation */
2165 if (!init_item_evaluation(item
))
2167 /* FIXME: Clean up the collection */
2170 /* Initialize the compiler data */
2171 init_item_compilerdata(item
);
2172 init_item_staticeval(item
);
2175 /* Initialize the evaluation index groups */
2176 initialize_evalgrps(sc
);
2178 /* Evaluate all static parts of the selection and analyze the tree
2179 * to allocate enough memory to store the value of each dynamic subtree. */
2183 if (item
->child
->type
== SEL_SUBEXPR
&& item
->child
->refcount
> 2)
2185 mark_subexpr_dynamic(item
->child
, TRUE
);
2187 set_evaluation_function(item
, &analyze_static
);
2188 rc
= item
->evaluate(&evaldata
, item
, NULL
);
2191 /* FIXME: Clean up the collection */
2197 /* Do a second pass to evaluate static parts of common subexpressions */
2198 /* Note that the refcount check skips constant subexpressions completely
2199 * since they were already evaluated by analyze_static(). */
2203 if (item
->child
->type
== SEL_SUBEXPR
&& item
->child
->refcount
> 2)
2205 mark_subexpr_dynamic(item
->child
, FALSE
);
2206 item
->child
->u
.cgrp
.isize
= 0;
2207 if (item
->child
->v
.type
== GROUP_VALUE
)
2209 item
->child
->child
->v
.u
.g
->isize
= 0;
2211 set_evaluation_function(item
, &analyze_static2
);
2212 rc
= item
->evaluate(&evaldata
, item
->child
, item
->child
->cdata
->gmax
);
2215 /* FIXME: Clean up the collection */
2222 /* Create the root elements if they do not yet exist. */
2223 /* The evaluation group of an existing root is also initialized here. */
2224 sc
->root
= process_roots(sc
->root
);
2226 /* Initialize position calculations for methods, perform some final
2227 * optimization and free the memory allocated for the compilation. */
2228 /* By default, use whole residues/molecules. */
2229 flags
= POS_COMPLWHOLE
;
2230 rc
= gmx_ana_poscalc_type_from_enum(sc
->rpost
, &post
, &flags
);
2233 gmx_bug("invalid default reference position type");
2234 /* FIXME: Clean up the collection */
2240 optimize_item_subexpressions(item
);
2241 rc
= init_item_comg(item
, sc
->pcc
, post
, flags
);
2244 /* FIXME: Clean up the collection */
2247 free_item_compilerdata(item
);
2251 /* Finish up by updating some information */
2252 update_info(sc
->top
, sc
->nr
, sc
->sel
, sc
->bMaskOnly
);
2253 set_group_names(sc
->nr
, sc
->sel
);