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
42 #include "gmx_fatal.h"
45 #include "gromacs/selection/indexutil.h"
46 #include "gromacs/selection/poscalc.h"
47 #include "gromacs/selection/position.h"
48 #include "gromacs/selection/selmethod.h"
49 #include "gromacs/utility/exceptions.h"
56 * \param[in] sel Selection for which the string is requested
57 * \returns Pointer to a string that corresponds to \p sel->type.
59 * The return value points to a string constant and should not be \p free'd.
61 * The function returns NULL if \p sel->type is not one of the valid values.
64 _gmx_selelem_type_str(t_selelem *sel)
68 case SEL_CONST: return "CONST";
69 case SEL_EXPRESSION: return "EXPR";
70 case SEL_BOOLEAN: return "BOOL";
71 case SEL_ARITHMETIC: return "ARITH";
72 case SEL_ROOT: return "ROOT";
73 case SEL_SUBEXPR: return "SUBEXPR";
74 case SEL_SUBEXPRREF: return "REF";
75 case SEL_GROUPREF: return "GROUPREF";
76 case SEL_MODIFIER: return "MODIFIER";
82 * \param[in] val Value structore for which the string is requested.
83 * \returns Pointer to a string that corresponds to \p val->type,
84 * NULL if the type value is invalid.
86 * The return value points to a string constant and should not be \p free'd.
89 _gmx_sel_value_type_str(gmx_ana_selvalue_t *val)
93 case NO_VALUE: return "NONE";
94 case INT_VALUE: return "INT";
95 case REAL_VALUE: return "REAL";
96 case STR_VALUE: return "STR";
97 case POS_VALUE: return "VEC";
98 case GROUP_VALUE: return "GROUP";
103 /*! \copydoc _gmx_selelem_type_str() */
105 _gmx_selelem_boolean_type_str(t_selelem *sel)
107 switch (sel->u.boolt)
109 case BOOL_NOT: return "NOT"; break;
110 case BOOL_AND: return "AND"; break;
111 case BOOL_OR: return "OR"; break;
112 case BOOL_XOR: return "XOR"; break;
118 * \param[in] type Type of selection element to allocate.
119 * \returns Pointer to the newly allocated and initialized element.
121 * \c t_selelem::type is set to \p type,
122 * \c t_selelem::v::type is set to \ref GROUP_VALUE for boolean and comparison
123 * expressions and \ref NO_VALUE for others,
124 * \ref SEL_ALLOCVAL is set for non-root elements (\ref SEL_ALLOCDATA is also
125 * set for \ref SEL_BOOLEAN elements),
126 * and \c t_selelem::refcount is set to one.
127 * All the pointers are set to NULL.
130 _gmx_selelem_create(e_selelem_t type)
137 sel->flags = (type != SEL_ROOT) ? SEL_ALLOCVAL : 0;
138 if (type == SEL_BOOLEAN)
140 sel->v.type = GROUP_VALUE;
141 sel->flags |= SEL_ALLOCDATA;
145 sel->v.type = NO_VALUE;
147 _gmx_selvalue_clear(&sel->v);
148 sel->evaluate = NULL;
158 * \param[in,out] sel Selection element to set the type for.
159 * \param[in] vtype Value type for the selection element.
160 * \returns 0 on success, EINVAL if the value type is invalid.
162 * If the new type is \ref GROUP_VALUE or \ref POS_VALUE, the
163 * \ref SEL_ALLOCDATA flag is also set.
165 * This function should only be called at most once for each element,
166 * preferably right after calling _gmx_selelem_create().
169 _gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype)
171 if (sel->type == SEL_BOOLEAN && vtype != GROUP_VALUE)
173 gmx_bug("internal error");
176 if (sel->v.type != NO_VALUE && vtype != sel->v.type)
178 gmx_call("_gmx_selelem_set_vtype() called more than once");
182 if (vtype == GROUP_VALUE || vtype == POS_VALUE)
184 sel->flags |= SEL_ALLOCDATA;
190 * \param[in,out] sel Selection element to reserve.
191 * \param[in] count Number of values to reserve memory for.
192 * \returns 0 on success or if no memory pool, non-zero on error.
194 * Reserves memory for the values of \p sel from the \p sel->mempool
195 * memory pool. If no memory pool is set, nothing is done.
198 _gmx_selelem_mempool_reserve(t_selelem *sel, int count)
207 sel->v.u.i = static_cast<int *>(
208 _gmx_sel_mempool_alloc(sel->mempool, sizeof(*sel->v.u.i)*count));
212 sel->v.u.r = static_cast<real *>(
213 _gmx_sel_mempool_alloc(sel->mempool, sizeof(*sel->v.u.r)*count));
217 _gmx_sel_mempool_alloc_group(sel->mempool, sel->v.u.g, count);
221 GMX_THROW(gmx::InternalError("Memory pooling not implemented for requested type"));
226 * \param[in,out] sel Selection element to release.
228 * Releases the memory allocated for the values of \p sel from the
229 * \p sel->mempool memory pool. If no memory pool is set, nothing is done.
232 _gmx_selelem_mempool_release(t_selelem *sel)
242 _gmx_sel_mempool_free(sel->mempool, sel->v.u.ptr);
243 _gmx_selvalue_setstore(&sel->v, NULL);
249 _gmx_sel_mempool_free_group(sel->mempool, sel->v.u.g);
254 GMX_THROW(gmx::InternalError("Memory pooling not implemented for requested type"));
259 * \param[in] sel Selection to free.
262 _gmx_selelem_free_values(t_selelem *sel)
266 _gmx_selelem_mempool_release(sel);
267 if ((sel->flags & SEL_ALLOCDATA) && sel->v.u.ptr)
269 /* The number of position/group structures is constant, so the
270 * backup of using sel->v.nr should work for them.
271 * For strings, we report an error if we don't know the allocation
273 n = (sel->v.nalloc > 0) ? sel->v.nalloc : sel->v.nr;
277 if (sel->v.nalloc == 0)
279 gmx_bug("SEL_ALLOCDATA should only be set for allocated STR_VALUE values");
282 for (i = 0; i < n; ++i)
284 sfree(sel->v.u.s[i]);
288 for (i = 0; i < n; ++i)
290 gmx_ana_pos_deinit(&sel->v.u.p[i]);
294 for (i = 0; i < n; ++i)
296 gmx_ana_index_deinit(&sel->v.u.g[i]);
299 default: /* No special handling for other types */
303 if (sel->flags & SEL_ALLOCVAL)
307 _gmx_selvalue_setstore(&sel->v, NULL);
308 if (sel->type == SEL_SUBEXPRREF && sel->u.param)
310 sel->u.param->val.u.ptr = NULL;
315 * \param[in] method Method to free.
316 * \param[in] mdata Method data to free.
319 _gmx_selelem_free_method(gmx_ana_selmethod_t *method, void *mdata)
321 sel_freefunc free_func = NULL;
323 /* Save the pointer to the free function. */
324 if (method && method->free)
326 free_func = method->free;
329 /* Free the method itself.
330 * Has to be done before freeing the method data, because parameter
331 * values are typically stored in the method data, and here we may
337 /* Free the memory allocated for the parameters that are not managed
338 * by the selection method itself. */
339 for (i = 0; i < method->nparams; ++i)
341 gmx_ana_selparam_t *param = &method->param[i];
343 if (param->val.u.ptr)
345 if (param->val.type == GROUP_VALUE)
347 for (j = 0; j < param->val.nr; ++j)
349 gmx_ana_index_deinit(¶m->val.u.g[j]);
352 else if (param->val.type == POS_VALUE)
354 for (j = 0; j < param->val.nr; ++j)
356 gmx_ana_pos_deinit(¶m->val.u.p[j]);
360 if (param->val.nalloc > 0)
362 sfree(param->val.u.ptr);
366 sfree(method->param);
369 /* Free method data. */
381 * \param[in] sel Selection to free.
384 _gmx_selelem_free_exprdata(t_selelem *sel)
386 if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
388 _gmx_selelem_free_method(sel->u.expr.method, sel->u.expr.mdata);
389 sel->u.expr.mdata = NULL;
390 sel->u.expr.method = NULL;
391 /* Free position data */
394 gmx_ana_pos_free(sel->u.expr.pos);
395 sel->u.expr.pos = NULL;
397 /* Free position calculation data */
400 gmx_ana_poscalc_free(sel->u.expr.pc);
401 sel->u.expr.pc = NULL;
404 if (sel->type == SEL_ARITHMETIC)
406 sfree(sel->u.arith.opstr);
407 sel->u.arith.opstr = NULL;
409 if (sel->type == SEL_SUBEXPR || sel->type == SEL_ROOT
410 || (sel->type == SEL_CONST && sel->v.type == GROUP_VALUE))
412 gmx_ana_index_deinit(&sel->u.cgrp);
414 if (sel->type == SEL_GROUPREF)
416 sfree(sel->u.gref.name);
421 * \param[in] sel Selection to free.
423 * Decrements \ref t_selelem::refcount "sel->refcount" and frees the
424 * memory allocated for \p sel and all its children if the reference count
428 _gmx_selelem_free(t_selelem *sel)
430 /* Decrement the reference counter and do nothing if references remain */
432 if (sel->refcount > 0)
437 /* Free the children.
438 * Must be done before freeing other data, because the children may hold
439 * references to data in this element. */
440 _gmx_selelem_free_chain(sel->child);
442 /* Free value storage */
443 _gmx_selelem_free_values(sel);
445 /* Free other storage */
446 _gmx_selelem_free_exprdata(sel);
448 /* Free temporary compiler data if present */
449 _gmx_selelem_free_compiler_data(sel);
455 * \param[in] first First selection to free.
457 * Frees \p first and all selections accessible through the
458 * \ref t_selelem::next "first->next" pointer.
461 _gmx_selelem_free_chain(t_selelem *first)
463 t_selelem *child, *prev;
470 _gmx_selelem_free(prev);
475 * \param[in] fp File handle to receive the output.
476 * \param[in] sel Root of the selection subtree to print.
477 * \param[in] bValues If true, the evaluated values of selection elements
478 * are printed as well.
479 * \param[in] level Indentation level, starting from zero.
482 _gmx_selelem_print_tree(FILE *fp, t_selelem *sel, bool bValues, int level)
487 fprintf(fp, "%*c %s %s", level*2+1, '*',
488 _gmx_selelem_type_str(sel), _gmx_sel_value_type_str(&sel->v));
491 fprintf(fp, " \"%s\"", sel->name);
493 fprintf(fp, " flg=");
494 if (sel->flags & SEL_FLAGSSET)
498 if (sel->flags & SEL_SINGLEVAL)
502 if (sel->flags & SEL_ATOMVAL)
506 if (sel->flags & SEL_VARNUMVAL)
510 if (sel->flags & SEL_DYNAMIC)
514 if (!(sel->flags & SEL_VALFLAGMASK))
522 if (sel->type == SEL_CONST)
524 if (sel->v.type == INT_VALUE)
526 fprintf(fp, " %d", sel->v.u.i[0]);
528 else if (sel->v.type == REAL_VALUE)
530 fprintf(fp, " %f", sel->v.u.r[0]);
532 else if (sel->v.type == GROUP_VALUE)
534 gmx_ana_index_t *g = sel->v.u.g;
535 if (!g || g->isize == 0)
537 fprintf(fp, " (%d atoms)", g->isize);
540 else if (sel->type == SEL_BOOLEAN)
542 fprintf(fp, " %s", _gmx_selelem_boolean_type_str(sel));
544 else if (sel->type == SEL_EXPRESSION
545 && sel->u.expr.method->name == sm_compare.name)
547 _gmx_selelem_print_compare_info(fp, sel->u.expr.mdata);
551 fprintf(fp, " eval=");
552 _gmx_sel_print_evalfunc_name(fp, sel->evaluate);
554 if (sel->refcount > 1)
556 fprintf(fp, " refc=%d", sel->refcount);
558 if (!(sel->flags & SEL_ALLOCVAL))
560 fprintf(fp, " (ext. output)");
564 if ((sel->type == SEL_CONST && sel->v.type == GROUP_VALUE) || sel->type == SEL_ROOT)
566 gmx_ana_index_t *g = sel->v.u.g;
567 if (!g || g->isize == 0 || sel->evaluate != NULL)
573 fprintf(fp, "%*c group: (null)\n", level*2+1, ' ');
575 else if (g->isize > 0)
577 fprintf(fp, "%*c group:", level*2+1, ' ');
580 for (i = 0; i < g->isize; ++i)
582 fprintf(fp, " %d", g->index[i] + 1);
587 fprintf(fp, " %d atoms", g->isize);
592 else if (sel->type == SEL_EXPRESSION)
596 fprintf(fp, "%*c COM", level*2+3, '*');
603 _gmx_selelem_print_compiler_info(fp, sel, level);
606 if (bValues && sel->type != SEL_CONST && sel->type != SEL_ROOT && sel->v.u.ptr)
608 fprintf(fp, "%*c value: ", level*2+1, ' ');
612 /* In normal use, the pointer should never be NULL, but it's
613 * useful to have the check for debugging to avoid accidental
614 * segfaults when printing the selection tree. */
617 fprintf(fp, "(%f, %f, %f)",
618 sel->v.u.p->x[0][XX], sel->v.u.p->x[0][YY],
619 sel->v.u.p->x[0][ZZ]);
623 fprintf(fp, "(null)");
627 fprintf(fp, "%d atoms", sel->v.u.g->isize);
628 if (sel->v.u.g->isize < 20)
630 if (sel->v.u.g->isize > 0)
634 for (i = 0; i < sel->v.u.g->isize; ++i)
636 fprintf(fp, " %d", sel->v.u.g->index[i] + 1);
647 /* Print the subexpressions with one more level of indentation */
651 if (!(sel->type == SEL_SUBEXPRREF && child->type == SEL_SUBEXPR))
653 _gmx_selelem_print_tree(fp, child, bValues, level+1);
660 * \param[in] root Root of the subtree to query.
661 * \returns true if \p root or any any of its elements require topology
662 * information, false otherwise.
665 _gmx_selelem_requires_top(t_selelem *root)
669 if (root->type == SEL_EXPRESSION || root->type == SEL_MODIFIER)
671 if (root->u.expr.method && (root->u.expr.method->flags & SMETH_REQTOP))
675 if (root->u.expr.pc && gmx_ana_poscalc_requires_top(root->u.expr.pc))
683 if (_gmx_selelem_requires_top(child))