1 // -*- c++ -*- 2 3 #ifndef COLVARATOMS_H 4 #define COLVARATOMS_H 5 6 #include "colvarmodule.h" 7 #include "colvarparse.h" 8 9 /// \brief Stores numeric id, mass and all mutable data for an atom, 10 /// mostly used by a \link cvc \endlink 11 /// 12 /// This class may be used (although not necessarily) to keep atomic 13 /// data (id, mass, position and collective variable derivatives) 14 /// altogether. There may be multiple instances with identical 15 /// numeric id, all acting independently: forces communicated through 16 /// these instances will be summed together. 17 /// 18 /// Read/write operations depend on the underlying code: hence, some 19 /// member functions are defined in colvarproxy_xxx.h. 20 class colvarmodule::atom { 21 22 protected: 23 24 /// \brief Index in the list of atoms involved by the colvars (\b 25 /// NOT in the global topology!) 26 int index; 27 28 public: 29 30 /// Internal identifier (zero-based) 31 int id; 32 33 /// Mass 34 cvm::real mass; 35 36 /// \brief Current position (copied from the program, can be 37 /// manipulated) 38 cvm::atom_pos pos; 39 40 /// \brief Current velocity (copied from the program, can be 41 /// manipulated) 42 cvm::rvector vel; 43 44 /// \brief System force at the previous step (copied from the 45 /// program, can be manipulated) 46 cvm::rvector system_force; 47 48 /// \brief Gradient of a scalar collective variable with respect 49 /// to this atom 50 /// 51 /// This can only handle a scalar collective variable (i.e. when 52 /// the \link colvarvalue::real_value \endlink member is used 53 /// from the \link colvarvalue \endlink class), which is also the 54 /// most frequent case. For more complex types of \link 55 /// colvarvalue \endlink objects, atomic gradients should be 56 /// defined within the specific \link cvc \endlink 57 /// implementation 58 cvm::rvector grad; 59 60 /// \brief Default constructor, setting id and index to invalid numbers atom()61 atom() : id (-1), index (-1) { reset_data(); } 62 63 /// \brief Initialize an atom for collective variable calculation 64 /// and get its internal identifier \param atom_number Atom index in 65 /// the system topology (starting from 1) 66 atom (int const &atom_number); 67 68 /// \brief Initialize an atom for collective variable calculation 69 /// and get its internal identifier \param residue Residue number 70 /// \param atom_name Name of the atom in the residue \param 71 /// segment_id For PSF topologies, the segment identifier; for other 72 /// type of topologies, may not be required 73 atom (cvm::residue_id const &residue, 74 std::string const &atom_name, 75 std::string const &segment_id = std::string ("")); 76 77 /// Copy constructor 78 atom (atom const &a); 79 80 /// Destructor 81 ~atom(); 82 83 /// Set non-constant data (everything except id and mass) to zero reset_data()84 inline void reset_data() { 85 pos = atom_pos (0.0); 86 vel = grad = system_force = rvector (0.0); 87 } 88 89 /// Get the current position 90 void read_position(); 91 92 /// Get the current velocity 93 void read_velocity(); 94 95 /// Get the system force 96 void read_system_force(); 97 98 /// \brief Apply a force to the atom 99 /// 100 /// The force will be used later by the MD integrator, the 101 /// collective variables module does not integrate equations of 102 /// motion. Multiple calls to this function by either the same 103 /// \link atom \endlink object or different objects with identical 104 /// \link id \endlink, will all add to the existing MD force. 105 void apply_force (cvm::rvector const &new_force); 106 }; 107 108 109 110 111 /// \brief Group of \link atom \endlink objects, mostly used by a 112 /// \link cvc \endlink 113 /// 114 /// This class inherits from \link colvarparse \endlink and from 115 /// std::vector<colvarmodule::atom>, and hence all functions and 116 /// operators (including the bracket operator, group[i]) can be used 117 /// on an \link atom_group \endlink object. It can be initialized as 118 /// a vector, or by parsing a keyword in the configuration. 119 class colvarmodule::atom_group 120 : public std::vector<cvm::atom>, 121 public colvarparse 122 { 123 public: 124 // Note: all members here are kept public, to allow any 125 // object accessing and manipulating them 126 127 128 /// \brief If this option is on, this group merely acts as a wrapper 129 /// for a fixed position; any calls to atoms within or to 130 /// functions that return disaggregated data will fail 131 bool b_dummy; 132 /// \brief dummy atom position 133 cvm::atom_pos dummy_atom_pos; 134 135 /// Sorted list of zero-based (internal) atom ids 136 /// (populated on-demand by create_sorted_ids) 137 std::vector<int> sorted_ids; 138 139 /// Allocates and populates the sorted list of atom ids 140 void create_sorted_ids (void); 141 142 143 /// \brief When updating atomic coordinates, translate them to align with the 144 /// center of mass of the reference coordinates 145 bool b_center; 146 147 /// \brief When updating atom coordinates (and after 148 /// centering them if b_center is set), rotate the group to 149 /// align with the reference coordinates. 150 /// 151 /// Note: gradients will be calculated in the rotated frame: when 152 /// forces will be applied, they will rotated back to the original 153 /// frame 154 bool b_rotate; 155 /// The rotation calculated automatically if b_rotate is defined 156 cvm::rotation rot; 157 158 /// \brief Indicates that the user has explicitly set centerReference or 159 /// rotateReference, and the corresponding reference: 160 /// cvc's (eg rmsd, eigenvector) will not override the user's choice 161 bool b_user_defined_fit; 162 163 /// \brief Whether or not the derivatives of the roto-translation 164 /// should be included when calculating the colvar's gradients (default: no) 165 bool b_fit_gradients; 166 167 /// \brief use reference coordinates for b_center or b_rotate 168 std::vector<cvm::atom_pos> ref_pos; 169 170 /// \brief Center of geometry of the reference coordinates; regardless 171 /// of whether b_center is true, ref_pos is centered to zero at 172 /// initialization, and ref_pos_cog serves to center the positions 173 cvm::atom_pos ref_pos_cog; 174 175 /// \brief If b_center or b_rotate is true, use this group to 176 /// define the transformation (default: this group itself) 177 atom_group *ref_pos_group; 178 179 /// Total mass of the atom group 180 cvm::real total_mass; 181 182 /// \brief Don't apply any force on this group (use its coordinates 183 /// only to calculate a colvar) 184 bool noforce; 185 186 187 /// \brief Initialize the group by looking up its configuration 188 /// string in conf and parsing it; this is actually done by parse(), 189 /// which is a member function so that a group can be initialized 190 /// also after construction 191 atom_group (std::string const &conf, 192 char const *key); 193 194 /// \brief Initialize the group by looking up its configuration 195 /// string in conf and parsing it 196 void parse (std::string const &conf, 197 char const *key); 198 199 /// \brief Initialize the group after a temporary vector of atoms 200 atom_group (std::vector<cvm::atom> const &atoms); 201 202 /// \brief Add an atom to this group 203 void add_atom (cvm::atom const &a); 204 205 /// \brief Re-initialize the total mass of a group. 206 /// This is needed in case the hosting MD code has an option to 207 /// change atom masses after their initialization. 208 void reset_mass (std::string &name, int i, int j); 209 210 /// \brief Default constructor 211 atom_group(); 212 213 /// \brief Destructor 214 ~atom_group(); 215 216 /// \brief Get the current positions; if b_center or b_rotate are 217 /// true, calc_apply_roto_translation() will be called too 218 void read_positions(); 219 220 /// \brief (Re)calculate the optimal roto-translation 221 void calc_apply_roto_translation(); 222 223 /// \brief Save center of geometry fo ref positions, 224 /// then subtract it 225 void center_ref_pos(); 226 227 /// \brief Move all positions 228 void apply_translation (cvm::rvector const &t); 229 230 /// \brief Rotate all positions 231 void apply_rotation (cvm::rotation const &q); 232 233 234 /// \brief Get the current velocities; this must be called always 235 /// *after* read_positions(); if b_rotate is defined, the same 236 /// rotation applied to the coordinates will be used 237 void read_velocities(); 238 239 /// \brief Get the current system_forces; this must be called always 240 /// *after* read_positions(); if b_rotate is defined, the same 241 /// rotation applied to the coordinates will be used 242 void read_system_forces(); 243 244 /// Call reset_data() for each atom reset_atoms_data()245 inline void reset_atoms_data() 246 { 247 for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) 248 ai->reset_data(); 249 if (ref_pos_group) 250 ref_pos_group->reset_atoms_data(); 251 } 252 253 /// \brief Return a copy of the current atom positions 254 std::vector<cvm::atom_pos> positions() const; 255 256 /// \brief Return a copy of the current atom positions, shifted by a constant vector 257 std::vector<cvm::atom_pos> positions_shifted (cvm::rvector const &shift) const; 258 259 /// \brief Return the center of geometry of the positions, assuming 260 /// that coordinates are already pbc-wrapped 261 cvm::atom_pos center_of_geometry() const; 262 263 /// \brief Return the center of mass of the positions, assuming that 264 /// coordinates are already pbc-wrapped 265 cvm::atom_pos center_of_mass() const; 266 267 /// \brief Atom positions at the previous step 268 std::vector<cvm::atom_pos> old_pos; 269 270 271 /// \brief Return a copy of the current atom velocities 272 std::vector<cvm::rvector> velocities() const; 273 274 275 /// \brief Return a copy of the system forces 276 std::vector<cvm::rvector> system_forces() const; 277 /// \brief Return a copy of the aggregated total force on the group 278 cvm::rvector system_force() const; 279 280 281 /// \brief Shorthand: save the specified gradient on each atom, 282 /// weighting with the atom mass (mostly used in combination with 283 /// \link center_of_mass() \endlink) 284 void set_weighted_gradient (cvm::rvector const &grad); 285 286 /// \brief Calculate the derivatives of the fitting transformation 287 void calc_fit_gradients(); 288 289 /// \brief Derivatives of the fitting transformation 290 std::vector<cvm::atom_pos> fit_gradients; 291 292 /// \brief Used by a (scalar) colvar to apply its force on its \link 293 /// atom_group \endlink members 294 /// 295 /// The (scalar) force is multiplied by the colvar gradient for each 296 /// atom; this should be used when a colvar with scalar \link 297 /// colvarvalue \endlink type is used (this is the most frequent 298 /// case: for colvars with a non-scalar type, the most convenient 299 /// solution is to sum together the Cartesian forces from all the 300 /// colvar components, and use apply_force() or apply_forces()). If 301 /// the group is being rotated to a reference frame (e.g. to express 302 /// the colvar independently from the solute rotation), the 303 /// gradients are temporarily rotated to the original frame. 304 void apply_colvar_force (cvm::real const &force); 305 306 /// \brief Apply a force "to the center of mass", i.e. the force is 307 /// distributed on each atom according to its mass 308 /// 309 /// If the group is being rotated to a reference frame (e.g. to 310 /// express the colvar independently from the solute rotation), the 311 /// force is rotated back to the original frame. Colvar gradients 312 /// are not used, either because they were not defined (e.g because 313 /// the colvar has not a scalar value) or the biases require to 314 /// micromanage the force. 315 void apply_force (cvm::rvector const &force); 316 317 /// \brief Apply an array of forces directly on the individual 318 /// atoms; the length of the specified vector must be the same of 319 /// this \link atom_group \endlink. 320 /// 321 /// If the group is being rotated to a reference frame (e.g. to 322 /// express the colvar independently from the solute rotation), the 323 /// forces are rotated back to the original frame. Colvar gradients 324 /// are not used, either because they were not defined (e.g because 325 /// the colvar has not a scalar value) or the biases require to 326 /// micromanage the forces. 327 void apply_forces (std::vector<cvm::rvector> const &forces); 328 329 }; 330 331 332 #endif 333