Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

colvaratoms.C

Go to the documentation of this file.
00001 #include "colvarmodule.h"
00002 #include "colvarparse.h"
00003 #include "colvaratoms.h"
00004 
00005 
00006 // atom member functions depend tightly on the MD interface, and are
00007 // thus defined in colvarproxy_xxx.cpp
00008 
00009 
00010 // atom_group member functions
00011 
00012 cvm::atom_group::atom_group (std::string const &conf,
00013                              char const        *key,
00014                              atom_group        *ref_pos_group_in)
00015   : b_center (false), b_rotate (false),
00016     ref_pos_group (NULL), // this is always set within parse(),
00017                           // regardless of ref_pos_group_in
00018     noforce (false)
00019 {
00020   cvm::log ("Defining atom group \""+
00021             std::string (key)+"\".\n");
00022   parse (conf, key, ref_pos_group_in);
00023 }
00024 
00025 
00026 void cvm::atom_group::parse (std::string const &conf,
00027                              char const        *key,
00028                              atom_group        *ref_pos_group_in)
00029 {
00030   std::string group_conf;
00031 
00032   // save_delimiters is set to false for this call, because "conf" is
00033   // not the config string of this group, but of its parent object
00034   // (which has already taken care of the delimiters)
00035   save_delimiters = false;
00036   key_lookup (conf, key, group_conf, dummy_pos);
00037   // restoring the normal value, because we do want keywords checked
00038   // inside "group_conf"
00039   save_delimiters = true;
00040 
00041   if (group_conf.size() == 0) {
00042     cvm::fatal_error ("Error: atom group \""+
00043                       std::string (key)+"\" is set, but "
00044                       "has no definition.\n");
00045   }
00046 
00047   cvm::increase_depth();
00048 
00049   cvm::log ("Initializing atom group \""+std::string (key)+"\".\n");
00050 
00051   // whether or not to include messages in the log
00052   colvarparse::Parse_Mode mode = parse_silent;
00053   {
00054     bool b_verbose;
00055     get_keyval (group_conf, "verboseOutput", b_verbose, false, parse_silent);
00056     if (b_verbose) mode = parse_normal;
00057   }
00058 
00059   {
00060     // get the atoms by numbers
00061     std::vector<int> atom_indexes;
00062     if (get_keyval (group_conf, "atomNumbers", atom_indexes, atom_indexes, mode)) {
00063       if (atom_indexes.size()) {
00064         this->reserve (this->size()+atom_indexes.size());
00065         for (size_t i = 0; i < atom_indexes.size(); i++) {
00066           this->push_back (cvm::atom (atom_indexes[i]));
00067         }
00068       } else
00069         cvm::fatal_error ("Error: no numbers provided for \""
00070                           "atomNumbers\".\n");
00071     }
00072   }
00073 
00074   {
00075     std::string range_conf = "";
00076     size_t pos = 0;
00077     while (key_lookup (group_conf, "atomNumbersRange",
00078                        range_conf, pos)) {
00079 
00080       if (range_conf.size()) {
00081         std::istringstream is (range_conf);
00082         int initial, final;
00083         char dash;
00084         if ( (is >> initial) && (initial > 0) &&
00085              (is >> dash) && (dash == '-') &&
00086              (is >> final) && (final > 0) ) {
00087           for (int anum = initial; anum <= final; anum++) {
00088             this->push_back (cvm::atom (anum));
00089           }
00090           range_conf = "";
00091           continue;
00092         }
00093       }
00094 
00095       cvm::fatal_error ("Error: no valid definition for \""
00096                         "atomNumbersRange\", \""+
00097                         range_conf+"\".\n");
00098     }
00099   }
00100 
00101   std::vector<std::string> psf_segids;
00102   get_keyval (group_conf, "psfSegID", psf_segids, std::vector<std::string> (), mode);
00103   for (std::vector<std::string>::iterator psii = psf_segids.begin();
00104        psii < psf_segids.end(); psii++) {
00105 
00106     if ( (psii->size() == 0) || (psii->size() > 4) ) {
00107       cvm::fatal_error ("Error: invalid segmend identifier provided, \""+
00108                         (*psii)+"\".\n");
00109     }
00110   }
00111 
00112   {
00113     std::string range_conf = "";
00114     size_t pos = 0;
00115     size_t range_count = 0;
00116     std::vector<std::string>::iterator psii = psf_segids.begin();
00117     while (key_lookup (group_conf, "atomNameResidueRange",
00118                        range_conf, pos)) {
00119 
00120       if (psii > psf_segids.end()) {
00121         cvm::fatal_error ("Error: more instances of \"atomNameResidueRange\" than "
00122                           "values of \"psfSegID\".\n");
00123       }
00124 
00125       std::string const &psf_segid = psf_segids.size() ? *psii : std::string ("");
00126 
00127       if (range_conf.size()) {
00128         
00129         std::istringstream is (range_conf);
00130         std::string atom_name;
00131         int initial, final;
00132         char dash;
00133         if ( (is >> atom_name) && (atom_name.size())  &&
00134              (is >> initial) && (initial > 0) &&
00135              (is >> dash) && (dash == '-') &&
00136              (is >> final) && (final > 0) ) {
00137           for (int resid = initial; resid <= final; resid++) {
00138             this->push_back (cvm::atom (resid, atom_name, psf_segid));
00139           }
00140           range_conf = "";
00141         } else {
00142           cvm::fatal_error ("Error: cannot parse definition for \""
00143                             "atomNameResidueRange\", \""+
00144                             range_conf+"\".\n");
00145         }
00146 
00147       } else {
00148         cvm::fatal_error ("Error: atomNameResidueRange with empty definition.\n");
00149       }
00150 
00151       if (psf_segid.size())
00152         psii++;
00153     }
00154   }
00155 
00156   {
00157     // read the atoms from a file
00158     std::string atoms_file_name;
00159     if (get_keyval (group_conf, "atomsFile", atoms_file_name, std::string (""), mode)) {
00160 
00161       std::string atoms_col;
00162       if (!get_keyval (group_conf, "atomsCol", atoms_col, std::string (""), mode)) {
00163         cvm::fatal_error ("Error: parameter atomsCol is required if atomsFile is set.\n");
00164       }
00165 
00166       double atoms_col_value;
00167       bool const atoms_col_value_defined = get_keyval (group_conf, "atomsColValue", atoms_col_value, 0.0, mode);
00168       if (atoms_col_value_defined && (!atoms_col_value))
00169         cvm::fatal_error ("Error: atomsColValue, "
00170                           "if provided, must be non-zero.\n");
00171 
00172       cvm::load_atoms (atoms_file_name.c_str(), *this, atoms_col, atoms_col_value);
00173     }
00174   }
00175 
00176   for (std::vector<cvm::atom>::iterator a1 = this->begin(); 
00177        a1 != this->end(); a1++) {
00178     std::vector<cvm::atom>::iterator a2 = a1;
00179     ++a2;
00180     for ( ; a2 != this->end(); a2++) {
00181       if (a1->id == a2->id) {
00182         if (cvm::debug())
00183           cvm::log ("Discarding doubly counted atom with number "+
00184                     cvm::to_str (a1->id+1)+".\n");
00185         a2 = this->erase (a2);
00186         if (a2 == this->end())
00187           break;
00188       }
00189     }
00190   }
00191 
00192   if (get_keyval (group_conf, "dummyAtom", dummy_atom_pos, cvm::atom_pos(), mode)) {
00193     b_dummy = true;
00194     this->total_mass = 1.0;
00195   } else 
00196     b_dummy = false;
00197 
00198   if (b_dummy && (this->size())) 
00199     cvm::fatal_error ("Error: cannot set up group \""+
00200                       std::string (key)+"\" as a dummy atom "
00201                       "and provide it with atom definitions.\n");
00202 
00203 #if (! defined (COLVARS_STANDALONE))
00204   if ( (!b_dummy) && (!cvm::b_analysis) && (!(this->size())) ) {
00205     cvm::fatal_error ("Error: no atoms defined for atom group \""+
00206                       std::string (key)+"\".\n");
00207   }
00208 #endif
00209 
00210   if (!b_dummy) {
00211     this->total_mass = 0.0;
00212     for (cvm::atom_iter ai = this->begin();
00213          ai != this->end(); ai++) {
00214       this->total_mass += ai->mass;
00215     }
00216   }
00217 
00218   get_keyval (group_conf, "disableForces",   noforce,  false, mode);
00219 
00220   get_keyval (group_conf, "centerReference", b_center, false, mode);
00221   get_keyval (group_conf, "rotateReference", b_rotate, false, mode);
00222 
00223   if (b_center || b_rotate) {
00224 
00225     if (b_dummy)
00226       cvm::fatal_error ("Error: cannot set \"centerReference\" or "
00227                         "\"rotateReference\" with \"dummyAtom\".\n");
00228 
00229     // use refPositionsGroup instead of this group as the one which is
00230     // used to fit the coordinates
00231     if (key_lookup (group_conf, "refPositionsGroup")) {
00232       if (ref_pos_group) {
00233         cvm::fatal_error ("Error: the atom group \""+
00234                           std::string (key)+"\" has already a reference group "
00235                           "for the rototranslational fit, which was communicated by the "
00236                           "colvar component.  You should not use refPositionsGroup "
00237                           "in this case.\n");
00238       }
00239       cvm::log ("Within atom group \""+std::string (key)+"\":\n");
00240       ref_pos_group = new atom_group (group_conf, "refPositionsGroup");
00241     }
00242 
00243     atom_group *ag = ref_pos_group ? ref_pos_group : this;
00244 
00245     if (get_keyval (group_conf, "refPositions", ref_pos, ref_pos, mode)) {
00246       cvm::log ("Using reference positions from input file.\n");
00247       if (ref_pos.size() != ag->size()) {
00248         cvm::fatal_error ("Error: the number of reference positions provided ("+
00249                           cvm::to_str (ref_pos.size())+
00250                           ") does not match the number of atoms within \""+
00251                           std::string (key)+
00252                           "\" ("+cvm::to_str (ag->size())+").\n");
00253       }
00254     }
00255 
00256     std::string ref_pos_file;
00257     if (get_keyval (group_conf, "refPositionsFile", ref_pos_file, std::string (""), mode)) {
00258 
00259       if (ref_pos.size()) {
00260         cvm::fatal_error ("Error: cannot specify \"refPositionsFile\" and "
00261                           "\"refPositions\" at the same time.\n");
00262       }
00263 
00264       std::string ref_pos_col;
00265       double ref_pos_col_value;
00266       
00267       if (get_keyval (group_conf, "refPositionsCol", ref_pos_col, std::string (""), mode)) {
00268         // if provided, use PDB column to select coordinates
00269         bool found = get_keyval (group_conf, "refPositionsColValue", ref_pos_col_value, 0.0, mode);
00270         if (found && !ref_pos_col_value)
00271           cvm::fatal_error ("Error: refPositionsColValue, "
00272                             "if provided, must be non-zero.\n");
00273       } else {
00274         // if not, rely on existing atom indices for the group
00275         ag->create_sorted_ids();
00276       }
00277       cvm::load_coords (ref_pos_file.c_str(), ref_pos, ag->sorted_ids,
00278                         ref_pos_col, ref_pos_col_value);
00279     }
00280 
00281     if (ref_pos.size()) {
00282 
00283       if (b_rotate) {
00284         if (ref_pos.size() != ag->size())
00285           cvm::fatal_error ("Error: the number of reference positions provided ("+
00286                             cvm::to_str (ref_pos.size())+
00287                             ") does not match the number of atoms within \""+
00288                             std::string (key)+
00289                             "\" ("+cvm::to_str (ag->size())+").\n");
00290       }
00291 
00292       // save the center of mass of ref_pos and then subtract it from
00293       // them; in this way it is possible to use the coordinates for
00294       // the rotational fit, if needed
00295       ref_pos_cog = cvm::atom_pos (0.0, 0.0, 0.0);
00296       std::vector<cvm::atom_pos>::iterator pi = ref_pos.begin();
00297       for ( ; pi != ref_pos.end(); pi++) {
00298         ref_pos_cog += *pi;
00299       }
00300       ref_pos_cog /= (cvm::real) ref_pos.size();
00301 
00302       for (std::vector<cvm::atom_pos>::iterator pi = ref_pos.begin();
00303            pi != ref_pos.end(); pi++) {
00304         (*pi) -= ref_pos_cog;
00305       }
00306     } else {
00307 #if (! defined (COLVARS_STANDALONE))
00308       if (!cvm::b_analysis)
00309         cvm::fatal_error ("Error: no reference positions provided.\n");
00310 #endif
00311     }
00312 
00313     if (b_rotate && !noforce) {
00314       cvm::log ("Warning: atom group \""+std::string (key)+
00315                 "\" is set to be rotated to a reference orientation: "
00316                 "a torque different than zero on this group "
00317                 "could make the simulation unstable.  "
00318                 "If this happens, set \"disableForces\" to yes "
00319                 "for this group.\n");
00320     }
00321 
00322   }
00323 
00324 
00325   if (cvm::debug())
00326     cvm::log ("Done initializing atom group with name \""+
00327               std::string (key)+"\".\n");
00328 
00329   this->check_keywords (group_conf, key);
00330 
00331   cvm::log ("Atom group \""+std::string (key)+"\" defined, "+
00332             cvm::to_str (this->size())+" initialized: total mass = "+
00333             cvm::to_str (this->total_mass)+".\n");
00334 
00335   cvm::decrease_depth();
00336 }
00337 
00338 
00339 cvm::atom_group::atom_group (std::vector<cvm::atom> const &atoms)
00340   : b_dummy (false), b_center (false), b_rotate (false), 
00341     ref_pos_group (NULL), noforce (false)
00342 {
00343   this->reserve (atoms.size());
00344   for (size_t i = 0; i < atoms.size(); i++) {
00345     this->push_back (atoms[i]);
00346   }
00347   total_mass = 0.0;
00348   for (cvm::atom_iter ai = this->begin();
00349        ai != this->end(); ai++) {
00350     total_mass += ai->mass;
00351   }
00352 }
00353 
00354 
00355 cvm::atom_group::atom_group()
00356   : b_dummy (false), b_center (false), b_rotate (false), 
00357     ref_pos_group (NULL), noforce (false)
00358 {
00359   total_mass = 0.0;
00360 }
00361 
00362 
00363 cvm::atom_group::~atom_group()
00364 {
00365   if (ref_pos_group) {
00366     delete ref_pos_group;
00367     ref_pos_group = NULL;
00368   }
00369 }
00370 
00371 
00372 void cvm::atom_group::add_atom (cvm::atom const &a)
00373 {
00374   if (b_dummy) {
00375     cvm::fatal_error ("Error: cannot add atoms to a dummy group.\n");
00376   } else {
00377     this->push_back (a);
00378     total_mass += a.mass;
00379   }
00380 }
00381 
00382 
00383 void cvm::atom_group::create_sorted_ids (void)
00384 {
00385   // Only do the work if the vector is not yet populated
00386   if (sorted_ids.size())
00387     return;
00388 
00389   std::list<int> temp_id_list;
00390   for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) {
00391     temp_id_list.push_back (ai->id);
00392   }
00393   temp_id_list.sort();
00394   temp_id_list.unique();
00395   if (temp_id_list.size() != this->size()) {
00396     cvm::fatal_error ("Error: duplicate atom IDs in atom group? (found " +
00397                       cvm::to_str(temp_id_list.size()) +
00398                       " unique atom IDs instead of" +
00399                       cvm::to_str(this->size()) + ").\n");
00400   }
00401   sorted_ids = std::vector<int> (temp_id_list.begin(), temp_id_list.end());
00402   return;
00403 }
00404 
00405 
00406 void cvm::atom_group::read_positions()
00407 {
00408   if (b_dummy) return;
00409 
00410 #if (! defined (COLVARS_STANDALONE))
00411   if (!this->size())
00412     cvm::fatal_error ("Error: no atoms defined in the requested group.\n");
00413 #endif
00414 
00415   for (cvm::atom_iter ai = this->begin();
00416        ai != this->end(); ai++) {
00417     ai->read_position();
00418   }
00419 
00420   if (ref_pos_group)
00421     ref_pos_group->read_positions();
00422 
00423   atom_group *fit_group = ref_pos_group ? ref_pos_group : this;
00424 
00425   if (b_center) {
00426     // store aside the current center of geometry (all positions will be
00427     // set to the closest images to the first one) and then center on
00428     // the origin
00429     cvm::atom_pos const cog = fit_group->center_of_geometry();
00430     for (cvm::atom_iter ai = this->begin();
00431          ai != this->end(); ai++) {
00432       ai->pos -= cog;
00433     }
00434   }
00435 
00436   if (b_rotate) {
00437     // rotate the group (around the center of geometry if b_center is
00438     // true, around the origin otherwise); store the rotation, in
00439     // order to bring back the forces to the original frame before
00440     // applying them
00441     rot.calc_optimal_rotation (fit_group->positions(), ref_pos);
00442 
00443     for (cvm::atom_iter ai = this->begin();
00444          ai != this->end(); ai++) {
00445       ai->pos = rot.rotate (ai->pos);
00446     }
00447   }
00448 
00449   if (b_center) {
00450     // use the center of geometry of ref_pos
00451     for (cvm::atom_iter ai = this->begin();
00452          ai != this->end(); ai++) {
00453       ai->pos += ref_pos_cog;
00454     }
00455   }
00456 }
00457 
00458 
00459 void cvm::atom_group::apply_translation (cvm::rvector const &t) 
00460 {
00461   if (b_dummy) return;
00462 
00463   for (cvm::atom_iter ai = this->begin();
00464        ai != this->end(); ai++) {
00465     ai->pos += t;
00466   }
00467 }
00468 
00469 
00470 void cvm::atom_group::apply_rotation (cvm::rotation const &rot) 
00471 {
00472   if (b_dummy) return;
00473 
00474   for (cvm::atom_iter ai = this->begin();
00475        ai != this->end(); ai++) {
00476     ai->pos = rot.rotate (ai->pos);
00477   }
00478 }
00479 
00480 
00481 void cvm::atom_group::read_velocities()
00482 {
00483   if (b_dummy) return;
00484 
00485   if (b_rotate) {
00486 
00487     for (cvm::atom_iter ai = this->begin();
00488          ai != this->end(); ai++) {
00489       ai->read_velocity();
00490       ai->vel = rot.rotate (ai->vel);
00491     }
00492 
00493   } else {
00494 
00495     for (cvm::atom_iter ai = this->begin();
00496          ai != this->end(); ai++) {
00497       ai->read_velocity();
00498     }
00499   }
00500 }
00501 
00502 void cvm::atom_group::read_system_forces()
00503 {
00504   if (b_dummy) return;
00505 
00506   if (b_rotate) {
00507 
00508     for (cvm::atom_iter ai = this->begin();
00509          ai != this->end(); ai++) {
00510       ai->read_system_force();
00511       ai->system_force = rot.rotate (ai->system_force);
00512     }
00513 
00514   } else {
00515 
00516     for (cvm::atom_iter ai = this->begin();
00517          ai != this->end(); ai++) {
00518       ai->read_system_force();
00519     }
00520   }
00521 }
00522 
00523 cvm::atom_pos cvm::atom_group::center_of_geometry (cvm::atom_pos const &ref_pos)
00524 {
00525   if (b_dummy) {
00526     cvm::select_closest_image (dummy_atom_pos, ref_pos);
00527     return dummy_atom_pos;
00528   }
00529 
00530   cvm::atom_pos cog (0.0, 0.0, 0.0);
00531   for (cvm::atom_iter ai = this->begin();
00532        ai != this->end(); ai++) {
00533     cvm::select_closest_image (ai->pos, ref_pos);
00534     cog += ai->pos;
00535   }
00536   cog /= this->size();
00537   return cog;
00538 }
00539 
00540 cvm::atom_pos cvm::atom_group::center_of_geometry() const
00541 {
00542   if (b_dummy)
00543     return dummy_atom_pos;
00544 
00545   cvm::atom_pos cog (0.0, 0.0, 0.0);
00546   for (cvm::atom_const_iter ai = this->begin();
00547        ai != this->end(); ai++) {
00548     cog += ai->pos;
00549   }
00550   cog /= this->size();
00551   return cog;
00552 }
00553 
00554 cvm::atom_pos cvm::atom_group::center_of_mass (cvm::atom_pos const &ref_pos)
00555 {
00556   if (b_dummy) {
00557     cvm::select_closest_image (dummy_atom_pos, ref_pos);
00558     return dummy_atom_pos;
00559   }
00560 
00561   cvm::atom_pos com (0.0, 0.0, 0.0);
00562   for (cvm::atom_iter ai = this->begin();
00563        ai != this->end(); ai++) {
00564     cvm::select_closest_image (ai->pos, ref_pos);
00565     com += ai->mass * ai->pos;
00566   }
00567   com /= this->total_mass;
00568   return com;
00569 }
00570 
00571 cvm::atom_pos cvm::atom_group::center_of_mass() const
00572 {
00573   if (b_dummy)
00574     return dummy_atom_pos;
00575 
00576   cvm::atom_pos com (0.0, 0.0, 0.0);
00577   for (cvm::atom_const_iter ai = this->begin();
00578        ai != this->end(); ai++) {
00579     com += ai->mass * ai->pos;
00580   }
00581   com /= this->total_mass;
00582   return com;
00583 }
00584 
00585 
00586 void cvm::atom_group::set_weighted_gradient (cvm::rvector const &grad)
00587 {
00588   if (b_dummy) return;
00589 
00590   for (cvm::atom_iter ai = this->begin();
00591        ai != this->end(); ai++) {
00592     ai->grad = (ai->mass/this->total_mass) * grad;
00593   }
00594 }
00595 
00596 
00597 std::vector<cvm::atom_pos> cvm::atom_group::positions() const
00598 {
00599   if (b_dummy)
00600     cvm::fatal_error ("Error: positions are not available "
00601                       "from a dummy atom group.\n");
00602 
00603   std::vector<cvm::atom_pos> x (this->size(), 0.0);
00604   cvm::atom_const_iter ai = this->begin();
00605   std::vector<cvm::atom_pos>::iterator xi = x.begin();
00606   for ( ; ai != this->end(); xi++, ai++) {
00607     *xi = ai->pos;
00608   }
00609   return x;
00610 }
00611 
00612 std::vector<cvm::atom_pos> cvm::atom_group::positions_shifted (cvm::rvector const &shift) const
00613 {
00614   if (b_dummy)
00615     cvm::fatal_error ("Error: positions are not available "
00616                       "from a dummy atom group.\n");
00617 
00618   std::vector<cvm::atom_pos> x (this->size(), 0.0);
00619   cvm::atom_const_iter ai = this->begin();
00620   std::vector<cvm::atom_pos>::iterator xi = x.begin();
00621   for ( ; ai != this->end(); xi++, ai++) {
00622     *xi = (ai->pos + shift);
00623   }
00624   return x;
00625 }
00626 
00627 std::vector<cvm::rvector> cvm::atom_group::velocities() const
00628 {
00629   if (b_dummy)
00630     cvm::fatal_error ("Error: velocities are not available "
00631                       "from a dummy atom group.\n");
00632 
00633   std::vector<cvm::rvector> v (this->size(), 0.0);
00634   cvm::atom_const_iter ai = this->begin();
00635   std::vector<cvm::atom_pos>::iterator vi = v.begin();
00636   for ( ; ai != this->end(); vi++, ai++) {
00637     *vi = ai->vel;
00638   }
00639   return v;
00640 }
00641 
00642 std::vector<cvm::rvector> cvm::atom_group::system_forces() const
00643 {
00644   if (b_dummy)
00645     cvm::fatal_error ("Error: system forces are not available "
00646                       "from a dummy atom group.\n");
00647 
00648   std::vector<cvm::rvector> f (this->size(), 0.0);
00649   cvm::atom_const_iter ai = this->begin();
00650   std::vector<cvm::atom_pos>::iterator fi = f.begin();
00651   for ( ; ai != this->end(); fi++, ai++) {
00652     *fi = ai->system_force;
00653   }
00654   return f;
00655 }
00656 
00657 cvm::rvector cvm::atom_group::system_force() const
00658 {
00659   if (b_dummy)
00660     cvm::fatal_error ("Error: system forces are not available "
00661                       "from a dummy atom group.\n");
00662 
00663   cvm::rvector f (0.0);
00664   for (cvm::atom_const_iter ai = this->begin(); ai != this->end(); ai++) {
00665     f += ai->system_force;
00666   }
00667   return f;
00668 }
00669 
00670 
00671 void cvm::atom_group::apply_colvar_force (cvm::real const &force)
00672 {
00673   if (b_dummy)
00674     return;
00675 
00676   if (noforce)
00677     cvm::fatal_error ("Error: sending a force to a group that has "
00678                       "\"disableForces\" defined.\n");
00679 
00680   if (b_rotate) {
00681 
00682     // get the forces back from the rotated frame
00683     cvm::rotation const rot_inv = rot.inverse();
00684     for (cvm::atom_iter ai = this->begin();
00685          ai != this->end(); ai++) {
00686       ai->apply_force (rot_inv.rotate (force * ai->grad));
00687     }
00688 
00689   } else {
00690 
00691     // no need to manipulate gradients, they are still in the original
00692     // frame
00693     for (cvm::atom_iter ai = this->begin();
00694          ai != this->end(); ai++) {
00695       ai->apply_force (force * ai->grad);
00696     }
00697   }
00698 }
00699 
00700 
00701 void cvm::atom_group::apply_force (cvm::rvector const &force)
00702 {
00703   if (b_dummy)
00704     return;
00705 
00706   if (noforce)
00707     cvm::fatal_error ("Error: sending a force to a group that has "
00708                       "\"disableForces\" defined.\n");
00709 
00710   if (b_rotate) {
00711 
00712     cvm::rotation const rot_inv = rot.inverse();
00713     for (cvm::atom_iter ai = this->begin();
00714          ai != this->end(); ai++) {
00715       ai->apply_force (rot_inv.rotate ((ai->mass/this->total_mass) * force));
00716     }
00717 
00718   } else {
00719 
00720     for (cvm::atom_iter ai = this->begin();
00721          ai != this->end(); ai++) {
00722       ai->apply_force ((ai->mass/this->total_mass) * force);
00723     } 
00724   }
00725 }
00726 
00727 
00728 void cvm::atom_group::apply_forces (std::vector<cvm::rvector> const &forces)
00729 {
00730   if (b_dummy)
00731     return;
00732 
00733   if (noforce)
00734     cvm::fatal_error ("Error: sending a force to a group that has "
00735                       "\"disableForces\" defined.\n");
00736 
00737   if (forces.size() != this->size()) {
00738     cvm::fatal_error ("Error: trying to apply an array of forces to an atom "
00739                       "group which does not have the same length.\n");
00740   }
00741 
00742   if (b_rotate) {
00743 
00744     cvm::rotation const rot_inv = rot.inverse();
00745     cvm::atom_iter ai = this->begin();
00746     std::vector<cvm::rvector>::const_iterator fi = forces.begin();
00747     for ( ; ai != this->end(); fi++, ai++) {
00748       ai->apply_force (rot_inv.rotate (*fi));
00749     }
00750 
00751   } else {
00752 
00753     cvm::atom_iter ai = this->begin();
00754     std::vector<cvm::rvector>::const_iterator fi = forces.begin();
00755     for ( ; ai != this->end(); fi++, ai++) {
00756       ai->apply_force (*fi);
00757     }
00758   }
00759 }
00760 
00761 

Generated on Fri May 25 04:07:13 2012 for NAMD by  doxygen 1.3.9.1