00001 #include "colvarmodule.h"
00002 #include "colvarparse.h"
00003 #include "colvaratoms.h"
00004
00005
00006
00007
00008
00009
00010
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),
00017
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
00033
00034
00035 save_delimiters = false;
00036 key_lookup (conf, key, group_conf, dummy_pos);
00037
00038
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
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
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
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
00230
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
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
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
00293
00294
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
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
00427
00428
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
00438
00439
00440
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
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
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
00692
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