Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / selection / selection.h
index 40c87572d3a6810159407decf87ec79dacd6fba0..55772ffbf50733b756cbed170a330ae7728146a2 100644 (file)
@@ -1,38 +1,42 @@
 /*
+ * This file is part of the GROMACS molecular simulation package.
  *
- *                This source code is part of
+ * Copyright (c) 2009,2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
  *
- *                 G   R   O   M   A   C   S
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
  *
- *          GROningen MAchine for Chemical Simulations
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
  *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
  *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
  *
  * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
+ * the research papers on the package. Check out http://www.gromacs.org.
  */
 /*! \file
  * \brief
  * Declares gmx::Selection and supporting classes.
  *
- * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \inpublicapi
  * \ingroup module_selection
  */
 #include <string>
 #include <vector>
 
-#include "../legacyheaders/typedefs.h"
-
-#include "../utility/arrayref.h"
-#include "../utility/common.h"
-#include "../utility/gmxassert.h"
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selectionenums.h"
+#include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/common.h"
+#include "gromacs/utility/gmxassert.h"
 
-#include "position.h"
-#include "indexutil.h"
-#include "selectionenums.h"
+struct t_topology;
 
 namespace gmx
 {
@@ -58,6 +60,7 @@ namespace gmx
 class SelectionOptionStorage;
 class SelectionTreeElement;
 
+class AnalysisNeighborhoodPositions;
 class Selection;
 class SelectionPosition;
 
@@ -67,7 +70,8 @@ typedef std::vector<Selection> SelectionList;
 namespace internal
 {
 
-/*! \internal \brief
+/*! \internal
+ * \brief
  * Internal data for a single selection.
  *
  * This class is internal to the selection module, but resides in a public
@@ -91,12 +95,19 @@ class SelectionData
         SelectionData(SelectionTreeElement *elem, const char *selstr);
         ~SelectionData();
 
+        //! Returns the name for this selection.
+        const char *name() const { return name_.c_str(); }
         //! Returns the string that was parsed to produce this selection.
         const char *selectionText() const { return selectionText_.c_str(); }
         //! Returns true if the size of the selection (posCount()) is dynamic.
         bool isDynamic() const { return bDynamic_; }
+        //! Returns the type of positions in the selection.
+        e_index_t type() const { return rawPositions_.m.type; }
+        //! Returns true if the selection only contains positions with a single atom each.
+        bool hasOnlyAtoms() const { return type() == INDEX_ATOM; }
+
         //! Number of positions in the selection.
-        int posCount() const { return rawPositions_.nr; }
+        int posCount() const { return rawPositions_.count(); }
         //! Returns the root of the evaluation tree for this selection.
         SelectionTreeElement &rootElement() { return rootElement_; }
 
@@ -111,15 +122,27 @@ class SelectionData
         //! \copydoc Selection::initCoveredFraction()
         bool initCoveredFraction(e_coverfrac_t type);
 
+        /*! \brief
+         * Updates the name of the selection if missing.
+         *
+         * \throws    std::bad_alloc if out of memory.
+         *
+         * If selections get their value from a group reference that cannot be
+         * resolved during parsing, the name is final only after group
+         * references have been resolved.
+         *
+         * This function is called by SelectionCollection::setIndexGroups().
+         */
+        void refreshName();
         /*! \brief
          * Computes total masses and charges for all selection positions.
          *
          * \param[in] top   Topology information.
          * \throws    std::bad_alloc if out of memory.
          *
-         * Computed values are cached, and need to be updated for dynamic
-         * selections with refreshMassesAndCharges() after the selection has
-         * been evaluated.  This is done by SelectionEvaluator.
+         * For dynamic selections, the values need to be updated after each
+         * evaluation with refreshMassesAndCharges().
+         * This is done by SelectionEvaluator.
          *
          * This function is called by SelectionCompiler.
          *
@@ -130,9 +153,11 @@ class SelectionData
          * Updates masses and charges after dynamic selection has been
          * evaluated.
          *
+         * \param[in] top   Topology information.
+         *
          * Called by SelectionEvaluator.
          */
-        void refreshMassesAndCharges();
+        void refreshMassesAndCharges(const t_topology *top);
         /*! \brief
          * Updates the covered fraction after a selection has been evaluated.
          *
@@ -152,57 +177,38 @@ class SelectionData
         /*! \brief
          * Restores position information to state it was in after compilation.
          *
+         * \param[in] top   Topology information.
+         *
          * Depends on SelectionCompiler storing the original atoms in the
          * \a rootElement_ object.
          * Called by SelectionEvaluator::evaluateFinal().
          */
-        void restoreOriginalPositions();
+        void restoreOriginalPositions(const t_topology *top);
 
     private:
-        /*! \brief
-         * Additional information about positions.
-         *
-         * This structure contains information about positions in the
-         * selection that is not stored in ::gmx_ana_pos_t.
-         *
-         * Methods in this class do not throw.
-         */
-        struct PositionInfo
-        {
-            //! Construct position information with unit mass and no charge.
-            PositionInfo() : mass(1.0), charge(0.0) {}
-            //! Construct position information with the given information.
-            PositionInfo(real mass, real charge) : mass(mass), charge(charge) {}
-
-            //! Total mass of atoms that make up the position.
-            real                mass;
-            //! Total charge of atoms that make up the position.
-            real                charge;
-        };
-
         //! Name of the selection.
-        std::string             name_;
+        std::string               name_;
         //! The actual selection string.
-        std::string             selectionText_;
+        std::string               selectionText_;
         //! Low-level representation of selected positions.
-        gmx_ana_pos_t           rawPositions_;
-        //! Information associated with the current positions.
-        std::vector<PositionInfo> posInfo_;
-        //! Information for all possible positions.
-        std::vector<PositionInfo> originalPosInfo_;
-        SelectionFlags          flags_;
+        gmx_ana_pos_t             rawPositions_;
+        //! Total masses for the current positions.
+        std::vector<real>         posMass_;
+        //! Total charges for the current positions.
+        std::vector<real>         posCharge_;
+        SelectionFlags            flags_;
         //! Root of the selection evaluation tree.
-        SelectionTreeElement   &rootElement_;
+        SelectionTreeElement     &rootElement_;
         //! Type of the covered fraction.
-        e_coverfrac_t           coveredFractionType_;
+        e_coverfrac_t             coveredFractionType_;
         //! Covered fraction of the selection for the current frame.
-        real                    coveredFraction_;
+        real                      coveredFraction_;
         //! The average covered fraction (over the trajectory).
-        real                    averageCoveredFraction_;
+        real                      averageCoveredFraction_;
         //! true if the value can change as a function of time.
-        bool                    bDynamic_;
+        bool                      bDynamic_;
         //! true if the covered fraction depends on the frame.
-        bool                    bDynamicCoveredFraction_;
+        bool                      bDynamicCoveredFraction_;
 
         /*! \brief
          * Needed to wrap access to information.
@@ -216,7 +222,7 @@ class SelectionData
         GMX_DISALLOW_COPY_AND_ASSIGN(SelectionData);
 };
 
-} // namespace internal
+}   // namespace internal
 
 /*! \brief
  * Provides access to a single selection.
@@ -227,6 +233,11 @@ class SelectionData
  * any time after the selection has been parsed, and type() can be accessed
  * after the selection has been compiled.
  *
+ * There are a few methods that can be used to change the behavior of the
+ * selection.  setEvaluateVelocities() and setEvaluateForces() can be called
+ * before the selection is compiled to request evaluation of velocities and/or
+ * forces in addition to coordinates.
+ *
  * Each selection is made of a set of positions.  Each position has associated
  * coordinates, and possibly velocities and forces if they have been requested
  * and are available.  It also has a set of atoms associated with it; typically
@@ -240,6 +251,9 @@ class SelectionData
  * It is also possible to access the list of atoms that make up all the
  * positions directly: atomCount() returns the total number of atoms in the
  * selection and atomIndices() an array of their indices.
+ * Similarly, it is possible to access the coordinates and other properties
+ * of the positions as continuous arrays through coordinates(), velocities(),
+ * forces(), masses(), charges(), refIds(), and mappedIds().
  *
  * Both positions and atoms can be accessed after the selection has been
  * compiled.  For dynamic selections, the return values of these methods change
@@ -276,6 +290,7 @@ class Selection
          *
          * Any attempt to call methods in the object before a selection is
          * assigned results in undefined behavior.
+         * isValid() returns `false` for the selection until it is initialized.
          */
         Selection() : sel_(NULL) {}
         /*! \brief
@@ -287,58 +302,135 @@ class Selection
          */
         explicit Selection(internal::SelectionData *sel) : sel_(sel) {}
 
+        //! Returns whether the selection object is initialized.
+        bool isValid() const { return sel_ != NULL; }
+
+        //! Returns whether two selection objects wrap the same selection.
+        bool operator==(const Selection &other) const
+        {
+            return sel_ == other.sel_;
+        }
+        //! Returns whether two selection objects wrap different selections.
+        bool operator!=(const Selection &other) const
+        {
+            return !operator==(other);
+        }
+
         //! Returns the name of the selection.
-        const char *name() const  { return data().name_.c_str(); }
+        const char *name() const  { return data().name(); }
         //! Returns the string that was parsed to produce this selection.
         const char *selectionText() const { return data().selectionText(); }
         //! Returns true if the size of the selection (posCount()) is dynamic.
         bool isDynamic() const { return data().isDynamic(); }
         //! Returns the type of positions in the selection.
-        e_index_t type() const { return data().rawPositions_.m.type; }
+        e_index_t type() const { return data().type(); }
+        //! Returns true if the selection only contains positions with a single atom each.
+        bool hasOnlyAtoms() const { return data().hasOnlyAtoms(); }
 
         //! Total number of atoms in the selection.
         int atomCount() const
         {
-            return data().rawPositions_.g != NULL ? data().rawPositions_.g->isize : 0;
+            return data().rawPositions_.m.mapb.nra;
         }
         //! Returns atom indices of all atoms in the selection.
         ConstArrayRef<int> atomIndices() const
         {
-            if (data().rawPositions_.g == NULL)
-            {
-                return ConstArrayRef<int>();
-            }
-            return ConstArrayRef<int>(data().rawPositions_.g->isize,
-                                      data().rawPositions_.g->index);
+            return constArrayRefFromArray(sel_->rawPositions_.m.mapb.a,
+                                          sel_->rawPositions_.m.mapb.nra);
         }
         //! Number of positions in the selection.
         int posCount() const { return data().posCount(); }
         //! Access a single position.
         SelectionPosition position(int i) const;
+        //! Returns coordinates for this selection as a continuous array.
+        ConstArrayRef<rvec> coordinates() const
+        {
+            return constArrayRefFromArray(data().rawPositions_.x, posCount());
+        }
+        //! Returns whether velocities are available for this selection.
+        bool hasVelocities() const { return data().rawPositions_.v != NULL; }
         /*! \brief
-         * Sets the ID for the \p i'th position for use with
-         * SelectionPosition::mappedId().
+         * Returns velocities for this selection as a continuous array.
          *
-         * \param[in] i  Zero-based index
-         * \param[in] id Identifier to set.
+         * Must not be called if hasVelocities() returns false.
+         */
+        ConstArrayRef<rvec> velocities() const
+        {
+            GMX_ASSERT(hasVelocities(), "Velocities accessed, but unavailable");
+            return constArrayRefFromArray(data().rawPositions_.v, posCount());
+        }
+        //! Returns whether forces are available for this selection.
+        bool hasForces() const { return sel_->rawPositions_.f != NULL; }
+        /*! \brief
+         * Returns forces for this selection as a continuous array.
          *
-         * This method is not part of SelectionPosition because that interface
-         * only provides access to const data by design.
+         * Must not be called if hasForces() returns false.
+         */
+        ConstArrayRef<rvec> forces() const
+        {
+            GMX_ASSERT(hasForces(), "Forces accessed, but unavailable");
+            return constArrayRefFromArray(data().rawPositions_.f, posCount());
+        }
+        //! Returns masses for this selection as a continuous array.
+        ConstArrayRef<real> masses() const
+        {
+            // posMass_ may have more entries than posCount() in the case of
+            // dynamic selections that don't have a topology
+            // (and thus the masses and charges are fixed).
+            GMX_ASSERT(data().posMass_.size() >= static_cast<size_t>(posCount()),
+                       "Internal inconsistency");
+            return constArrayRefFromVector<real>(data().posMass_.begin(),
+                                                 data().posMass_.begin() + posCount());
+        }
+        //! Returns charges for this selection as a continuous array.
+        ConstArrayRef<real> charges() const
+        {
+            // posCharge_ may have more entries than posCount() in the case of
+            // dynamic selections that don't have a topology
+            // (and thus the masses and charges are fixed).
+            GMX_ASSERT(data().posCharge_.size() >= static_cast<size_t>(posCount()),
+                       "Internal inconsistency");
+            return constArrayRefFromVector<real>(data().posCharge_.begin(),
+                                                 data().posCharge_.begin() + posCount());
+        }
+        /*! \brief
+         * Returns reference IDs for this selection as a continuous array.
          *
-         * This method can only be called after compilation, before the
-         * selection has been evaluated for any frame.
+         * \see SelectionPosition::refId()
+         */
+        ConstArrayRef<int> refIds() const
+        {
+            return constArrayRefFromArray(data().rawPositions_.m.refid, posCount());
+        }
+        /*! \brief
+         * Returns mapped IDs for this selection as a continuous array.
          *
          * \see SelectionPosition::mappedId()
          */
-        void setOriginalId(int i, int id) { data().rawPositions_.m.orgid[i] = id; }
-
-        //! Deprecated method for direct access to position data.
-        const gmx_ana_pos_t *positions() const { return &data().rawPositions_; }
+        ConstArrayRef<int> mappedIds() const
+        {
+            return constArrayRefFromArray(data().rawPositions_.m.mapid, posCount());
+        }
 
         //! Returns whether the covered fraction can change between frames.
         bool isCoveredFractionDynamic() const { return data().isCoveredFractionDynamic(); }
         //! Returns the covered fraction for the current frame.
         real coveredFraction() const { return data().coveredFraction_; }
+
+        /*! \brief
+         * Allows passing a selection directly to neighborhood searching.
+         *
+         * When initialized this way, AnalysisNeighborhoodPair objects return
+         * indices that can be used to index the selection positions with
+         * position().
+         *
+         * Works exactly like if AnalysisNeighborhoodPositions had a
+         * constructor taking a Selection object as a parameter.
+         * See AnalysisNeighborhoodPositions for rationale and additional
+         * discussion.
+         */
+        operator AnalysisNeighborhoodPositions() const;
+
         /*! \brief
          * Initializes information about covered fractions.
          *
@@ -350,6 +442,57 @@ class Selection
         {
             return data().initCoveredFraction(type);
         }
+        /*! \brief
+         * Sets whether this selection evaluates velocities for positions.
+         *
+         * \param[in] bEnabled  If true, velocities are evaluated.
+         *
+         * If you request the evaluation, but then evaluate the selection for
+         * a frame that does not contain velocity information, results are
+         * undefined.
+         *
+         * \todo
+         * Implement it such that in the above case, hasVelocities() will
+         * return false for such frames.
+         *
+         * Does not throw.
+         */
+        void setEvaluateVelocities(bool bEnabled)
+        {
+            data().flags_.set(efSelection_EvaluateVelocities, bEnabled);
+        }
+        /*! \brief
+         * Sets whether this selection evaluates forces for positions.
+         *
+         * \param[in] bEnabled  If true, forces are evaluated.
+         *
+         * If you request the evaluation, but then evaluate the selection for
+         * a frame that does not contain force information, results are
+         * undefined.
+         *
+         * Does not throw.
+         */
+        void setEvaluateForces(bool bEnabled)
+        {
+            data().flags_.set(efSelection_EvaluateForces, bEnabled);
+        }
+
+        /*! \brief
+         * Sets the ID for the \p i'th position for use with
+         * SelectionPosition::mappedId().
+         *
+         * \param[in] i  Zero-based index
+         * \param[in] id Identifier to set.
+         *
+         * This method is not part of SelectionPosition because that interface
+         * only provides access to const data by design.
+         *
+         * This method can only be called after compilation, before the
+         * selection has been evaluated for any frame.
+         *
+         * \see SelectionPosition::mappedId()
+         */
+        void setOriginalId(int i, int id) { data().rawPositions_.m.orgid[i] = id; }
 
         /*! \brief
          * Prints out one-line description of the selection.
@@ -448,34 +591,32 @@ class SelectionPosition
          *
          * Currently always returns the same as Selection::type().
          */
-        e_index_t type() const { return sel_->rawPositions_.m.type; }
+        e_index_t type() const { return sel_->type(); }
         //! Returns coordinates for this position.
         const rvec &x() const
         {
             return sel_->rawPositions_.x[i_];
         }
-        //! Returns whether velocity is available for this position.
-        bool hasVelocity() const { return sel_->rawPositions_.v != NULL; }
         /*! \brief
          * Returns velocity for this position.
          *
-         * Must not be called if hasVelocity() returns false.
+         * Must not be called if Selection::hasVelocities() returns false.
          */
         const rvec &v() const
         {
-            GMX_ASSERT(hasVelocity(), "Velocities accessed, but unavailable");
+            GMX_ASSERT(sel_->rawPositions_.v != NULL,
+                       "Velocities accessed, but unavailable");
             return sel_->rawPositions_.v[i_];
         }
-        //! Returns whether force is available for this position.
-        bool hasForce() const { return sel_->rawPositions_.f != NULL; }
         /*! \brief
          * Returns force for this position.
          *
-         * Must not be called if hasForce() returns false.
+         * Must not be called if Selection::hasForces() returns false.
          */
         const rvec &f() const
         {
-            GMX_ASSERT(hasForce(), "Forces accessed, but unavailable");
+            GMX_ASSERT(sel_->rawPositions_.f != NULL,
+                       "Velocities accessed, but unavailable");
             return sel_->rawPositions_.f[i_];
         }
         /*! \brief
@@ -487,7 +628,7 @@ class SelectionPosition
          */
         real mass() const
         {
-            return sel_->posInfo_[i_].mass;
+            return sel_->posMass_[i_];
         }
         /*! \brief
          * Returns total charge for this position.
@@ -498,24 +639,24 @@ class SelectionPosition
          */
         real charge() const
         {
-            return sel_->posInfo_[i_].charge;
+            return sel_->posCharge_[i_];
         }
         //! Returns the number of atoms that make up this position.
         int atomCount() const
         {
             return sel_->rawPositions_.m.mapb.index[i_ + 1]
-                 - sel_->rawPositions_.m.mapb.index[i_];
+                   - sel_->rawPositions_.m.mapb.index[i_];
         }
         //! Return atom indices that make up this position.
         ConstArrayRef<int> atomIndices() const
         {
-            if (sel_->rawPositions_.g == NULL)
+            const int *atoms = sel_->rawPositions_.m.mapb.a;
+            if (atoms == NULL)
             {
                 return ConstArrayRef<int>();
             }
-            int first = sel_->rawPositions_.m.mapb.index[i_];
-            return ConstArrayRef<int>(atomCount(),
-                                      &sel_->rawPositions_.g->index[first]);
+            const int first = sel_->rawPositions_.m.mapb.index[i_];
+            return constArrayRefFromArray(&atoms[first], atomCount());
         }
         /*! \brief
          * Returns whether this position is selected in the current frame.
@@ -576,6 +717,20 @@ class SelectionPosition
             return sel_->rawPositions_.m.mapid[i_];
         }
 
+        /*! \brief
+         * Allows passing a selection position directly to neighborhood searching.
+         *
+         * When initialized this way, AnalysisNeighborhoodPair objects return
+         * the index that can be used to access this position using
+         * Selection::position().
+         *
+         * Works exactly like if AnalysisNeighborhoodPositions had a
+         * constructor taking a SelectionPosition object as a parameter.
+         * See AnalysisNeighborhoodPositions for rationale and additional
+         * discussion.
+         */
+        operator AnalysisNeighborhoodPositions() const;
+
     private:
         const internal::SelectionData  *sel_;
         int                             i_;