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
33 * Implements functions in selelem.h.
35 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36 * \ingroup module_selection
40 #include "gromacs/legacyheaders/smalloc.h"
42 #include "gromacs/selection/indexutil.h"
43 #include "gromacs/selection/poscalc.h"
44 #include "gromacs/selection/position.h"
45 #include "gromacs/selection/selmethod.h"
46 #include "gromacs/utility/exceptions.h"
47 #include "gromacs/utility/gmxassert.h"
54 * \param[in] sel Selection for which the string is requested
55 * \returns Pointer to a string that corresponds to \p sel->type.
57 * The return value points to a string constant and should not be \p free'd.
59 * The function returns NULL if \p sel->type is not one of the valid values.
62 _gmx_selelem_type_str(const gmx::SelectionTreeElement &sel)
66 case SEL_CONST: return "CONST";
67 case SEL_EXPRESSION: return "EXPR";
68 case SEL_BOOLEAN: return "BOOL";
69 case SEL_ARITHMETIC: return "ARITH";
70 case SEL_ROOT: return "ROOT";
71 case SEL_SUBEXPR: return "SUBEXPR";
72 case SEL_SUBEXPRREF: return "REF";
73 case SEL_GROUPREF: return "GROUPREF";
74 case SEL_MODIFIER: return "MODIFIER";
80 * \param[in] val Value structore for which the string is requested.
81 * \returns Pointer to a string that corresponds to \p val->type,
82 * NULL if the type value is invalid.
84 * The return value points to a string constant and should not be \p free'd.
87 _gmx_sel_value_type_str(const gmx_ana_selvalue_t *val)
91 case NO_VALUE: return "NONE";
92 case INT_VALUE: return "INT";
93 case REAL_VALUE: return "REAL";
94 case STR_VALUE: return "STR";
95 case POS_VALUE: return "VEC";
96 case GROUP_VALUE: return "GROUP";
101 /*! \copydoc _gmx_selelem_type_str() */
103 _gmx_selelem_boolean_type_str(const gmx::SelectionTreeElement &sel)
107 case BOOL_NOT: return "NOT"; break;
108 case BOOL_AND: return "AND"; break;
109 case BOOL_OR: return "OR"; break;
110 case BOOL_XOR: return "XOR"; break;
119 SelectionTreeElement::SelectionTreeElement(e_selelem_t type)
122 this->flags = (type != SEL_ROOT) ? SEL_ALLOCVAL : 0;
123 if (type == SEL_BOOLEAN)
125 this->v.type = GROUP_VALUE;
126 this->flags |= SEL_ALLOCDATA;
130 this->v.type = NO_VALUE;
132 _gmx_selvalue_clear(&this->v);
133 std::memset(&this->u, 0, sizeof(this->u));
134 this->evaluate = NULL;
135 this->mempool = NULL;
139 SelectionTreeElement::~SelectionTreeElement()
141 /* Free the children.
142 * Must be done before freeing other data, because the children may hold
143 * references to data in this element. */
147 freeExpressionData();
151 void SelectionTreeElement::freeValues()
154 if ((flags & SEL_ALLOCDATA) && v.u.ptr)
156 /* The number of position/group structures is constant, so the
157 * backup of using sel->v.nr should work for them.
158 * For strings, we report an error if we don't know the allocation
160 int n = (v.nalloc > 0) ? v.nalloc : v.nr;
164 GMX_RELEASE_ASSERT(v.nalloc != 0,
165 "SEL_ALLOCDATA should only be set for allocated "
167 for (int i = 0; i < n; ++i)
173 for (int i = 0; i < n; ++i)
175 gmx_ana_pos_deinit(&v.u.p[i]);
179 for (int i = 0; i < n; ++i)
181 gmx_ana_index_deinit(&v.u.g[i]);
184 default: /* No special handling for other types */
188 if (flags & SEL_ALLOCVAL)
192 _gmx_selvalue_setstore(&v, NULL);
193 if (type == SEL_SUBEXPRREF && u.param)
195 u.param->val.u.ptr = NULL;
200 SelectionTreeElement::freeExpressionData()
202 if (type == SEL_EXPRESSION || type == SEL_MODIFIER)
204 _gmx_selelem_free_method(u.expr.method, u.expr.mdata);
206 u.expr.method = NULL;
207 /* Free position data */
210 gmx_ana_pos_free(u.expr.pos);
213 /* Free position calculation data */
216 gmx_ana_poscalc_free(u.expr.pc);
220 if (type == SEL_ARITHMETIC)
222 sfree(u.arith.opstr);
223 u.arith.opstr = NULL;
225 if (type == SEL_SUBEXPR || type == SEL_ROOT
226 || (type == SEL_CONST && v.type == GROUP_VALUE))
228 gmx_ana_index_deinit(&u.cgrp);
230 if (type == SEL_GROUPREF)
236 void SelectionTreeElement::mempoolReserve(int count)
245 v.u.i = static_cast<int *>(
246 _gmx_sel_mempool_alloc(mempool, sizeof(*v.u.i)*count));
250 v.u.r = static_cast<real *>(
251 _gmx_sel_mempool_alloc(mempool, sizeof(*v.u.r)*count));
255 _gmx_sel_mempool_alloc_group(mempool, v.u.g, count);
259 GMX_THROW(gmx::InternalError("Memory pooling not implemented for requested type"));
263 void SelectionTreeElement::mempoolRelease()
273 _gmx_sel_mempool_free(mempool, v.u.ptr);
274 _gmx_selvalue_setstore(&v, NULL);
280 _gmx_sel_mempool_free_group(mempool, v.u.g);
285 GMX_THROW(gmx::InternalError("Memory pooling not implemented for requested type"));
292 * \param[in,out] sel Selection element to set the type for.
293 * \param[in] vtype Value type for the selection element.
295 * If the new type is \ref GROUP_VALUE or \ref POS_VALUE, the
296 * \ref SEL_ALLOCDATA flag is also set.
298 * This function should only be called at most once for each element,
299 * preferably right after calling _gmx_selelem_create().
302 _gmx_selelem_set_vtype(const gmx::SelectionTreeElementPointer &sel,
305 GMX_RELEASE_ASSERT(sel->type != SEL_BOOLEAN || vtype == GROUP_VALUE,
306 "Boolean elements must have a group value");
307 GMX_RELEASE_ASSERT(sel->v.type == NO_VALUE || vtype == sel->v.type,
308 "_gmx_selelem_set_vtype() called more than once");
310 if (vtype == GROUP_VALUE || vtype == POS_VALUE)
312 sel->flags |= SEL_ALLOCDATA;
317 * \param[in] method Method to free.
318 * \param[in] mdata Method data to free.
321 _gmx_selelem_free_method(gmx_ana_selmethod_t *method, void *mdata)
323 sel_freefunc free_func = NULL;
325 /* Save the pointer to the free function. */
326 if (method && method->free)
328 free_func = method->free;
331 /* Free the method itself.
332 * Has to be done before freeing the method data, because parameter
333 * values are typically stored in the method data, and here we may
339 /* Free the memory allocated for the parameters that are not managed
340 * by the selection method itself. */
341 for (i = 0; i < method->nparams; ++i)
343 gmx_ana_selparam_t *param = &method->param[i];
345 if (param->val.u.ptr)
347 if (param->val.type == GROUP_VALUE)
349 for (j = 0; j < param->val.nr; ++j)
351 gmx_ana_index_deinit(¶m->val.u.g[j]);
354 else if (param->val.type == POS_VALUE)
356 for (j = 0; j < param->val.nr; ++j)
358 gmx_ana_pos_deinit(¶m->val.u.p[j]);
362 if (param->val.nalloc > 0)
364 sfree(param->val.u.ptr);
368 sfree(method->param);
371 /* Free method data. */
386 * \param[in] fp File handle to receive the output.
387 * \param[in] sel Root of the selection subtree to print.
388 * \param[in] bValues If true, the evaluated values of selection elements
389 * are printed as well.
390 * \param[in] level Indentation level, starting from zero.
393 _gmx_selelem_print_tree(FILE *fp, const gmx::SelectionTreeElement &sel,
394 bool bValues, int level)
398 fprintf(fp, "%*c %s %s", level*2+1, '*',
399 _gmx_selelem_type_str(sel), _gmx_sel_value_type_str(&sel.v));
400 if (!sel.name().empty())
402 fprintf(fp, " \"%s\"", sel.name().c_str());
404 fprintf(fp, " flg=");
405 if (sel.flags & SEL_FLAGSSET)
409 if (sel.flags & SEL_SINGLEVAL)
413 if (sel.flags & SEL_ATOMVAL)
417 if (sel.flags & SEL_VARNUMVAL)
421 if (sel.flags & SEL_DYNAMIC)
425 if (!(sel.flags & SEL_VALFLAGMASK))
433 if (sel.type == SEL_CONST)
435 if (sel.v.type == INT_VALUE)
437 fprintf(fp, " %d", sel.v.u.i[0]);
439 else if (sel.v.type == REAL_VALUE)
441 fprintf(fp, " %f", sel.v.u.r[0]);
443 else if (sel.v.type == GROUP_VALUE)
445 const gmx_ana_index_t *g = sel.v.u.g;
446 if (!g || g->isize == 0)
448 fprintf(fp, " (%d atoms)", g->isize);
451 else if (sel.type == SEL_BOOLEAN)
453 fprintf(fp, " %s", _gmx_selelem_boolean_type_str(sel));
455 else if (sel.type == SEL_EXPRESSION
456 && sel.u.expr.method->name == sm_compare.name)
458 _gmx_selelem_print_compare_info(fp, sel.u.expr.mdata);
462 fprintf(fp, " eval=");
463 _gmx_sel_print_evalfunc_name(fp, sel.evaluate);
465 if (!(sel.flags & SEL_ALLOCVAL))
467 fprintf(fp, " (ext. output)");
471 if ((sel.type == SEL_CONST && sel.v.type == GROUP_VALUE) || sel.type == SEL_ROOT)
473 const gmx_ana_index_t *g = sel.v.u.g;
474 if (!g || g->isize == 0 || sel.evaluate != NULL)
480 fprintf(fp, "%*c group: (null)\n", level*2+1, ' ');
482 else if (g->isize > 0)
484 fprintf(fp, "%*c group:", level*2+1, ' ');
487 for (i = 0; i < g->isize; ++i)
489 fprintf(fp, " %d", g->index[i] + 1);
494 fprintf(fp, " %d atoms", g->isize);
499 else if (sel.type == SEL_EXPRESSION)
503 fprintf(fp, "%*c COM", level*2+3, '*');
510 _gmx_selelem_print_compiler_info(fp, sel, level);
513 if (bValues && sel.type != SEL_CONST && sel.type != SEL_ROOT && sel.v.u.ptr)
515 fprintf(fp, "%*c value: ", level*2+1, ' ');
519 /* In normal use, the pointer should never be NULL, but it's
520 * useful to have the check for debugging to avoid accidental
521 * segfaults when printing the selection tree. */
524 fprintf(fp, "(%f, %f, %f)",
525 sel.v.u.p->x[0][XX], sel.v.u.p->x[0][YY],
526 sel.v.u.p->x[0][ZZ]);
530 fprintf(fp, "(null)");
534 fprintf(fp, "%d atoms", sel.v.u.g->isize);
535 if (sel.v.u.g->isize < 20)
537 if (sel.v.u.g->isize > 0)
541 for (i = 0; i < sel.v.u.g->isize; ++i)
543 fprintf(fp, " %d", sel.v.u.g->index[i] + 1);
554 /* Print the subexpressions with one more level of indentation */
555 gmx::SelectionTreeElementPointer child = sel.child;
558 if (!(sel.type == SEL_SUBEXPRREF && child->type == SEL_SUBEXPR))
560 _gmx_selelem_print_tree(fp, *child, bValues, level+1);
567 * \param[in] root Root of the subtree to query.
568 * \returns true if \p root or any any of its elements require topology
569 * information, false otherwise.
572 _gmx_selelem_requires_top(const gmx::SelectionTreeElement &root)
574 if (root.type == SEL_EXPRESSION || root.type == SEL_MODIFIER)
576 if (root.u.expr.method && (root.u.expr.method->flags & SMETH_REQTOP))
580 if (root.u.expr.pc && gmx_ana_poscalc_requires_top(root.u.expr.pc))
585 gmx::SelectionTreeElementPointer child = root.child;
588 if (_gmx_selelem_requires_top(*child))