1 /* 2 * This file is part of the GROMACS molecular simulation package. 3 * 4 * Copyright (c) 2009-2017, The GROMACS development team. 5 * Copyright (c) 2019, by the GROMACS development team, led by 6 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl, 7 * and including many others, as listed in the AUTHORS file in the 8 * top-level source directory and at http://www.gromacs.org. 9 * 10 * GROMACS is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public License 12 * as published by the Free Software Foundation; either version 2.1 13 * of the License, or (at your option) any later version. 14 * 15 * GROMACS is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with GROMACS; if not, see 22 * http://www.gnu.org/licenses, or write to the Free Software Foundation, 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 * 25 * If you want to redistribute modifications to GROMACS, please 26 * consider that scientific software is very special. Version 27 * control is crucial - bugs must be traceable. We will be happy to 28 * consider code for inclusion in the official distribution, but 29 * derived work must not be called official GROMACS. Details are found 30 * in the README & COPYING files - if they are missing, get the 31 * official version at http://www.gromacs.org. 32 * 33 * To help us fund GROMACS development, we humbly ask that you cite 34 * the research papers on the package. Check out http://www.gromacs.org. 35 */ 36 /*! \internal \file 37 * \brief 38 * Declares gmx::SelectionTreeElement and related things. 39 * 40 * The selection element trees constructed by the parser and the compiler 41 * are described on the respective pages: 42 * \ref page_module_selection_parser and \ref page_module_selection_compiler. 43 * 44 * This is an implementation header: there should be no need to use it outside 45 * this directory. 46 * 47 * \author Teemu Murtola <teemu.murtola@gmail.com> 48 * \ingroup module_selection 49 */ 50 #ifndef GMX_SELECTION_SELELEM_H 51 #define GMX_SELECTION_SELELEM_H 52 53 #include <memory> 54 #include <string> 55 56 #include "gromacs/selection/indexutil.h" 57 #include "gromacs/utility/classhelpers.h" 58 #include "gromacs/utility/real.h" 59 60 #include "selvalue.h" 61 62 struct gmx_ana_poscalc_t; 63 struct gmx_ana_selparam_t; 64 struct gmx_ana_selmethod_t; 65 66 struct gmx_sel_evaluate_t; 67 struct gmx_sel_mempool_t; 68 69 struct t_compiler_data; 70 71 namespace gmx 72 { 73 class SelectionTreeElement; 74 struct SelectionTopologyProperties; 75 76 //! Smart pointer type for selection tree element pointers. 77 typedef std::shared_ptr<SelectionTreeElement> SelectionTreeElementPointer; 78 } // namespace gmx 79 80 /********************************************************************/ 81 /*! \name Enumerations for expression types 82 ********************************************************************/ 83 //!\{ 84 85 /** Defines the type of a gmx::SelectionTreeElement object. */ 86 typedef enum 87 { 88 /** Constant-valued expression. */ 89 SEL_CONST, 90 /** Method expression that requires evaluation. */ 91 SEL_EXPRESSION, 92 /** Boolean expression. */ 93 SEL_BOOLEAN, 94 /** Arithmetic expression. */ 95 SEL_ARITHMETIC, 96 /** Root node of the evaluation tree. */ 97 SEL_ROOT, 98 /** Subexpression that may be referenced several times. */ 99 SEL_SUBEXPR, 100 /** Reference to a subexpression. */ 101 SEL_SUBEXPRREF, 102 /** Unresolved reference to an external group. */ 103 SEL_GROUPREF, 104 /** Post-processing of selection value. */ 105 SEL_MODIFIER 106 } e_selelem_t; 107 108 /** Defines the boolean operation of gmx::SelectionTreeElement objects with type \ref SEL_BOOLEAN. */ 109 typedef enum 110 { 111 BOOL_NOT, /**< Not */ 112 BOOL_AND, /**< And */ 113 BOOL_OR, /**< Or */ 114 BOOL_XOR /**< Xor (not implemented). */ 115 } e_boolean_t; 116 117 /** Defines the arithmetic operation of gmx::SelectionTreeElement objects with type \ref SEL_ARITHMETIC. */ 118 typedef enum 119 { 120 ARITH_PLUS, /**< Addition (`+`) */ 121 ARITH_MINUS, /**< Subtraction (`-`) */ 122 ARITH_NEG, /**< Unary `-` */ 123 ARITH_MULT, /**< Multiplication (`*`) */ 124 ARITH_DIV, /**< Division (`/`) */ 125 ARITH_EXP /**< Power (`^`) */ 126 } e_arithmetic_t; 127 128 /** Returns a string representation of the type of a gmx::SelectionTreeElement. */ 129 extern const char* _gmx_selelem_type_str(const gmx::SelectionTreeElement& sel); 130 /** Returns a string representation of the boolean type of a \ref SEL_BOOLEAN gmx::SelectionTreeElement. */ 131 extern const char* _gmx_selelem_boolean_type_str(const gmx::SelectionTreeElement& sel); 132 /** Returns a string representation of the type of a \c gmx_ana_selvalue_t. */ 133 extern const char* _gmx_sel_value_type_str(const gmx_ana_selvalue_t* val); 134 135 //!\} 136 137 138 /********************************************************************/ 139 /*! \name Selection expression flags 140 * \anchor selelem_flags 141 ********************************************************************/ 142 //!\{ 143 /*! \brief 144 * Selection value flags are set. 145 * 146 * If this flag is set, the flags covered by \ref SEL_VALFLAGMASK 147 * have been set properly for the element. 148 */ 149 #define SEL_FLAGSSET 1 150 /*! \brief 151 * The element evaluates to a single value. 152 * 153 * This flag is always set for \ref GROUP_VALUE elements. 154 */ 155 #define SEL_SINGLEVAL 2 156 /*! \brief 157 * The element evaluates to one value for each input atom. 158 */ 159 #define SEL_ATOMVAL 4 160 /*! \brief 161 * The element evaluates to an arbitrary number of values. 162 */ 163 #define SEL_VARNUMVAL 8 164 /*! \brief 165 * The element (or one of its children) is dynamic. 166 */ 167 #define SEL_DYNAMIC 16 168 /*! \brief 169 * The element may contain atom indices in an unsorted order. 170 */ 171 #define SEL_UNSORTED 32 172 /*! \brief 173 * Mask that covers the flags that describe the number of values. 174 */ 175 #define SEL_VALTYPEMASK (SEL_SINGLEVAL | SEL_ATOMVAL | SEL_VARNUMVAL) 176 /*! \brief 177 * Mask that covers the flags that describe the value type. 178 */ 179 #define SEL_VALFLAGMASK (SEL_FLAGSSET | SEL_VALTYPEMASK | SEL_DYNAMIC) 180 /*! \brief 181 * Data has been allocated for the \p v.u union. 182 * 183 * If not set, the \p v.u.ptr points to data allocated externally. 184 * This is the case if the value of the element is used as a parameter 185 * for a selection method or if the element evaluates the final value of 186 * a selection. 187 * 188 * Even if the flag is set, \p v.u.ptr can be NULL during initialization. 189 * 190 * \todo 191 * This flag overlaps with the function of \p v.nalloc field, and could 192 * probably be removed, making memory management simpler. Currently, the 193 * \p v.nalloc field is not kept up-to-date in all cases when this flag 194 * is changed and is used in places where this flag is not, so this would 195 * require a careful investigation of the selection code. 196 */ 197 #define SEL_ALLOCVAL (1 << 8) 198 /*! \brief 199 * Data has been allocated for the group/position structure. 200 * 201 * If not set, the memory allocated for fields in \p v.u.g or \p v.u.p is 202 * managed externally. 203 * 204 * This field has no effect if the value type is not \ref GROUP_VALUE or 205 * \ref POS_VALUE, but should not be set. 206 */ 207 #define SEL_ALLOCDATA (1 << 9) 208 /*! \brief 209 * \p method->init_frame should be called for the frame. 210 */ 211 #define SEL_INITFRAME (1 << 10) 212 /*! \brief 213 * Parameter has been evaluated for the current frame. 214 * 215 * This flag is set for children of \ref SEL_EXPRESSION elements (which 216 * describe method parameters) after the element has been evaluated for the 217 * current frame. 218 * It is not set for \ref SEL_ATOMVAL elements, because they may need to 219 * be evaluated multiple times. 220 */ 221 #define SEL_EVALFRAME (1 << 11) 222 /*! \brief 223 * \p method->init has been called. 224 */ 225 #define SEL_METHODINIT (1 << 12) 226 /*! \brief 227 * \p method->outinit has been called. 228 * 229 * This flag is also used for \ref SEL_SUBEXPRREF elements. 230 */ 231 #define SEL_OUTINIT (1 << 13) 232 //!\} 233 234 235 namespace gmx 236 { 237 238 class ExceptionInitializer; 239 240 //! \cond internal 241 /*! \brief 242 * Function pointer for evaluating a gmx::SelectionTreeElement. 243 */ 244 typedef void (*sel_evalfunc)(struct gmx_sel_evaluate_t* data, 245 const SelectionTreeElementPointer& sel, 246 gmx_ana_index_t* g); 247 //! \endcond 248 249 /*! \internal 250 * \brief 251 * Stores the location of a selection element in the selection text. 252 * 253 * The location is stored as a range in the pretty-printed selection text 254 * (where whitespace has been sanitized), and can be used to extract that text 255 * for error messages and other diagnostic purposes. 256 * During parsing, the extraction is done with _gmx_sel_lexer_get_text(). 257 * 258 * This needs to be a plain C struct for Bison to properly deal with it. 259 */ 260 struct SelectionLocation 261 { 262 //! Returns an empty location. createEmptySelectionLocation263 static SelectionLocation createEmpty() 264 { 265 SelectionLocation empty = { 0, 0 }; 266 return empty; 267 } 268 269 //! Start index of the string where this element has been parsed from. 270 int startIndex; 271 //! End index of the string where this element has been parsed from. 272 int endIndex; 273 }; 274 275 /*! \internal \brief 276 * Represents an element of a selection expression. 277 */ 278 class SelectionTreeElement 279 { 280 public: 281 /*! \brief 282 * Allocates memory and performs common initialization. 283 * 284 * \param[in] type Type of selection element to create. 285 * \param[in] location Location of the element. 286 * 287 * \a type is set to \p type, 288 * \a v::type is set to \ref GROUP_VALUE for boolean and comparison 289 * expressions and \ref NO_VALUE for others, and 290 * \ref SEL_ALLOCVAL is set for non-root elements (\ref SEL_ALLOCDATA 291 * is also set for \ref SEL_BOOLEAN elements). 292 * All the pointers are set to NULL. 293 */ 294 SelectionTreeElement(e_selelem_t type, const SelectionLocation& location); 295 ~SelectionTreeElement(); 296 297 //! Frees the memory allocated for the \a v union. 298 void freeValues(); 299 //! Frees the memory allocated for the \a u union. 300 void freeExpressionData(); 301 /* In compiler.cpp */ 302 /*! \brief 303 * Frees the memory allocated for the selection compiler. 304 * 305 * This function only frees the data for the given selection, not its 306 * children. It is safe to call the function when compiler data has 307 * not been allocated or has already been freed; in such a case, 308 * nothing is done. 309 */ 310 void freeCompilerData(); 311 312 /*! \brief 313 * Reserves memory for value from a memory pool. 314 * 315 * \param[in] count Number of values to reserve memory for. 316 * 317 * Reserves memory for the values of this element from the \a mempool 318 * memory pool. 319 * If no memory pool is set, nothing is done. 320 */ 321 void mempoolReserve(int count); 322 /*! \brief 323 * Releases memory pool used for value. 324 * 325 * Releases the memory allocated for the values of this element from the 326 * \a mempool memory pool. 327 * If no memory pool is set, nothing is done. 328 */ 329 void mempoolRelease(); 330 331 //! Returns the name of the element. name()332 const std::string& name() const { return name_; } 333 //! Returns the location of the element. location()334 const SelectionLocation& location() const { return location_; } 335 336 /*! \brief 337 * Sets the name of the element. 338 * 339 * \param[in] name Name to set (can be NULL). 340 * \throws std::bad_alloc if out of memory. 341 */ setName(const char * name)342 void setName(const char* name) { name_ = (name != nullptr ? name : ""); } 343 //! \copydoc setName(const char *) setName(const std::string & name)344 void setName(const std::string& name) { name_ = name; } 345 /*! \brief 346 * Sets the name of a root element if it is missing. 347 * 348 * \param[in] selectionText Full selection text to use as a fallback. 349 * \throws std::bad_alloc if out of memory. 350 * 351 * If index groups have not yet been set and the selection is a result 352 * of a group reference, the name may still be empty after this call. 353 * 354 * Strong exception safety guarantee. 355 */ 356 void fillNameIfMissing(const char* selectionText); 357 358 /*! \brief 359 * Returns which topology properties the selection element subtree requires 360 * for evaluation. 361 * 362 * \returns List of topology properties required for evaluation. 363 */ 364 SelectionTopologyProperties requiredTopologyProperties() const; 365 /*! \brief 366 * Checks that this element and its children do not contain unsupported 367 * elements with unsorted atoms. 368 * 369 * \param[in] bUnsortedAllowed Whether this element's parents allow it 370 * to have unsorted atoms. 371 * \param errors Object for reporting any error messages. 372 * \throws std::bad_alloc if out of memory. 373 * 374 * Errors are reported as nested exceptions in \p errors. 375 */ 376 void checkUnsortedAtoms(bool bUnsortedAllowed, ExceptionInitializer* errors) const; 377 /*! \brief 378 * Checks whether the element or its children have unresolved index 379 * group references. 380 * 381 * Does not throw. 382 */ 383 bool requiresIndexGroups() const; 384 /*! \brief 385 * Resolves an unresolved reference to an index group. 386 * 387 * \param[in] grps Index groups to use to resolve the reference. 388 * \param[in] natoms Maximum number of atoms the selections can evaluate to 389 * (zero if the topology/atom count is not set yet). 390 * \throws std::bad_alloc if out of memory. 391 * \throws InconsistentInputError if the reference cannot be 392 * resolved. 393 */ 394 void resolveIndexGroupReference(gmx_ana_indexgrps_t* grps, int natoms); 395 /*! \brief 396 * Checks that an index group has valid atom indices. 397 * 398 * \param[in] natoms Maximum number of atoms the selections can evaluate to. 399 * \throws std::bad_alloc if out of memory. 400 * \throws InconsistentInputError if there are invalid atom indices. 401 */ 402 void checkIndexGroup(int natoms); 403 404 //! Type of the element. 405 e_selelem_t type; 406 /*! \brief 407 * Value storage of the element. 408 * 409 * This field contains the evaluated value of the element, as well as 410 * the output value type. 411 */ 412 gmx_ana_selvalue_t v; 413 /*! \brief 414 * Evaluation function for the element. 415 * 416 * Can be either NULL (if the expression is a constant and does not 417 * require evaluation) or point to one of the functions defined in 418 * evaluate.h. 419 */ 420 sel_evalfunc evaluate; 421 /*! \brief 422 * Information flags about the element. 423 * 424 * Allowed flags are listed here: 425 * \ref selelem_flags "flags for gmx::SelectionTreeElement". 426 */ 427 int flags; 428 //! Data required by the evaluation function. 429 union { 430 /*! \brief Index group data for several element types. 431 * 432 * - \ref SEL_CONST : if the value type is \ref GROUP_VALUE, 433 * this field holds the unprocessed group value. 434 * - \ref SEL_ROOT : holds the group value for which the 435 * selection subtree should be evaluated. 436 * - \ref SEL_SUBEXPR : holds the group for which the subexpression 437 * has been evaluated. 438 */ 439 gmx_ana_index_t cgrp; 440 //! Data for \ref SEL_EXPRESSION and \ref SEL_MODIFIER elements. 441 struct 442 { 443 //! Pointer the method used in this expression. 444 struct gmx_ana_selmethod_t* method; 445 //! Pointer to the data allocated by the method's \p init_data (see sel_datafunc()). 446 void* mdata; 447 //! Pointer to the position data passed to the method. 448 struct gmx_ana_pos_t* pos; 449 //! Pointer to the evaluation data for \p pos. 450 struct gmx_ana_poscalc_t* pc; 451 } expr; 452 //! Operation type for \ref SEL_BOOLEAN elements. 453 e_boolean_t boolt; 454 //! Operation type for \ref SEL_ARITHMETIC elements. 455 struct 456 { 457 //! Operation type. 458 e_arithmetic_t type; 459 //! String representation. 460 char* opstr; 461 } arith; 462 //! Associated selection parameter for \ref SEL_SUBEXPRREF elements. 463 struct gmx_ana_selparam_t* param; 464 //! The string/number used to reference the group. 465 struct 466 { 467 //! Name of the referenced external group. 468 char* name; 469 //! If \a name is NULL, the index number of the referenced group. 470 int id; 471 } gref; 472 } u; 473 //! Memory pool to use for values, or NULL if standard memory handling. 474 struct gmx_sel_mempool_t* mempool; 475 //! Internal data for the selection compiler. 476 t_compiler_data* cdata; 477 478 /*! \brief The first child element. 479 * 480 * Other children can be accessed through the \p next field of \p child. 481 */ 482 SelectionTreeElementPointer child; 483 //! The next sibling element. 484 SelectionTreeElementPointer next; 485 486 private: 487 /*! \brief 488 * Name of the element. 489 * 490 * This field is only used for diagnostic purposes. 491 */ 492 std::string name_; 493 /*! \brief 494 * Location of the element in the selection text. 495 * 496 * This field is only used for diagnostic purposes (including error 497 * messages). 498 */ 499 SelectionLocation location_; 500 501 GMX_DISALLOW_COPY_AND_ASSIGN(SelectionTreeElement); 502 }; 503 504 } // namespace gmx 505 506 /********************************************************************/ 507 /*! \name Selection expression functions 508 */ 509 //!\{ 510 511 /* In evaluate.c */ 512 /** Writes out a human-readable name for an evaluation function. */ 513 void _gmx_sel_print_evalfunc_name(FILE* fp, gmx::sel_evalfunc evalfunc); 514 515 /** Sets the value type of a gmx::SelectionTreeElement. */ 516 void _gmx_selelem_set_vtype(const gmx::SelectionTreeElementPointer& sel, e_selvalue_t vtype); 517 518 /*! \brief 519 * Frees the memory allocated for a selection method parameter. 520 * 521 * \param[in] param Parameter to free. 522 */ 523 void _gmx_selelem_free_param(struct gmx_ana_selparam_t* param); 524 /*! \brief 525 * Frees the memory allocated for a selection method. 526 * 527 * \param[in] method Method to free. 528 * \param[in] mdata Method data to free. 529 */ 530 void _gmx_selelem_free_method(struct gmx_ana_selmethod_t* method, void* mdata); 531 532 /** Prints a human-readable version of a selection element subtree. */ 533 void _gmx_selelem_print_tree(FILE* fp, const gmx::SelectionTreeElement& sel, bool bValues, int level); 534 /* In compiler.c */ 535 /** Prints a human-readable version of the internal compiler data structure. */ 536 void _gmx_selelem_print_compiler_info(FILE* fp, const gmx::SelectionTreeElement& sel, int level); 537 538 /* In sm_insolidangle.c */ 539 /** Returns true if the covered fraction of the selection can be calculated. */ 540 bool _gmx_selelem_can_estimate_cover(const gmx::SelectionTreeElement& sel); 541 /** Returns the covered fraction of the selection for the current frame. */ 542 real _gmx_selelem_estimate_coverfrac(const gmx::SelectionTreeElement& sel); 543 544 //!\} 545 546 #endif 547