Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / selection / selmethod.cpp
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
33  * Implements functions in selmethod.h.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \ingroup module_selection
37  */
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #include <ctype.h>
43 #include <stdarg.h>
44
45 #include <macros.h>
46 #include <string2.h>
47
48 #include "gromacs/selection/selmethod.h"
49
50 #include "symrec.h"
51
52 /*
53  * These global variables cannot be const because gmx_ana_selmethod_register()
54  * modifies them to set some defaults. This is a small price to pay for the
55  * convenience of not having to remember exactly how the selection compiler
56  * expects the structures to be filled, and even more so if the expectations
57  * change. Also, even if the gmx_ana_selmethod_t structures were made const,
58  * the parameters could not be without typecasts somewhere, because the param
59  * field in gmx_ana_selmethod_t cannot be declared const.
60  *
61  * Even though the variables may be modified, this should be thread-safe as
62  * modifications are done only in gmx_ana_selmethod_register(), and it should
63  * work even if called more than once for the same structure, and even if
64  * called concurrently from multiple threads (as long as the selection
65  * collection is not the same).
66  *
67  * All of these problems should go away if/when the selection methods are
68  * implemented as C++ classes.
69  */
70
71 /* From sm_com.c */
72 extern gmx_ana_selmethod_t sm_cog;
73 extern gmx_ana_selmethod_t sm_com;
74 /* From sm_simple.c */
75 extern gmx_ana_selmethod_t sm_all;
76 extern gmx_ana_selmethod_t sm_none;
77 extern gmx_ana_selmethod_t sm_atomnr;
78 extern gmx_ana_selmethod_t sm_resnr;
79 extern gmx_ana_selmethod_t sm_resindex;
80 extern gmx_ana_selmethod_t sm_molindex;
81 extern gmx_ana_selmethod_t sm_atomname;
82 extern gmx_ana_selmethod_t sm_atomtype;
83 extern gmx_ana_selmethod_t sm_resname;
84 extern gmx_ana_selmethod_t sm_insertcode;
85 extern gmx_ana_selmethod_t sm_chain;
86 extern gmx_ana_selmethod_t sm_mass;
87 extern gmx_ana_selmethod_t sm_charge;
88 extern gmx_ana_selmethod_t sm_altloc;
89 extern gmx_ana_selmethod_t sm_occupancy;
90 extern gmx_ana_selmethod_t sm_betafactor;
91 extern gmx_ana_selmethod_t sm_x;
92 extern gmx_ana_selmethod_t sm_y;
93 extern gmx_ana_selmethod_t sm_z;
94 /* From sm_distance.c */
95 extern gmx_ana_selmethod_t sm_distance;
96 extern gmx_ana_selmethod_t sm_mindistance;
97 extern gmx_ana_selmethod_t sm_within;
98 /* From sm_insolidangle.c */
99 extern gmx_ana_selmethod_t sm_insolidangle;
100 /* From sm_same.c */
101 extern gmx_ana_selmethod_t sm_same;
102
103 /* From sm_merge.c */
104 extern gmx_ana_selmethod_t sm_merge;
105 extern gmx_ana_selmethod_t sm_plus;
106 /* From sm_permute.c */
107 extern gmx_ana_selmethod_t sm_permute;
108
109 /*! \internal \brief
110  * Helper structure for defining selection methods.
111  */
112 typedef struct {
113     /*! \brief
114      * Name to register the method under.
115      *
116      * If NULL, use the actual name of the method.
117      * This field is used for defining synonyms.
118      */
119     const char            *name;
120     /** Method data structure to register. */
121     gmx_ana_selmethod_t   *method;
122 } t_register_method;
123
124 /** Array of selection methods defined in the library. */
125 static const t_register_method smtable_def[] = {
126     {NULL,         &sm_cog},
127     {NULL,         &sm_com},
128
129     {NULL,         &sm_all},
130     {NULL,         &sm_none},
131     {NULL,         &sm_atomnr},
132     {NULL,         &sm_resnr},
133     {"resid",      &sm_resnr},
134     {NULL,         &sm_resindex},
135     {"residue",    &sm_resindex},
136     {NULL,         &sm_molindex},
137     {"mol",        &sm_molindex},
138     {"molecule",   &sm_molindex},
139     {NULL,         &sm_atomname},
140     {NULL,         &sm_atomtype},
141     {NULL,         &sm_resname},
142     {NULL,         &sm_insertcode},
143     {NULL,         &sm_chain},
144     {NULL,         &sm_mass},
145     {NULL,         &sm_charge},
146     {NULL,         &sm_altloc},
147     {NULL,         &sm_occupancy},
148     {NULL,         &sm_betafactor},
149     {NULL,         &sm_x},
150     {NULL,         &sm_y},
151     {NULL,         &sm_z},
152
153     {NULL,         &sm_distance},
154     {NULL,         &sm_mindistance},
155     {NULL,         &sm_within},
156     {NULL,         &sm_insolidangle},
157     {NULL,         &sm_same},
158
159     {NULL,         &sm_merge},
160     {NULL,         &sm_plus},
161     {NULL,         &sm_permute},
162 };
163
164 /*! \brief
165  * Convenience function for reporting errors found in selection methods.
166  */
167 static void
168 report_error(FILE *fp, const char *name, const char *fmt, ...)
169 {
170     va_list ap;
171     va_start(ap, fmt);
172     if (fp)
173     {
174         fprintf(fp, "selection method '%s': ", name);
175         vfprintf(fp, fmt, ap);
176         fprintf(fp, "\n");
177     }
178     va_end(ap);
179 }
180
181 /*! \brief
182  * Convenience function for reporting errors found in selection method parameters.
183  */
184 static void
185 report_param_error(FILE *fp, const char *mname, const char *pname,
186                    const char *fmt, ...)
187 {
188     va_list ap;
189     va_start(ap, fmt);
190     if (fp)
191     {
192         fprintf(fp, "selection method '%s': parameter '%s': ", mname, pname);
193         vfprintf(fp, fmt, ap);
194         fprintf(fp, "\n");
195     }
196     va_end(ap);
197 }
198
199 /*! \brief
200  * Checks the validity of parameters.
201  *
202  * \param[in]     fp      File handle to use for diagnostic messages
203  *   (can be NULL).
204  * \param[in]     name    Name of the method (used for error messages).
205  * \param[in]     nparams Number of parameters in \p param.
206  * \param[in,out] param   Parameter array
207  *   (only the \c flags field of boolean parameters may be modified).
208  * \param[in]     symtab  Symbol table (used for checking overlaps).
209  * \returns       true if there are no problems with the parameters,
210  *   false otherwise.
211  *
212  * This function performs some checks common to both check_method() and
213  * check_modifier().
214  * The purpose of these checks is to ensure that the selection parser does not
215  * need to check for the validity of the parameters at each turn, and to
216  * report programming errors as early as possible.
217  * If you remove a check, make sure that the parameter parser can handle the
218  * resulting parameters.
219  */
220 static bool
221 check_params(FILE *fp, const char *name, int nparams, gmx_ana_selparam_t param[],
222              gmx_sel_symtab_t *symtab)
223 {
224     bool              bOk = true;
225     gmx_sel_symrec_t *sym;
226     int               i, j;
227
228     if (nparams > 0 && !param)
229     {
230         report_error(fp, name, "error: missing parameter data");
231         bOk = false;
232         return false;
233     }
234     if (nparams == 0 && param)
235     {
236         report_error(fp, name, "warning: parameter data unused because nparams=0");
237     }
238     /* Check each parameter */
239     for (i = 0; i < nparams; ++i)
240     {
241         /* Check that there is at most one NULL name, in the beginning */
242         if (param[i].name == NULL && i > 0)
243         {
244             report_error(fp, name, "error: NULL parameter should be the first one");
245             bOk = false;
246             continue;
247         }
248         /* Check for duplicates */
249         for (j = 0; j < i; ++j)
250         {
251             if (param[j].name == NULL)
252             {
253                 continue;
254             }
255             if (!gmx_strcasecmp(param[i].name, param[j].name))
256             {
257                 report_error(fp, name, "error: duplicate parameter name '%s'", param[i].name);
258                 bOk = false;
259                 break;
260             }
261         }
262         /* Check flags */
263         if (param[i].flags & SPAR_SET)
264         {
265             report_param_error(fp, name, param[i].name, "warning: flag SPAR_SET is set");
266             param[i].flags &= ~SPAR_SET;
267         }
268         if (param[i].flags & SPAR_RANGES)
269         {
270             if (param[i].val.type != INT_VALUE && param[i].val.type != REAL_VALUE)
271             {
272                 report_param_error(fp, name, param[i].name, "error: SPAR_RANGES cannot be set for a non-numeric parameter");
273                 bOk = false;
274             }
275             if (param[i].flags & SPAR_DYNAMIC)
276             {
277                 report_param_error(fp, name, param[i].name, "warning: SPAR_DYNAMIC does not have effect with SPAR_RANGES");
278                 param[i].flags &= ~SPAR_DYNAMIC;
279             }
280             if (!(param[i].flags & SPAR_VARNUM) && param[i].val.nr != 1)
281             {
282                 report_param_error(fp, name, param[i].name, "error: range should take either one or an arbitrary number of values");
283                 bOk = false;
284             }
285             if (param[i].flags & SPAR_ATOMVAL)
286             {
287                 report_param_error(fp, name, param[i].name, "error: SPAR_RANGES and SPAR_ATOMVAL both set");
288                 bOk = false;
289             }
290         }
291         if ((param[i].flags & SPAR_VARNUM) && (param[i].flags & SPAR_ATOMVAL))
292         {
293             report_param_error(fp, name, param[i].name, "error: SPAR_VARNUM and SPAR_ATOMVAL both set");
294             bOk = false;
295         }
296         if (param[i].flags & SPAR_ENUMVAL)
297         {
298             if (param[i].val.type != STR_VALUE)
299             {
300                 report_param_error(fp, name, param[i].name, "error: SPAR_ENUMVAL can only be set for string parameters");
301                 bOk = false;
302             }
303             if (param[i].val.nr != 1)
304             {
305                 report_param_error(fp, name, param[i].name, "error: SPAR_ENUMVAL parameters should take exactly one value");
306                 bOk = false;
307             }
308             if (param[i].flags & (SPAR_DYNAMIC | SPAR_VARNUM | SPAR_ATOMVAL))
309             {
310                 report_param_error(fp, name, param[i].name, "error: only SPAR_OPTIONAL supported with SPAR_ENUMVAL");
311                 bOk = false;
312             }
313         }
314         /* Check boolean parameters */
315         if (param[i].val.type == NO_VALUE)
316         {
317             if (param[i].val.nr != 0)
318             {
319                 report_param_error(fp, name, param[i].name, "error: number of values should be zero for boolean parameters");
320                 bOk = false;
321             }
322             /* The boolean parameters should always be optional, so set the
323              * flag for convenience. */
324             param[i].flags |= SPAR_OPTIONAL;
325             /* Any other flags should not be specified */
326             if (param[i].flags & ~SPAR_OPTIONAL)
327             {
328                 report_param_error(fp, name, param[i].name, "error: boolean parameter should not have any flags set");
329                 bOk = false;
330             }
331         }
332         /* Check val.nr */
333         if (param[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL))
334         {
335             if (param[i].val.nr != -1)
336             {
337                 report_param_error(fp, name, param[i].name, "warning: val.nr is not -1 although SPAR_VARNUM/SPAR_ATOMVAL is set");
338             }
339             param[i].val.nr = -1;
340         }
341         else if (param[i].val.type != NO_VALUE)
342         {
343             if (param[i].val.nr <= 0)
344             {
345                 report_param_error(fp, name, param[i].name, "error: val.nr <= 0");
346                 bOk = false;
347             }
348         }
349         /* Check that the value pointer is NULL */
350         if (param[i].nvalptr != NULL)
351         {
352             report_param_error(fp, name, param[i].name, "warning: nvalptr is set");
353         }
354         if (param[i].val.u.ptr != NULL && !(param[i].flags & SPAR_ENUMVAL))
355         {
356             report_param_error(fp, name, param[i].name, "warning: value pointer is set");
357         }
358         /* Check that the name contains only valid characters */
359         if (param[i].name == NULL)
360         {
361             continue;
362         }
363         if (!isalpha(param[i].name[0]))
364         {
365             report_param_error(fp, name, param[i].name, "error: name does not begin with a letter");
366             bOk = false;
367             continue;
368         }
369         for (j = 1; param[i].name[j] != 0; ++j)
370         {
371             if (param[i].name[j] != '_' && !isalnum(param[i].name[j]))
372             {
373                 report_param_error(fp, name, param[i].name, "error: name contains non-alphanumeric characters");
374                 bOk = false;
375                 break;
376             }
377         }
378         if (param[i].name[j] != 0)
379         {
380             continue;
381         }
382         /* Check that the name does not conflict with a method */
383         if (_gmx_sel_find_symbol(symtab, param[i].name, true))
384         {
385             report_param_error(fp, name, param[i].name, "error: name conflicts with another method or a keyword");
386             bOk = false;
387         }
388     } /* End of parameter loop */
389     /* Check parameters of existing methods */
390     sym = _gmx_sel_first_symbol(symtab, SYMBOL_METHOD);
391     while (sym)
392     {
393         gmx_ana_selmethod_t *method = _gmx_sel_sym_value_method(sym);
394         gmx_ana_selparam_t  *param =
395             gmx_ana_selmethod_find_param(name, method);
396         if (param)
397         {
398             report_param_error(fp, method->name, param->name, "error: name conflicts with another method or a keyword");
399             bOk = false;
400         }
401         sym = _gmx_sel_next_symbol(sym, SYMBOL_METHOD);
402     }
403     return bOk;
404 }
405
406 /*! \brief
407  * Checks the validity of selection method callback functions.
408  *
409  * \param[in] fp        File handle to use for diagnostic messages
410  *   (can be NULL).
411  * \param[in] method    The method to check.
412  * \returns   true if there are no problems, false otherwise.
413  *
414  * This function performs some checks common to both check_method() and
415  * check_modifier().
416  * This function checks that all the required callbacks are defined, i.e.,
417  * not NULL, to find programming errors.
418  */
419 static bool
420 check_callbacks(FILE *fp, gmx_ana_selmethod_t *method)
421 {
422     bool         bOk = true;
423     bool         bNeedInit;
424     int          i;
425
426     /* Make some checks on init_data and free */
427     if (method->nparams > 0 && !method->init_data)
428     {
429         report_error(fp, method->name, "error: init_data should be provided because the method has parameters");
430         bOk = false;
431     }
432     if (method->free && !method->init_data)
433     {
434         report_error(fp, method->name, "warning: free is not used because of missing init_data");
435     }
436     /* Check presence of outinit for position-valued methods */
437     if (method->type == POS_VALUE && !method->outinit)
438     {
439         report_error(fp, method->name, "error: outinit should be provided because the method has POS_VALUE");
440         bOk = false;
441     }
442     /* Warn of dynamic callbacks in static methods */
443     if (!(method->flags & SMETH_MODIFIER))
444     {
445         if (method->pupdate && !(method->flags & SMETH_DYNAMIC))
446         {
447             report_error(fp, method->name, "warning: pupdate not used because the method is static");
448             method->pupdate = NULL;
449         }
450     }
451     /* Check that there is an evaluation function */
452     if (method->type != NO_VALUE && !method->update && !method->pupdate)
453     {
454         report_error(fp, method->name, "error: evaluation function missing");
455         bOk = false;
456     }
457     /* Loop through the parameters to determine if initialization callbacks
458      * are needed. */
459     bNeedInit = false;
460     for (i = 0; i < method->nparams; ++i)
461     {
462         if (method->param[i].val.type != POS_VALUE
463             && (method->param[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
464         {
465             bNeedInit = true;
466         }
467     }
468     /* Check that the callbacks required by the parameters are present */
469     if (bNeedInit && !method->init)
470     {
471         report_error(fp, method->name, "error: init should be provided");
472         bOk = false;
473     }
474     return bOk;
475 }
476
477 /*!
478  * Checks the validity of a selection method.
479  *
480  * \param[in]     fp     File handle to use for diagnostic messages
481  *   (can be NULL).
482  * \param[in,out] method Method to check.
483  * \param[in]     symtab Symbol table (used for checking overlaps).
484  *
485  * Checks the validity of the given selection method data structure
486  * that does not have \ref SMETH_MODIFIER set.
487  * If you remove a check, please make sure that the selection parser,
488  * compiler, and evaluation functions can deal with the method.
489  */
490 static bool
491 check_method(FILE *fp, gmx_ana_selmethod_t *method, gmx_sel_symtab_t *symtab)
492 {
493     bool         bOk = true;
494
495     /* Check the type */
496     if (method->type == NO_VALUE)
497     {
498         report_error(fp, method->name, "error: no value type specified");
499         bOk = false;
500     }
501     if (method->type == STR_VALUE && method->nparams > 0)
502     {
503         report_error(fp, method->name, "error: evaluates to a string but is not a keyword");
504         bOk = false;
505     }
506     /* Check flags */
507     if (method->type == GROUP_VALUE)
508     {
509         /* Group methods should always have SMETH_SINGLEVAL,
510          * so set it for convenience. */
511         method->flags |= SMETH_SINGLEVAL;
512         /* Check that conflicting flags are not present. */
513         if (method->flags & SMETH_VARNUMVAL)
514         {
515             report_error(fp, method->name, "error: SMETH_VARNUMVAL cannot be set for group-valued methods");
516             bOk = false;
517         }
518     }
519     else
520     {
521         if ((method->flags & SMETH_SINGLEVAL)
522             && (method->flags & SMETH_VARNUMVAL))
523         {
524             report_error(fp, method->name, "error: SMETH_SINGLEVAL and SMETH_VARNUMVAL both set");
525             bOk = false;
526         }
527     }
528     if ((method->flags & SMETH_CHARVAL) && method->type != STR_VALUE)
529     {
530         report_error(fp, method->name, "error: SMETH_CHARVAL can only be specified for STR_VALUE methods");
531         bOk = false;
532     }
533     /* Check the parameters */
534     if (!check_params(fp, method->name, method->nparams, method->param, symtab))
535     {
536         bOk = false;
537     }
538     /* Check the callback pointers */
539     if (!check_callbacks(fp, method))
540     {
541         bOk = false;
542     }
543
544     return bOk;
545 }
546
547 /*!
548  * Checks the validity of a selection modifier method.
549  *
550  * \param[in]     fp     File handle to use for diagnostic messages
551  *   (can be NULL).
552  * \param[in,out] method Method to check.
553  * \param[in]     symtab Symbol table (used for checking overlaps).
554  *
555  * Checks the validity of the given selection method data structure
556  * that has \ref SMETH_MODIFIER set.
557  * If you remove a check, please make sure that the selection parser,
558  * compiler, and evaluation functions can deal with the method.
559  */
560 static bool
561 check_modifier(FILE *fp, gmx_ana_selmethod_t *method, gmx_sel_symtab_t *symtab)
562 {
563     bool         bOk = true;
564
565     /* Check the type */
566     if (method->type != NO_VALUE && method->type != POS_VALUE)
567     {
568         report_error(fp, method->name, "error: modifier should have type POS_VALUE or NO_VALUE");
569         bOk = false;
570     }
571     /* Check flags */
572     if (method->flags & (SMETH_SINGLEVAL | SMETH_VARNUMVAL))
573     {
574         report_error(fp, method->name, "error: modifier should not have SMETH_SINGLEVAL or SMETH_VARNUMVAL set");
575         bOk = false;
576     }
577     /* Check the parameters */
578     /* The first parameter is skipped */
579     if (!check_params(fp, method->name, method->nparams-1, method->param+1, symtab))
580     {
581         bOk = false;
582     }
583     /* Check the callback pointers */
584     if (!check_callbacks(fp, method))
585     {
586         bOk = false;
587     }
588     if (method->update)
589     {
590         report_error(fp, method->name, "error: modifier should not have update");
591         bOk = false;
592     }
593     if (method->type == POS_VALUE && !method->pupdate)
594     {
595         report_error(fp, method->name, "error: evaluation function missing");
596         bOk = false;
597     }
598
599     return bOk;
600 }
601
602 /*!
603  * \param[in,out] symtab Symbol table to register the method to.
604  * \param[in]     name   Name under which the method should be registered.
605  * \param[in]     method Method to register.
606  * \returns       0 on success, EINVAL if there was something wrong with the
607  *   method.
608  *
609  * \p name does not need to match the name of the method, and the same
610  * method can be registered multiple times under different names.
611  * If \p name equals some previously registered name,
612  * an error message is printed and the method is not registered.
613  *
614  * The function also performs some sanity checking on the input method,
615  * and refuses to register it if there are problems.
616  * Some problems only generate warnings.
617  * All problems are described to \p stderr.
618  */
619 int
620 gmx_ana_selmethod_register(gmx_sel_symtab_t *symtab,
621                            const char *name, gmx_ana_selmethod_t *method)
622 {
623     bool bOk;
624
625     /* Check the method */
626     if (method->flags & SMETH_MODIFIER)
627     {
628         bOk = check_modifier(stderr, method, symtab);
629     }
630     else
631     {
632         bOk = check_method(stderr, method, symtab);
633     }
634     /* Try to register the method if everything is ok */
635     if (bOk) 
636     {
637         if (!_gmx_sel_add_method_symbol(symtab, name, method))
638         {
639             bOk = false;
640         }
641     }
642     if (!bOk)
643     {
644         report_error(stderr, name, "warning: not registered");
645         return EINVAL;
646     }
647     return 0;
648 }
649
650 /*!
651  * \param[in,out] symtab Symbol table to register the methods to.
652  * \returns       0 on success, -1 if any of the default methods could not be
653  *   registered.
654  */
655 int
656 gmx_ana_selmethod_register_defaults(gmx_sel_symtab_t *symtab)
657 {
658     size_t i;
659     int  rc;
660     bool bOk;
661
662     bOk = true;
663     for (i = 0; i < asize(smtable_def); ++i)
664     {
665         gmx_ana_selmethod_t *method = smtable_def[i].method;
666
667         if (smtable_def[i].name == NULL)
668         {
669             rc = gmx_ana_selmethod_register(symtab, method->name, method);
670         }
671         else
672         {
673             rc = gmx_ana_selmethod_register(symtab, smtable_def[i].name, method);
674         }
675         if (rc != 0)
676         {
677             bOk = false;
678         }
679     }
680     return bOk ? 0 : -1;
681 }
682
683 /*!
684  * \param[in] name   Name of the parameter to search.
685  * \param[in] method Method to search for the parameter.
686  * \returns   Pointer to the parameter in the
687  *   \ref gmx_ana_selmethod_t::param "method->param" array,
688  *   or NULL if no parameter with name \p name was found.
689  *
690  * This is a simple wrapper for gmx_ana_selparam_find().
691  */
692 gmx_ana_selparam_t *
693 gmx_ana_selmethod_find_param(const char *name, gmx_ana_selmethod_t *method)
694 {
695     return gmx_ana_selparam_find(name, method->nparams, method->param);
696 }