09971c053894f90799d278c1460c10ec0958ee96
[alexxy/gromacs.git] / src / gmxlib / selection / selelem.c
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
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.
13
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.
18  *
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.
25  *
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.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \internal \file
32  * \brief Implementation of functions in selelem.h.
33  */
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include <smalloc.h>
39 #include <gmx_fatal.h>
40
41 #include <indexutil.h>
42 #include <poscalc.h>
43 #include <position.h>
44 #include <selmethod.h>
45
46 #include "keywords.h"
47 #include "mempool.h"
48 #include "selelem.h"
49
50 /*!
51  * \param[in] sel Selection for which the string is requested
52  * \returns   Pointer to a string that corresponds to \p sel->type.
53  *
54  * The return value points to a string constant and should not be \p free'd.
55  * 
56  * The function returns NULL if \p sel->type is not one of the valid values.
57  */
58 const char *
59 _gmx_selelem_type_str(t_selelem *sel)
60 {
61     switch (sel->type)
62     {
63         case SEL_CONST:      return "CONST";
64         case SEL_EXPRESSION: return "EXPR";
65         case SEL_BOOLEAN:    return "BOOL";
66         case SEL_ARITHMETIC: return "ARITH";
67         case SEL_ROOT:       return "ROOT";
68         case SEL_SUBEXPR:    return "SUBEXPR";
69         case SEL_SUBEXPRREF: return "REF";
70         case SEL_MODIFIER:   return "MODIFIER";
71     }
72     return NULL;
73 }
74
75 /*!
76  * \param[in] val Value structore for which the string is requested.
77  * \returns   Pointer to a string that corresponds to \p val->type,
78  *   NULL if the type value is invalid.
79  *
80  * The return value points to a string constant and should not be \p free'd.
81  */
82 const char *
83 _gmx_sel_value_type_str(gmx_ana_selvalue_t *val)
84 {
85     switch (val->type)
86     {
87         case NO_VALUE:       return "NONE";
88         case INT_VALUE:      return "INT";
89         case REAL_VALUE:     return "REAL";
90         case STR_VALUE:      return "STR";
91         case POS_VALUE:      return "VEC";
92         case GROUP_VALUE:    return "GROUP";
93     }
94     return NULL;
95 }
96
97 /*! \copydoc _gmx_selelem_type_str() */
98 const char *
99 _gmx_selelem_gmx_boolean_type_str(t_selelem *sel)
100 {
101     switch (sel->u.boolt)
102     {
103         case BOOL_NOT:  return "NOT"; break;
104         case BOOL_AND:  return "AND"; break;
105         case BOOL_OR:   return "OR";  break;
106         case BOOL_XOR:  return "XOR"; break;
107     }
108     return NULL;
109 }
110
111 /*!
112  * \param[in] type Type of selection element to allocate.
113  * \returns   Pointer to the newly allocated and initialized element.
114  *
115  * \c t_selelem::type is set to \p type,
116  * \c t_selelem::v::type is set to \ref GROUP_VALUE for gmx_boolean and comparison
117  * expressions and \ref NO_VALUE for others,
118  * \ref SEL_ALLOCVAL is set for non-root elements (\ref SEL_ALLOCDATA is also
119  * set for \ref SEL_BOOLEAN elements),
120  * and \c t_selelem::refcount is set to one.
121  * All the pointers are set to NULL.
122  */
123 t_selelem *
124 _gmx_selelem_create(e_selelem_t type)
125 {
126     t_selelem *sel;
127
128     snew(sel, 1);
129     sel->name       = NULL;
130     sel->type       = type;
131     sel->flags      = (type != SEL_ROOT) ? SEL_ALLOCVAL : 0;
132     if (type == SEL_BOOLEAN)
133     {
134         sel->v.type = GROUP_VALUE;
135         sel->flags |= SEL_ALLOCDATA;
136     }
137     else
138     {
139         sel->v.type = NO_VALUE;
140     }
141     _gmx_selvalue_clear(&sel->v);
142     sel->evaluate   = NULL;
143     sel->mempool    = NULL;
144     sel->child      = NULL;
145     sel->next       = NULL;
146     sel->refcount   = 1;
147
148     return sel;
149 }
150
151 /*!
152  * \param[in,out] sel   Selection element to set the type for.
153  * \param[in]     vtype Value type for the selection element.
154  * \returns       0 on success, EINVAL if the value type is invalid.
155  *
156  * If the new type is \ref GROUP_VALUE or \ref POS_VALUE, the
157  * \ref SEL_ALLOCDATA flag is also set.
158  *
159  * This function should only be called at most once for each element,
160  * preferably right after calling _gmx_selelem_create().
161  */
162 int
163 _gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype)
164 {
165     if (sel->type == SEL_BOOLEAN && vtype != GROUP_VALUE)
166     {
167         gmx_bug("internal error");
168         return EINVAL;
169     }
170     if (sel->v.type != NO_VALUE && vtype != sel->v.type)
171     {
172         gmx_call("_gmx_selelem_set_vtype() called more than once");
173         return EINVAL;
174     }
175     sel->v.type = vtype;
176     if (vtype == GROUP_VALUE || vtype == POS_VALUE)
177     {
178         sel->flags |= SEL_ALLOCDATA;
179     }
180     return 0;
181 }
182
183 /*!
184  * \param[in,out] sel   Selection element to reserve.
185  * \param[in]     count Number of values to reserve memory for.
186  * \returns       0 on success or if no memory pool, non-zero on error.
187  *
188  * Reserves memory for the values of \p sel from the \p sel->mempool
189  * memory pool. If no memory pool is set, nothing is done.
190  */
191 int
192 _gmx_selelem_mempool_reserve(t_selelem *sel, int count)
193 {
194     int rc = 0;
195
196     if (!sel->mempool)
197     {
198         return 0;
199     }
200     switch (sel->v.type)
201     {
202         case INT_VALUE:
203             rc = _gmx_sel_mempool_alloc(sel->mempool, (void **)&sel->v.u.i,
204                                         sizeof(*sel->v.u.i)*count);
205             break;
206
207         case REAL_VALUE:
208             rc = _gmx_sel_mempool_alloc(sel->mempool, (void **)&sel->v.u.r,
209                                         sizeof(*sel->v.u.r)*count);
210             break;
211
212         case GROUP_VALUE:
213             rc = _gmx_sel_mempool_alloc_group(sel->mempool, sel->v.u.g, count);
214             break;
215
216         default:
217             gmx_incons("mem pooling not implemented for requested type");
218             return -1;
219     }
220     return rc;
221 }
222
223 /*!
224  * \param[in,out] sel   Selection element to release.
225  *
226  * Releases the memory allocated for the values of \p sel from the
227  * \p sel->mempool memory pool. If no memory pool is set, nothing is done.
228  */
229 void
230 _gmx_selelem_mempool_release(t_selelem *sel)
231 {
232     if (!sel->mempool)
233     {
234         return;
235     }
236     switch (sel->v.type)
237     {
238         case INT_VALUE:
239         case REAL_VALUE:
240             _gmx_sel_mempool_free(sel->mempool, sel->v.u.ptr);
241             _gmx_selvalue_setstore(&sel->v, NULL);
242             break;
243
244         case GROUP_VALUE:
245             if (sel->v.u.g)
246             {
247                 _gmx_sel_mempool_free_group(sel->mempool, sel->v.u.g);
248             }
249             break;
250
251         default:
252             gmx_incons("mem pooling not implemented for requested type");
253             break;
254     }
255 }
256
257 /*!
258  * \param[in] sel Selection to free.
259  */
260 void
261 _gmx_selelem_free_values(t_selelem *sel)
262 {
263     int   i, n;
264
265     _gmx_selelem_mempool_release(sel);
266     if ((sel->flags & SEL_ALLOCDATA) && sel->v.u.ptr)
267     {
268         /* The number of position/group structures is constant, so the
269          * backup of using sel->v.nr should work for them.
270          * For strings, we report an error if we don't know the allocation
271          * size here. */
272         n = (sel->v.nalloc > 0) ? sel->v.nalloc : sel->v.nr;
273         switch (sel->v.type)
274         {
275             case STR_VALUE:
276                 if (sel->v.nalloc == 0)
277                 {
278                     gmx_bug("SEL_ALLOCDATA should only be set for allocated STR_VALUE values");
279                     break;
280                 }
281                 for (i = 0; i < n; ++i)
282                 {
283                     sfree(sel->v.u.s[i]);
284                 }
285                 break;
286             case POS_VALUE:
287                 for (i = 0; i < n; ++i)
288                 {
289                     gmx_ana_pos_deinit(&sel->v.u.p[i]);
290                 }
291                 break;
292             case GROUP_VALUE:
293                 for (i = 0; i < n; ++i)
294                 {
295                     gmx_ana_index_deinit(&sel->v.u.g[i]);
296                 }
297                 break;
298             default: /* No special handling for other types */
299                 break;
300         }
301     }
302     if (sel->flags & SEL_ALLOCVAL)
303     {
304         sfree(sel->v.u.ptr);
305     }
306     _gmx_selvalue_setstore(&sel->v, NULL);
307     if (sel->type == SEL_SUBEXPRREF && sel->u.param)
308     {
309         sel->u.param->val.u.ptr = NULL;
310     }
311 }
312
313 /*!
314  * \param[in] method Method to free.
315  * \param[in] mdata  Method data to free.
316  */
317 void
318 _gmx_selelem_free_method(gmx_ana_selmethod_t *method, void *mdata)
319 {
320     sel_freefunc free_func = NULL;
321
322     /* Save the pointer to the free function. */
323     if (method && method->free)
324     {
325         free_func = method->free;
326     }
327
328     /* Free the method itself.
329      * Has to be done before freeing the method data, because parameter
330      * values are typically stored in the method data, and here we may
331      * access them. */
332     if (method)
333     {
334         int  i, j;
335
336         /* Free the memory allocated for the parameters that are not managed
337          * by the selection method itself. */
338         for (i = 0; i < method->nparams; ++i)
339         {
340             gmx_ana_selparam_t *param = &method->param[i];
341
342             if (param->val.u.ptr)
343             {
344                 if (param->val.type == GROUP_VALUE)
345                 {
346                     for (j = 0; j < param->val.nr; ++j)
347                     {
348                         gmx_ana_index_deinit(&param->val.u.g[j]);
349                     }
350                 }
351                 else if (param->val.type == POS_VALUE)
352                 {
353                     for (j = 0; j < param->val.nr; ++j)
354                     {
355                         gmx_ana_pos_deinit(&param->val.u.p[j]);
356                     }
357                 }
358
359                 if (param->val.nalloc > 0)
360                 {
361                     sfree(param->val.u.ptr);
362                 }
363             }
364         }
365         sfree(method->param);
366         sfree(method);
367     }
368     /* Free method data. */
369     if (mdata)
370     {
371         if (free_func)
372         {
373             free_func(mdata);
374         }
375         sfree(mdata);
376     }
377 }
378
379 /*!
380  * \param[in] sel Selection to free.
381  */
382 void
383 _gmx_selelem_free_exprdata(t_selelem *sel)
384 {
385     if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
386     {
387         _gmx_selelem_free_method(sel->u.expr.method, sel->u.expr.mdata);
388         sel->u.expr.mdata = NULL;
389         sel->u.expr.method = NULL;
390         /* Free position data */
391         if (sel->u.expr.pos)
392         {
393             gmx_ana_pos_free(sel->u.expr.pos);
394             sel->u.expr.pos = NULL;
395         }
396         /* Free position calculation data */
397         if (sel->u.expr.pc)
398         {
399             gmx_ana_poscalc_free(sel->u.expr.pc);
400             sel->u.expr.pc = NULL;
401         }
402     }
403     if (sel->type == SEL_ARITHMETIC)
404     {
405         sfree(sel->u.arith.opstr);
406         sel->u.arith.opstr = NULL;
407     }
408     if (sel->type == SEL_SUBEXPR || sel->type == SEL_ROOT
409         || (sel->type == SEL_CONST && sel->v.type == GROUP_VALUE))
410     {
411         gmx_ana_index_deinit(&sel->u.cgrp);
412     }
413 }
414
415 /*!
416  * \param[in] sel Selection to free.
417  *
418  * Decrements \ref t_selelem::refcount "sel->refcount" and frees the
419  * memory allocated for \p sel and all its children if the reference count
420  * reaches zero.
421  */
422 void
423 _gmx_selelem_free(t_selelem *sel)
424 {
425     /* Decrement the reference counter and do nothing if references remain */
426     sel->refcount--;
427     if (sel->refcount > 0)
428     {
429         return;
430     }
431
432     /* Free the children.
433      * Must be done before freeing other data, because the children may hold
434      * references to data in this element. */
435     _gmx_selelem_free_chain(sel->child);
436
437     /* Free value storage */
438     _gmx_selelem_free_values(sel);
439
440     /* Free other storage */
441     _gmx_selelem_free_exprdata(sel);
442
443     /* Free temporary compiler data if present */
444     _gmx_selelem_free_compiler_data(sel);
445
446     sfree(sel);
447 }
448
449 /*!
450  * \param[in] first First selection to free.
451  *
452  * Frees \p first and all selections accessible through the
453  * \ref t_selelem::next "first->next" pointer.
454  */
455 void
456 _gmx_selelem_free_chain(t_selelem *first)
457 {
458     t_selelem *child, *prev;
459
460     child = first;
461     while (child)
462     {
463         prev = child;
464         child = child->next;
465         _gmx_selelem_free(prev);
466     }
467 }
468
469 /*!
470  * \param[in] fp      File handle to receive the output.
471  * \param[in] sel     Root of the selection subtree to print.
472  * \param[in] bValues If TRUE, the evaluated values of selection elements
473  *   are printed as well.
474  * \param[in] level   Indentation level, starting from zero.
475  */
476 void
477 _gmx_selelem_print_tree(FILE *fp, t_selelem *sel, gmx_bool bValues, int level)
478 {
479     t_selelem *child;
480     int          i;
481
482     fprintf(fp, "%*c %s %s", level*2+1, '*',
483             _gmx_selelem_type_str(sel), _gmx_sel_value_type_str(&sel->v));
484     if (sel->name)
485     {
486         fprintf(fp, " \"%s\"", sel->name);
487     }
488     fprintf(fp, " flg=");
489     if (sel->flags & SEL_FLAGSSET)
490     {
491         fprintf(fp, "s");
492     }
493     if (sel->flags & SEL_SINGLEVAL)
494     {
495         fprintf(fp, "S");
496     }
497     if (sel->flags & SEL_ATOMVAL)
498     {
499         fprintf(fp, "A");
500     }
501     if (sel->flags & SEL_VARNUMVAL)
502     {
503         fprintf(fp, "V");
504     }
505     if (sel->flags & SEL_DYNAMIC)
506     {
507         fprintf(fp, "D");
508     }
509     if (!(sel->flags & SEL_VALFLAGMASK))
510     {
511         fprintf(fp, "0");
512     }
513     if (sel->mempool)
514     {
515         fprintf(fp, "P");
516     }
517     if (sel->type == SEL_CONST)
518     {
519         if (sel->v.type == INT_VALUE)
520         {
521             fprintf(fp, " %d", sel->v.u.i[0]);
522         }
523         else if (sel->v.type == REAL_VALUE)
524         {
525             fprintf(fp, " %f", sel->v.u.r[0]);
526         }
527         else if (sel->v.type == GROUP_VALUE)
528         {
529             gmx_ana_index_t *g = sel->v.u.g;
530             if (!g || g->isize == 0)
531                 g = &sel->u.cgrp;
532             fprintf(fp, " (%d atoms)", g->isize);
533         }
534     }
535     else if (sel->type == SEL_BOOLEAN)
536     {
537         fprintf(fp, " %s", _gmx_selelem_gmx_boolean_type_str(sel));
538     }
539     else if (sel->type == SEL_EXPRESSION
540              && sel->u.expr.method->name == sm_compare.name)
541     {
542         _gmx_selelem_print_compare_info(fp, sel->u.expr.mdata);
543     }
544     if (sel->evaluate)
545     {
546         fprintf(fp, " eval=");
547         _gmx_sel_print_evalfunc_name(fp, sel->evaluate);
548     }
549     if (sel->refcount > 1)
550     {
551         fprintf(fp, " refc=%d", sel->refcount);
552     }
553     if (!(sel->flags & SEL_ALLOCVAL))
554     {
555         fprintf(fp, " (ext. output)");
556     }
557     fprintf(fp, "\n");
558
559     if ((sel->type == SEL_CONST && sel->v.type == GROUP_VALUE) || sel->type == SEL_ROOT)
560     {
561         gmx_ana_index_t *g = sel->v.u.g;
562         if (!g || g->isize == 0 || sel->evaluate != NULL)
563         {
564             g = &sel->u.cgrp;
565         }
566         if (g->isize < 0)
567         {
568             fprintf(fp, "%*c group: (null)\n", level*2+1, ' ');
569         }
570         else if (g->isize > 0)
571         {
572             fprintf(fp, "%*c group:", level*2+1, ' ');
573             if (g->isize <= 20)
574             {
575                 for (i = 0; i < g->isize; ++i)
576                 {
577                     fprintf(fp, " %d", g->index[i] + 1);
578                 }
579             }
580             else
581             {
582                 fprintf(fp, " %d atoms", g->isize);
583             }
584             fprintf(fp, "\n");
585         }
586     }
587     else if (sel->type == SEL_EXPRESSION)
588     {
589         if (sel->u.expr.pc)
590         {
591             fprintf(fp, "%*c COM", level*2+3, '*');
592             fprintf(fp, "\n");
593         }
594     }
595
596     if (sel->cdata)
597     {
598         _gmx_selelem_print_compiler_info(fp, sel, level);
599     }
600
601     if (bValues && sel->type != SEL_CONST && sel->type != SEL_ROOT && sel->v.u.ptr)
602     {
603         fprintf(fp, "%*c value: ", level*2+1, ' ');
604         switch (sel->v.type)
605         {
606             case POS_VALUE:
607                 /* In normal use, the pointer should never be NULL, but it's
608                  * useful to have the check for debugging to avoid accidental
609                  * segfaults when printing the selection tree. */
610                 if (sel->v.u.p->x)
611                 {
612                     fprintf(fp, "(%f, %f, %f)",
613                             sel->v.u.p->x[0][XX], sel->v.u.p->x[0][YY],
614                             sel->v.u.p->x[0][ZZ]);
615                 }
616                 else
617                 {
618                     fprintf(fp, "(null)");
619                 }
620                 break;
621             case GROUP_VALUE:
622                 fprintf(fp, "%d atoms", sel->v.u.g->isize);
623                 if (sel->v.u.g->isize < 20)
624                 {
625                     if (sel->v.u.g->isize > 0)
626                     {
627                         fprintf(fp, ":");
628                     }
629                     for (i = 0; i < sel->v.u.g->isize; ++i)
630                     {
631                         fprintf(fp, " %d", sel->v.u.g->index[i] + 1);
632                     }
633                 }
634                 break;
635             default:
636                 fprintf(fp, "???");
637                 break;
638         }
639         fprintf(fp, "\n");
640     }
641
642     /* Print the subexpressions with one more level of indentation */
643     child = sel->child;
644     while (child)
645     {
646         if (!(sel->type == SEL_SUBEXPRREF && child->type == SEL_SUBEXPR))
647         {
648             _gmx_selelem_print_tree(fp, child, bValues, level+1);
649         }
650         child = child->next;
651     }
652 }
653
654 /*!
655  * \param[in] root Root of the subtree to query.
656  * \returns TRUE if \p root or any any of its elements require topology
657  *   information, FALSE otherwise.
658  */
659 gmx_bool
660 _gmx_selelem_requires_top(t_selelem *root)
661 {
662     t_selelem *child;
663
664     if (root->type == SEL_EXPRESSION || root->type == SEL_MODIFIER)
665     {
666         if (root->u.expr.method && (root->u.expr.method->flags & SMETH_REQTOP))
667         {
668             return TRUE;
669         }
670         if (root->u.expr.pc && gmx_ana_poscalc_requires_top(root->u.expr.pc))
671         {
672             return TRUE;
673         }
674     }
675     child = root->child;
676     while (child)
677     {
678         if (_gmx_selelem_requires_top(child))
679         {
680             return TRUE;
681         }
682         child = child->next;
683     }
684     return FALSE;
685 }