| version 1.11 | version 1.12 |
|---|
| |
| /// -*- c++ -*- | // -*- c++ -*- |
| | |
| #ifndef COLVARATOMS_H | #ifndef COLVARATOMS_H |
| #define COLVARATOMS_H | #define COLVARATOMS_H |
| | |
| #include "colvarmodule.h" | #include "colvarmodule.h" |
| #include "colvarparse.h" | #include "colvarparse.h" |
| | #include "colvardeps.h" |
| | |
| | |
| /// \brief Stores numeric id, mass and all mutable data for an atom, | /// \brief Stores numeric id, mass and all mutable data for an atom, |
| /// mostly used by a \link cvc \endlink | /// mostly used by a \link cvc \endlink |
| /// | /// |
| /// This class may be used (although not necessarily) to keep atomic | /// This class may be used to keep atomic data such as id, mass, |
| /// data (id, mass, position and collective variable derivatives) | /// position and collective variable derivatives) altogether. |
| /// altogether. There may be multiple instances with identical | /// There may be multiple instances with identical |
| /// numeric id, all acting independently: forces communicated through | /// numeric id, all acting independently: forces communicated through |
| /// these instances will be summed together. | /// these instances will be summed together. |
| /// | |
| /// Read/write operations depend on the underlying code: hence, some | |
| /// member functions are defined in colvarproxy_xxx.h. | |
| class colvarmodule::atom { | class colvarmodule::atom { |
| | |
| protected: | protected: |
| | |
| /// \brief Index in the list of atoms involved by the colvars (\b | /// Index in the colvarproxy arrays (\b NOT in the global topology!) |
| /// NOT in the global topology!) | |
| int index; | int index; |
| | |
| public: | public: |
| | |
| /// Internal identifier (zero-based) | /// Identifier for the MD program (0-based) |
| int id; | int id; |
| | |
| /// Mass | /// Mass |
| cvm::real mass; | cvm::real mass; |
| | |
| | /// Charge |
| | cvm::real charge; |
| | |
| /// \brief Current position (copied from the program, can be | /// \brief Current position (copied from the program, can be |
| /// manipulated) | /// modified if necessary) |
| cvm::atom_pos pos; | cvm::atom_pos pos; |
| | |
| /// \brief Current velocity (copied from the program, can be | /// \brief Current velocity (copied from the program, can be |
| /// manipulated) | /// modified if necessary) |
| cvm::rvector vel; | cvm::rvector vel; |
| | |
| /// \brief System force at the previous step (copied from the | /// \brief System force at the previous step (copied from the |
| /// program, can be manipulated) | /// program, can be modified if necessary) |
| cvm::rvector system_force; | cvm::rvector total_force; |
| | |
| /// \brief Gradient of a scalar collective variable with respect | /// \brief Gradient of a scalar collective variable with respect |
| /// to this atom | /// to this atom |
| |
| /// implementation | /// implementation |
| cvm::rvector grad; | cvm::rvector grad; |
| | |
| /// \brief Default constructor, setting index and id to invalid numbers | /// \brief Default constructor (sets index and id both to -1) |
| atom() : index(-1), id(-1) { reset_data(); } | atom(); |
| | |
| /// \brief Initialize an atom for collective variable calculation | /// \brief Initialize an atom for collective variable calculation |
| /// and get its internal identifier \param atom_number Atom index in | /// and get its internal identifier \param atom_number Atom index in |
| /// the system topology (starting from 1) | /// the system topology (starting from 1) |
| atom(int const &atom_number); | atom(int atom_number); |
| | |
| /// \brief Initialize an atom for collective variable calculation | /// \brief Initialize an atom for collective variable calculation |
| /// and get its internal identifier \param residue Residue number | /// and get its internal identifier \param residue Residue number |
| |
| /// type of topologies, may not be required | /// type of topologies, may not be required |
| atom(cvm::residue_id const &residue, | atom(cvm::residue_id const &residue, |
| std::string const &atom_name, | std::string const &atom_name, |
| std::string const &segment_id = std::string("")); | std::string const &segment_id); |
| | |
| /// Copy constructor | /// Copy constructor |
| atom(atom const &a); | atom(atom const &a); |
| |
| /// Destructor | /// Destructor |
| ~atom(); | ~atom(); |
| | |
| /// Set non-constant data (everything except id and mass) to zero | /// Set mutable data (everything except id and mass) to zero; update mass |
| inline void reset_data() { | inline void reset_data() |
| pos = atom_pos(0.0); | { |
| vel = grad = system_force = rvector(0.0); | pos = cvm::atom_pos(0.0); |
| | vel = grad = total_force = cvm::rvector(0.0); |
| | } |
| | |
| | /// Get the latest value of the mass |
| | inline void update_mass() |
| | { |
| | mass = (cvm::proxy)->get_atom_mass(index); |
| | } |
| | |
| | /// Get the latest value of the charge |
| | inline void update_charge() |
| | { |
| | charge = (cvm::proxy)->get_atom_charge(index); |
| } | } |
| | |
| /// Get the current position | /// Get the current position |
| void read_position(); | inline void read_position() |
| | { |
| | pos = (cvm::proxy)->get_atom_position(index); |
| | } |
| | |
| /// Get the current velocity | /// Get the current velocity |
| void read_velocity(); | inline void read_velocity() |
| | { |
| | vel = (cvm::proxy)->get_atom_velocity(index); |
| | } |
| | |
| /// Get the system force | /// Get the total force |
| void read_system_force(); | inline void read_total_force() |
| | { |
| | total_force = (cvm::proxy)->get_atom_total_force(index); |
| | } |
| | |
| /// \brief Apply a force to the atom | /// \brief Apply a force to the atom |
| /// | /// |
| /// The force will be used later by the MD integrator, the | /// Note: the force is not applied instantly, but will be used later |
| /// collective variables module does not integrate equations of | /// by the MD integrator (the colvars module does not integrate |
| /// motion. Multiple calls to this function by either the same | /// equations of motion. |
| | /// |
| | /// Multiple calls to this function by either the same |
| /// \link atom \endlink object or different objects with identical | /// \link atom \endlink object or different objects with identical |
| /// \link id \endlink, will all add to the existing MD force. | /// \link id \endlink will all be added together. |
| void apply_force(cvm::rvector const &new_force); | inline void apply_force(cvm::rvector const &new_force) const |
| | { |
| | (cvm::proxy)->apply_atom_force(index, new_force); |
| | } |
| }; | }; |
| | |
| | |
| | |
| | |
| /// \brief Group of \link atom \endlink objects, mostly used by a | /// \brief Group of \link atom \endlink objects, mostly used by a |
| /// \link cvc \endlink | /// \link cvc \endlink object to gather all atomic data |
| /// | |
| /// This class inherits from \link colvarparse \endlink and from | |
| /// std::vector<colvarmodule::atom>, and hence all functions and | |
| /// operators (including the bracket operator, group[i]) can be used | |
| /// on an \link atom_group \endlink object. It can be initialized as | |
| /// a vector, or by parsing a keyword in the configuration. | |
| class colvarmodule::atom_group | class colvarmodule::atom_group |
| : public std::vector<cvm::atom>, | : public colvarparse, public colvardeps |
| public colvarparse | |
| { | { |
| public: | public: |
| // Note: all members here are kept public, to allow any | |
| // object accessing and manipulating them | |
| | |
| | /// \brief Initialize the group by looking up its configuration |
| | /// string in conf and parsing it; this is actually done by parse(), |
| | /// which is a member function so that a group can be initialized |
| | /// also after construction |
| | atom_group(std::string const &conf, |
| | char const *key); |
| | |
| | /// \brief Keyword used to define the group |
| | // TODO Make this field part of the data structures that link a group to a CVC |
| | std::string key; |
| | |
| | /// \brief Set default values for common flags |
| | int init(); |
| | |
| | /// \brief Update data required to calculate cvc's |
| | int setup(); |
| | |
| | /// \brief Initialize the group by looking up its configuration |
| | /// string in conf and parsing it |
| | int parse(std::string const &conf); |
| | |
| | int add_atom_numbers(std::string const &numbers_conf); |
| | int add_index_group(std::string const &index_group_name); |
| | int add_atom_numbers_range(std::string const &range_conf); |
| | int add_atom_name_residue_range(std::string const &psf_segid, |
| | std::string const &range_conf); |
| | int parse_fitting_options(std::string const &group_conf); |
| | |
| | /// \brief Initialize the group after a (temporary) vector of atoms |
| | atom_group(std::vector<cvm::atom> const &atoms_in); |
| | |
| | /// \brief Add an atom object to this group |
| | int add_atom(cvm::atom const &a); |
| | |
| | /// \brief Add an atom ID to this group (the actual atomicdata will be not be handled by the group) |
| | int add_atom_id(int aid); |
| | |
| | /// \brief Remove an atom object from this group |
| | int remove_atom(cvm::atom_iter ai); |
| | |
| | /// \brief Re-initialize the total mass of a group. |
| | /// This is needed in case the hosting MD code has an option to |
| | /// change atom masses after their initialization. |
| | void reset_mass(std::string &name, int i, int j); |
| | |
| | /// \brief Implementation of the feature list for atom group |
| | static std::vector<feature *> ag_features; |
| | |
| | /// \brief Implementation of the feature list accessor for atom group |
| | virtual std::vector<feature *> &features() { |
| | return ag_features; |
| | } |
| | |
| | /// \brief Default constructor |
| | atom_group(); |
| | |
| | /// \brief Destructor |
| | ~atom_group(); |
| | |
| | protected: |
| | |
| | /// \brief Array of atom objects |
| | std::vector<cvm::atom> atoms; |
| | |
| | /// \brief Array of atom identifiers for the MD program (0-based) |
| | std::vector<int> atoms_ids; |
| | |
| | /// \brief Dummy atom position |
| | cvm::atom_pos dummy_atom_pos; |
| | |
| | /// \brief Index in the colvarproxy arrays (if the group is scalable) |
| | int index; |
| | |
| | public: |
| | |
| | inline cvm::atom & operator [] (size_t const i) |
| | { |
| | return atoms[i]; |
| | } |
| | |
| | inline cvm::atom const & operator [] (size_t const i) const |
| | { |
| | return atoms[i]; |
| | } |
| | |
| | inline cvm::atom_iter begin() |
| | { |
| | return atoms.begin(); |
| | } |
| | |
| | inline cvm::atom_const_iter begin() const |
| | { |
| | return atoms.begin(); |
| | } |
| | |
| | inline cvm::atom_iter end() |
| | { |
| | return atoms.end(); |
| | } |
| | |
| | inline cvm::atom_const_iter end() const |
| | { |
| | return atoms.end(); |
| | } |
| | |
| | inline size_t size() const |
| | { |
| | return atoms.size(); |
| | } |
| | |
| /// \brief If this option is on, this group merely acts as a wrapper | /// \brief If this option is on, this group merely acts as a wrapper |
| /// for a fixed position; any calls to atoms within or to | /// for a fixed position; any calls to atoms within or to |
| /// functions that return disaggregated data will fail | /// functions that return disaggregated data will fail |
| bool b_dummy; | bool b_dummy; |
| /// \brief dummy atom position | |
| cvm::atom_pos dummy_atom_pos; | |
| | |
| /// Sorted list of zero-based (internal) atom ids | /// Sorted list of zero-based (internal) atom ids |
| /// (populated on-demand by create_sorted_ids) | /// (populated on-demand by create_sorted_ids) |
| |
| bool b_user_defined_fit; | bool b_user_defined_fit; |
| | |
| /// \brief Whether or not the derivatives of the roto-translation | /// \brief Whether or not the derivatives of the roto-translation |
| /// should be included when calculating the colvar's gradients (default: no) | /// should be included when calculating the colvar's gradients (default: yes) |
| bool b_fit_gradients; | bool b_fit_gradients; |
| | |
| /// \brief use reference coordinates for b_center or b_rotate | /// \brief use reference coordinates for b_center or b_rotate |
| |
| | |
| /// \brief If b_center or b_rotate is true, use this group to | /// \brief If b_center or b_rotate is true, use this group to |
| /// define the transformation (default: this group itself) | /// define the transformation (default: this group itself) |
| atom_group *ref_pos_group; | atom_group *fitting_group; |
| | |
| /// Total mass of the atom group | /// Total mass of the atom group |
| cvm::real total_mass; | cvm::real total_mass; |
| | void update_total_mass(); |
| | |
| | /// Total charge of the atom group |
| | cvm::real total_charge; |
| | void update_total_charge(); |
| | |
| /// \brief Don't apply any force on this group (use its coordinates | /// \brief Don't apply any force on this group (use its coordinates |
| /// only to calculate a colvar) | /// only to calculate a colvar) |
| bool noforce; | bool noforce; |
| | |
| | /// \brief Get the current positions |
| /// \brief Initialize the group by looking up its configuration | |
| /// string in conf and parsing it; this is actually done by parse(), | |
| /// which is a member function so that a group can be initialized | |
| /// also after construction | |
| atom_group(std::string const &conf, | |
| char const *key); | |
| | |
| /// \brief Initialize the group by looking up its configuration | |
| /// string in conf and parsing it | |
| int parse(std::string const &conf, | |
| char const *key); | |
| | |
| /// \brief Initialize the group after a temporary vector of atoms | |
| atom_group(std::vector<cvm::atom> const &atoms); | |
| | |
| /// \brief Add an atom to this group | |
| void add_atom(cvm::atom const &a); | |
| | |
| /// \brief Re-initialize the total mass of a group. | |
| /// This is needed in case the hosting MD code has an option to | |
| /// change atom masses after their initialization. | |
| void reset_mass(std::string &name, int i, int j); | |
| | |
| /// \brief Default constructor | |
| atom_group(); | |
| | |
| /// \brief Destructor | |
| ~atom_group(); | |
| | |
| /// \brief Get the current positions; if b_center or b_rotate are | |
| /// true, calc_apply_roto_translation() will be called too | |
| void read_positions(); | void read_positions(); |
| | |
| /// \brief (Re)calculate the optimal roto-translation | /// \brief (Re)calculate the optimal roto-translation |
| void calc_apply_roto_translation(); | void calc_apply_roto_translation(); |
| | |
| /// \brief Save center of geometry fo ref positions, | /// \brief Save aside the center of geometry of the reference positions, |
| /// then subtract it | /// then subtract it from them |
| | /// |
| | /// In this way it will be possible to use ref_pos also for the |
| | /// rotational fit. |
| | /// This is called either by atom_group::parse or by CVCs that assign |
| | /// reference positions (eg. RMSD, eigenvector). |
| void center_ref_pos(); | void center_ref_pos(); |
| | |
| /// \brief Move all positions | /// \brief Move all positions |
| void apply_translation(cvm::rvector const &t); | void apply_translation(cvm::rvector const &t); |
| | |
| /// \brief Rotate all positions | |
| void apply_rotation(cvm::rotation const &q); | |
| | |
| | |
| /// \brief Get the current velocities; this must be called always | /// \brief Get the current velocities; this must be called always |
| /// *after* read_positions(); if b_rotate is defined, the same | /// *after* read_positions(); if b_rotate is defined, the same |
| /// rotation applied to the coordinates will be used | /// rotation applied to the coordinates will be used |
| void read_velocities(); | void read_velocities(); |
| | |
| /// \brief Get the current system_forces; this must be called always | /// \brief Get the current total_forces; this must be called always |
| /// *after* read_positions(); if b_rotate is defined, the same | /// *after* read_positions(); if b_rotate is defined, the same |
| /// rotation applied to the coordinates will be used | /// rotation applied to the coordinates will be used |
| void read_system_forces(); | void read_total_forces(); |
| | |
| /// Call reset_data() for each atom | /// Call reset_data() for each atom |
| inline void reset_atoms_data() | inline void reset_atoms_data() |
| { | { |
| for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) | for (cvm::atom_iter ai = atoms.begin(); ai != atoms.end(); ai++) |
| ai->reset_data(); | ai->reset_data(); |
| if (ref_pos_group) | if (fitting_group) |
| ref_pos_group->reset_atoms_data(); | fitting_group->reset_atoms_data(); |
| } | } |
| | |
| | /// \brief Recompute all mutable quantities that are required to compute CVCs |
| | int calc_required_properties(); |
| | |
| /// \brief Return a copy of the current atom positions | /// \brief Return a copy of the current atom positions |
| std::vector<cvm::atom_pos> positions() const; | std::vector<cvm::atom_pos> positions() const; |
| | |
| /// \brief Return a copy of the current atom positions, shifted by a constant vector | /// \brief Calculate the center of geometry of the atomic positions, assuming |
| std::vector<cvm::atom_pos> positions_shifted(cvm::rvector const &shift) const; | /// that they are already pbc-wrapped |
| | int calc_center_of_geometry(); |
| | |
| | private: |
| | |
| | /// \brief Center of geometry |
| | cvm::atom_pos cog; |
| | |
| | /// \brief Center of geometry before any fitting |
| | cvm::atom_pos cog_orig; |
| | |
| | public: |
| | |
| /// \brief Return the center of geometry of the positions, assuming | /// \brief Return the center of geometry of the atomic positions |
| /// that coordinates are already pbc-wrapped | inline cvm::atom_pos center_of_geometry() const |
| cvm::atom_pos center_of_geometry() const; | { |
| | return cog; |
| /// \brief Return the center of mass of the positions, assuming that | } |
| /// coordinates are already pbc-wrapped | |
| cvm::atom_pos center_of_mass() const; | |
| | |
| /// \brief Atom positions at the previous step | /// \brief Calculate the center of mass of the atomic positions, assuming that |
| std::vector<cvm::atom_pos> old_pos; | /// they are already pbc-wrapped |
| | int calc_center_of_mass(); |
| | private: |
| | /// \brief Center of mass |
| | cvm::atom_pos com; |
| | /// \brief The derivative of a scalar variable with respect to the COM |
| | // TODO for scalable calculations of more complex variables (e.g. rotation), |
| | // use a colvarvalue of vectors to hold the entire derivative |
| | cvm::rvector scalar_com_gradient; |
| | public: |
| | /// \brief Return the center of mass of the atomic positions |
| | inline cvm::atom_pos center_of_mass() const |
| | { |
| | return com; |
| | } |
| | |
| | /// \brief Return a copy of the current atom positions, shifted by a constant vector |
| | std::vector<cvm::atom_pos> positions_shifted(cvm::rvector const &shift) const; |
| | |
| /// \brief Return a copy of the current atom velocities | /// \brief Return a copy of the current atom velocities |
| std::vector<cvm::rvector> velocities() const; | std::vector<cvm::rvector> velocities() const; |
| | |
| | ///\brief Calculate the dipole of the atom group around the specified center |
| | int calc_dipole(cvm::atom_pos const &com); |
| | private: |
| | cvm::rvector dip; |
| | public: |
| | ///\brief Return the (previously calculated) dipole of the atom group |
| | inline cvm::rvector dipole() const |
| | { |
| | return dip; |
| | } |
| | |
| | /// \brief Return a copy of the total forces |
| | std::vector<cvm::rvector> total_forces() const; |
| | |
| /// \brief Return a copy of the system forces | |
| std::vector<cvm::rvector> system_forces() const; | |
| /// \brief Return a copy of the aggregated total force on the group | /// \brief Return a copy of the aggregated total force on the group |
| cvm::rvector system_force() const; | cvm::rvector total_force() const; |
| | |
| | |
| /// \brief Shorthand: save the specified gradient on each atom, | /// \brief Shorthand: save the specified gradient on each atom, |
| |
| /// micromanage the force. | /// micromanage the force. |
| void apply_force(cvm::rvector const &force); | void apply_force(cvm::rvector const &force); |
| | |
| /// \brief Apply an array of forces directly on the individual | |
| /// atoms; the length of the specified vector must be the same of | |
| /// this \link atom_group \endlink. | |
| /// | |
| /// If the group is being rotated to a reference frame (e.g. to | |
| /// express the colvar independently from the solute rotation), the | |
| /// forces are rotated back to the original frame. Colvar gradients | |
| /// are not used, either because they were not defined (e.g because | |
| /// the colvar has not a scalar value) or the biases require to | |
| /// micromanage the forces. | |
| void apply_forces(std::vector<cvm::rvector> const &forces); | |
| | |
| }; | }; |
| | |
| | |