forked from lijiext/lammps
333 lines
12 KiB
C++
333 lines
12 KiB
C++
// -*- c++ -*-
|
|
|
|
#ifndef COLVARATOMS_H
|
|
#define COLVARATOMS_H
|
|
|
|
#include "colvarmodule.h"
|
|
#include "colvarparse.h"
|
|
|
|
/// \brief Stores numeric id, mass and all mutable data for an atom,
|
|
/// mostly used by a \link cvc \endlink
|
|
///
|
|
/// This class may be used (although not necessarily) to keep atomic
|
|
/// data (id, mass, position and collective variable derivatives)
|
|
/// altogether. There may be multiple instances with identical
|
|
/// numeric id, all acting independently: forces communicated through
|
|
/// 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 {
|
|
|
|
protected:
|
|
|
|
/// \brief Index in the list of atoms involved by the colvars (\b
|
|
/// NOT in the global topology!)
|
|
int index;
|
|
|
|
public:
|
|
|
|
/// Internal identifier (zero-based)
|
|
int id;
|
|
|
|
/// Mass
|
|
cvm::real mass;
|
|
|
|
/// \brief Current position (copied from the program, can be
|
|
/// manipulated)
|
|
cvm::atom_pos pos;
|
|
|
|
/// \brief Current velocity (copied from the program, can be
|
|
/// manipulated)
|
|
cvm::rvector vel;
|
|
|
|
/// \brief System force at the previous step (copied from the
|
|
/// program, can be manipulated)
|
|
cvm::rvector system_force;
|
|
|
|
/// \brief Gradient of a scalar collective variable with respect
|
|
/// to this atom
|
|
///
|
|
/// This can only handle a scalar collective variable (i.e. when
|
|
/// the \link colvarvalue::real_value \endlink member is used
|
|
/// from the \link colvarvalue \endlink class), which is also the
|
|
/// most frequent case. For more complex types of \link
|
|
/// colvarvalue \endlink objects, atomic gradients should be
|
|
/// defined within the specific \link cvc \endlink
|
|
/// implementation
|
|
cvm::rvector grad;
|
|
|
|
/// \brief Default constructor, setting id and index to invalid numbers
|
|
atom() : id (-1), index (-1) { reset_data(); }
|
|
|
|
/// \brief Initialize an atom for collective variable calculation
|
|
/// and get its internal identifier \param atom_number Atom index in
|
|
/// the system topology (starting from 1)
|
|
atom (int const &atom_number);
|
|
|
|
/// \brief Initialize an atom for collective variable calculation
|
|
/// and get its internal identifier \param residue Residue number
|
|
/// \param atom_name Name of the atom in the residue \param
|
|
/// segment_id For PSF topologies, the segment identifier; for other
|
|
/// type of topologies, may not be required
|
|
atom (cvm::residue_id const &residue,
|
|
std::string const &atom_name,
|
|
std::string const &segment_id = std::string (""));
|
|
|
|
/// Copy constructor
|
|
atom (atom const &a);
|
|
|
|
/// Destructor
|
|
~atom();
|
|
|
|
/// Set non-constant data (everything except id and mass) to zero
|
|
inline void reset_data() {
|
|
pos = atom_pos (0.0);
|
|
vel = grad = system_force = rvector (0.0);
|
|
}
|
|
|
|
/// Get the current position
|
|
void read_position();
|
|
|
|
/// Get the current velocity
|
|
void read_velocity();
|
|
|
|
/// Get the system force
|
|
void read_system_force();
|
|
|
|
/// \brief Apply a force to the atom
|
|
///
|
|
/// The force will be used later by the MD integrator, the
|
|
/// collective variables module does not integrate equations of
|
|
/// motion. Multiple calls to this function by either the same
|
|
/// \link atom \endlink object or different objects with identical
|
|
/// \link id \endlink, will all add to the existing MD force.
|
|
void apply_force (cvm::rvector const &new_force);
|
|
};
|
|
|
|
|
|
|
|
|
|
/// \brief Group of \link atom \endlink objects, mostly used by a
|
|
/// \link cvc \endlink
|
|
///
|
|
/// 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
|
|
: public std::vector<cvm::atom>,
|
|
public colvarparse
|
|
{
|
|
public:
|
|
// Note: all members here are kept public, to allow any
|
|
// object accessing and manipulating them
|
|
|
|
|
|
/// \brief If this option is on, this group merely acts as a wrapper
|
|
/// for a fixed position; any calls to atoms within or to
|
|
/// functions that return disaggregated data will fail
|
|
bool b_dummy;
|
|
/// \brief dummy atom position
|
|
cvm::atom_pos dummy_atom_pos;
|
|
|
|
/// Sorted list of zero-based (internal) atom ids
|
|
/// (populated on-demand by create_sorted_ids)
|
|
std::vector<int> sorted_ids;
|
|
|
|
/// Allocates and populates the sorted list of atom ids
|
|
void create_sorted_ids (void);
|
|
|
|
|
|
/// \brief When updating atomic coordinates, translate them to align with the
|
|
/// center of mass of the reference coordinates
|
|
bool b_center;
|
|
|
|
/// \brief When updating atom coordinates (and after
|
|
/// centering them if b_center is set), rotate the group to
|
|
/// align with the reference coordinates.
|
|
///
|
|
/// Note: gradients will be calculated in the rotated frame: when
|
|
/// forces will be applied, they will rotated back to the original
|
|
/// frame
|
|
bool b_rotate;
|
|
/// The rotation calculated automatically if b_rotate is defined
|
|
cvm::rotation rot;
|
|
|
|
/// \brief Indicates that the user has explicitly set centerReference or
|
|
/// rotateReference, and the corresponding reference:
|
|
/// cvc's (eg rmsd, eigenvector) will not override the user's choice
|
|
bool b_user_defined_fit;
|
|
|
|
/// \brief Whether or not the derivatives of the roto-translation
|
|
/// should be included when calculating the colvar's gradients (default: no)
|
|
bool b_fit_gradients;
|
|
|
|
/// \brief use reference coordinates for b_center or b_rotate
|
|
std::vector<cvm::atom_pos> ref_pos;
|
|
|
|
/// \brief Center of geometry of the reference coordinates; regardless
|
|
/// of whether b_center is true, ref_pos is centered to zero at
|
|
/// initialization, and ref_pos_cog serves to center the positions
|
|
cvm::atom_pos ref_pos_cog;
|
|
|
|
/// \brief If b_center or b_rotate is true, use this group to
|
|
/// define the transformation (default: this group itself)
|
|
atom_group *ref_pos_group;
|
|
|
|
/// Total mass of the atom group
|
|
cvm::real total_mass;
|
|
|
|
/// \brief Don't apply any force on this group (use its coordinates
|
|
/// only to calculate a colvar)
|
|
bool noforce;
|
|
|
|
|
|
/// \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
|
|
void 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();
|
|
|
|
/// \brief (Re)calculate the optimal roto-translation
|
|
void calc_apply_roto_translation();
|
|
|
|
/// \brief Save center of geometry fo ref positions,
|
|
/// then subtract it
|
|
void center_ref_pos();
|
|
|
|
/// \brief Move all positions
|
|
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
|
|
/// *after* read_positions(); if b_rotate is defined, the same
|
|
/// rotation applied to the coordinates will be used
|
|
void read_velocities();
|
|
|
|
/// \brief Get the current system_forces; this must be called always
|
|
/// *after* read_positions(); if b_rotate is defined, the same
|
|
/// rotation applied to the coordinates will be used
|
|
void read_system_forces();
|
|
|
|
/// Call reset_data() for each atom
|
|
inline void reset_atoms_data()
|
|
{
|
|
for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++)
|
|
ai->reset_data();
|
|
if (ref_pos_group)
|
|
ref_pos_group->reset_atoms_data();
|
|
}
|
|
|
|
/// \brief Return a copy of the current atom positions
|
|
std::vector<cvm::atom_pos> positions() const;
|
|
|
|
/// \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 the center of geometry of the positions, assuming
|
|
/// that coordinates are already pbc-wrapped
|
|
cvm::atom_pos center_of_geometry() const;
|
|
|
|
/// \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
|
|
std::vector<cvm::atom_pos> old_pos;
|
|
|
|
|
|
/// \brief Return a copy of the current atom velocities
|
|
std::vector<cvm::rvector> velocities() 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
|
|
cvm::rvector system_force() const;
|
|
|
|
|
|
/// \brief Shorthand: save the specified gradient on each atom,
|
|
/// weighting with the atom mass (mostly used in combination with
|
|
/// \link center_of_mass() \endlink)
|
|
void set_weighted_gradient (cvm::rvector const &grad);
|
|
|
|
/// \brief Calculate the derivatives of the fitting transformation
|
|
void calc_fit_gradients();
|
|
|
|
/// \brief Derivatives of the fitting transformation
|
|
std::vector<cvm::atom_pos> fit_gradients;
|
|
|
|
/// \brief Used by a (scalar) colvar to apply its force on its \link
|
|
/// atom_group \endlink members
|
|
///
|
|
/// The (scalar) force is multiplied by the colvar gradient for each
|
|
/// atom; this should be used when a colvar with scalar \link
|
|
/// colvarvalue \endlink type is used (this is the most frequent
|
|
/// case: for colvars with a non-scalar type, the most convenient
|
|
/// solution is to sum together the Cartesian forces from all the
|
|
/// colvar components, and use apply_force() or apply_forces()). If
|
|
/// the group is being rotated to a reference frame (e.g. to express
|
|
/// the colvar independently from the solute rotation), the
|
|
/// gradients are temporarily rotated to the original frame.
|
|
void apply_colvar_force (cvm::real const &force);
|
|
|
|
/// \brief Apply a force "to the center of mass", i.e. the force is
|
|
/// distributed on each atom according to its mass
|
|
///
|
|
/// If the group is being rotated to a reference frame (e.g. to
|
|
/// express the colvar independently from the solute rotation), the
|
|
/// force is 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 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);
|
|
|
|
};
|
|
|
|
|
|
#endif
|