00001
00002
00003 #include "colvarmodule.h"
00004 #include "colvarvalue.h"
00005 #include "colvarparse.h"
00006 #include "colvar.h"
00007 #include "colvarcomp.h"
00008 #include <algorithm>
00009
00010
00011
00012
00013
00014 colvar::colvar (std::string const &conf)
00015 {
00016 cvm::log ("Initializing a new collective variable.\n");
00017
00018 get_keyval (conf, "name", this->name,
00019 (std::string ("colvar")+cvm::to_str (cvm::colvars.size()+1)));
00020
00021 for (std::vector<colvar *>::iterator cvi = cvm::colvars.begin();
00022 cvi < cvm::colvars.end();
00023 cvi++) {
00024 if ((*cvi)->name == this->name)
00025 cvm::fatal_error ("Error: this colvar has the same name, \""+this->name+
00026 "\", as another colvar.\n");
00027 }
00028
00029
00030 for (size_t i = 0; i < task_ntot; i++) {
00031 tasks[i] = false;
00032 }
00033
00034 kinetic_energy = 0.0;
00035 potential_energy = 0.0;
00036
00037
00038
00039 #define initialize_components(def_desc,def_config_key,def_class_name) \
00040 { \
00041 size_t def_count = 0; \
00042 std::string def_conf = ""; \
00043 size_t pos = 0; \
00044 while ( this->key_lookup (conf, \
00045 def_config_key, \
00046 def_conf, \
00047 pos) ) { \
00048 if (!def_conf.size()) continue; \
00049 cvm::log ("Initializing " \
00050 "a new \""+std::string (def_config_key)+"\" component"+ \
00051 (cvm::debug() ? ", with configuration:\n"+def_conf \
00052 : ".\n")); \
00053 cvm::increase_depth(); \
00054 cvc *cvcp = new colvar::def_class_name (def_conf); \
00055 if (cvcp != NULL) { \
00056 cvcs.push_back (cvcp); \
00057 cvcp->check_keywords (def_conf, def_config_key); \
00058 cvm::decrease_depth(); \
00059 } else { \
00060 cvm::fatal_error ("Error: in allocating component \"" \
00061 def_config_key"\".\n"); \
00062 } \
00063 if ( (cvcp->period != 0.0) || (cvcp->wrap_center != 0.0) ) { \
00064 if ( (cvcp->function_type != std::string ("distance_z")) && \
00065 (cvcp->function_type != std::string ("dihedral")) && \
00066 (cvcp->function_type != std::string ("spin_angle")) ) { \
00067 cvm::fatal_error ("Error: invalid use of period and/or " \
00068 "wrapAround in a \""+ \
00069 std::string (def_config_key)+ \
00070 "\" component.\n"+ \
00071 "Period: "+cvm::to_str(cvcp->period) + \
00072 " wrapAround: "+cvm::to_str(cvcp->wrap_center));\
00073 } \
00074 } \
00075 if ( ! cvcs.back()->name.size()) \
00076 cvcs.back()->name = std::string (def_config_key)+ \
00077 (cvm::to_str (++def_count)); \
00078 if (cvm::debug()) \
00079 cvm::log ("Done initializing a \""+ \
00080 std::string (def_config_key)+ \
00081 "\" component"+ \
00082 (cvm::debug() ? \
00083 ", named \""+cvcs.back()->name+"\"" \
00084 : "")+".\n"); \
00085 def_conf = ""; \
00086 if (cvm::debug()) \
00087 cvm::log ("Parsed "+cvm::to_str (cvcs.size())+ \
00088 " components at this time.\n"); \
00089 } \
00090 }
00091
00092
00093 initialize_components ("distance", "distance", distance);
00094 initialize_components ("distance vector", "distanceVec", distance_vec);
00095 initialize_components ("distance vector "
00096 "direction", "distanceDir", distance_dir);
00097 initialize_components ("distance projection "
00098 "on an axis", "distanceZ", distance_z);
00099 initialize_components ("distance projection "
00100 "on a plane", "distanceXY", distance_xy);
00101 initialize_components ("minimum distance", "minDistance", min_distance);
00102
00103 initialize_components ("coordination "
00104 "number", "coordNum", coordnum);
00105 initialize_components ("self-coordination "
00106 "number", "selfCoordNum", selfcoordnum);
00107
00108 initialize_components ("angle", "angle", angle);
00109 initialize_components ("dihedral", "dihedral", dihedral);
00110
00111 initialize_components ("hydrogen bond", "hBond", h_bond);
00112
00113
00114 initialize_components ("alpha helix", "alpha", alpha_angles);
00115
00116 initialize_components ("dihedral principal "
00117 "component", "dihedralPC", dihedPC);
00118
00119 initialize_components ("orientation", "orientation", orientation);
00120 initialize_components ("orientation "
00121 "angle", "orientationAngle",orientation_angle);
00122 initialize_components ("tilt", "tilt", tilt);
00123 initialize_components ("spin angle", "spinAngle", spin_angle);
00124
00125 initialize_components ("RMSD", "rmsd", rmsd);
00126
00127
00128
00129 initialize_components ("radius of "
00130 "gyration", "gyration", gyration);
00131 initialize_components ("eigenvector", "eigenvector", eigenvector);
00132
00133 if (!cvcs.size())
00134 cvm::fatal_error ("Error: no valid components were provided "
00135 "for this collective variable.\n");
00136
00137 cvm::log ("All components initialized.\n");
00138
00139
00140
00141
00142 b_linear = true;
00143
00144
00145 b_inverse_gradients = true;
00146 b_Jacobian_force = true;
00147
00148
00149
00150 if (cvcs.size() == 1 && (cvcs[0])->b_periodic && (cvcs[0])->sup_np == 1
00151 && (cvcs[0])->sup_coeff == 1.0 ) {
00152 this->b_periodic = true;
00153 this->period = (cvcs[0])->period;
00154
00155
00156
00157 } else {
00158 this->b_periodic = false;
00159 this->period = 0.0;
00160 }
00161
00162
00163 for (size_t i = 0; i < cvcs.size(); i++) {
00164
00165 if ((cvcs[i])->sup_np != 1) {
00166 if (cvm::debug() && b_linear)
00167 cvm::log ("Warning: You are using a non-linear polynomial "
00168 "combination to define this collective variable, "
00169 "some biasing methods may be unavailable.\n");
00170 b_linear = false;
00171
00172 if ((cvcs[i])->sup_np < 0) {
00173 cvm::log ("Warning: you chose a negative exponent in the combination; "
00174 "if you apply forces, the simulation may become unstable "
00175 "when the component \""+
00176 (cvcs[i])->function_type+"\" approaches zero.\n");
00177 }
00178 }
00179
00180 if ((cvcs[i])->b_periodic && !b_periodic) {
00181 cvm::log ("Warning: although this component is periodic, the colvar will "
00182 "not be treated as periodic, either because the exponent is not "
00183 "1, or because multiple components are present. Make sure that "
00184 "you know what you are doing!");
00185 }
00186
00187 if (! (cvcs[i])->b_inverse_gradients)
00188 b_inverse_gradients = false;
00189
00190 if (! (cvcs[i])->b_Jacobian_derivative)
00191 b_Jacobian_force = false;
00192
00193 for (size_t j = i; j < cvcs.size(); j++) {
00194 if ( (cvcs[i])->type() != (cvcs[j])->type() ) {
00195 cvm::fatal_error ("ERROR: you are definining this collective variable "
00196 "by using components of different types, \""+
00197 colvarvalue::type_desc[(cvcs[i])->type()]+
00198 "\" and \""+
00199 colvarvalue::type_desc[(cvcs[j])->type()]+
00200 "\". "
00201 "You must use the same type in order to "
00202 " sum them together.\n");
00203 }
00204 }
00205 }
00206
00207
00208 {
00209 colvarvalue::Type const value_type = (cvcs[0])->type();
00210 if (cvm::debug())
00211 cvm::log ("This collective variable is a "+
00212 colvarvalue::type_desc[value_type]+", corresponding to "+
00213 cvm::to_str (colvarvalue::dof_num[value_type])+
00214 " internal degrees of freedom.\n");
00215 x.type (value_type);
00216 x_reported.type (value_type);
00217 }
00218
00219 get_keyval (conf, "width", width, 1.0);
00220 if (width <= 0.0)
00221 cvm::fatal_error ("Error: \"width\" must be positive.\n");
00222
00223 lower_boundary.type (this->type());
00224 lower_wall.type (this->type());
00225
00226 upper_boundary.type (this->type());
00227 upper_wall.type (this->type());
00228
00229 if (this->type() == colvarvalue::type_scalar) {
00230
00231 if (get_keyval (conf, "lowerBoundary", lower_boundary, lower_boundary)) {
00232 enable (task_lower_boundary);
00233 }
00234
00235 get_keyval (conf, "lowerWallConstant", lower_wall_k, 0.0);
00236 if (lower_wall_k > 0.0) {
00237 get_keyval (conf, "lowerWall", lower_wall, lower_boundary);
00238 enable (task_lower_wall);
00239 }
00240
00241 if (get_keyval (conf, "upperBoundary", upper_boundary, upper_boundary)) {
00242 enable (task_upper_boundary);
00243 }
00244
00245 get_keyval (conf, "upperWallConstant", upper_wall_k, 0.0);
00246 if (upper_wall_k > 0.0) {
00247 get_keyval (conf, "upperWall", upper_wall, upper_boundary);
00248 enable (task_upper_wall);
00249 }
00250 }
00251
00252
00253 if (tasks[task_lower_boundary] && tasks[task_upper_boundary]) {
00254 if (lower_boundary >= upper_boundary) {
00255 cvm::fatal_error ("Error: the upper boundary, "+
00256 cvm::to_str (upper_boundary)+
00257 ", is not higher than the lower boundary, "+
00258 cvm::to_str (lower_boundary)+".\n");
00259 }
00260 }
00261
00262 if (tasks[task_lower_wall] && tasks[task_upper_wall]) {
00263 if (lower_wall >= upper_wall) {
00264 cvm::fatal_error ("Error: the upper wall, "+
00265 cvm::to_str (upper_wall)+
00266 ", is not higher than the lower wall, "+
00267 cvm::to_str (lower_wall)+".\n");
00268 }
00269
00270 if (dist2 (lower_wall, upper_wall) < 1.0E-12) {
00271 cvm::log ("Lower wall and upper wall are equal "
00272 "in the periodic domain of the colvar: disabling walls.\n");
00273 disable (task_lower_wall);
00274 disable (task_upper_wall);
00275 }
00276 }
00277
00278 get_keyval (conf, "expandBoundaries", expand_boundaries, false);
00279 if (expand_boundaries && periodic_boundaries()) {
00280 cvm::fatal_error ("Error: trying to expand boundaries that already "
00281 "cover a whole period of a periodic colvar.\n");
00282 }
00283
00284 {
00285 bool b_extended_lagrangian;
00286 get_keyval (conf, "extendedLagrangian", b_extended_lagrangian, false);
00287
00288 if (b_extended_lagrangian) {
00289 cvm::real temp, tolerance, period;
00290
00291 cvm::log ("Enabling the extended Lagrangian term for colvar \""+
00292 this->name+"\".\n");
00293
00294 enable (task_extended_lagrangian);
00295
00296 xr.type (this->type());
00297 vr.type (this->type());
00298 fr.type (this->type());
00299
00300 const bool found = get_keyval (conf, "extendedTemp", temp, cvm::temperature());
00301 if (temp <= 0.0) {
00302 if (found)
00303 cvm::fatal_error ("Error: \"extendedTemp\" must be positive.\n");
00304 else
00305 cvm::fatal_error ("Error: a positive temperature must be provided, either "
00306 "by enabling a thermostat, or through \"extendedTemp\".\n");
00307 }
00308
00309 get_keyval (conf, "extendedFluctuation", tolerance, 0.2*width);
00310 if (tolerance <= 0.0)
00311 cvm::fatal_error ("Error: \"extendedFluctuation\" must be positive.\n");
00312 ext_force_k = cvm::boltzmann() * temp / (tolerance * tolerance);
00313 cvm::log ("Computed extended system force constant: " + cvm::to_str(ext_force_k) + " kcal/mol/U^2");
00314
00315 get_keyval (conf, "extendedTimeConstant", period, 40.0 * cvm::dt());
00316 if (period <= 0.0)
00317 cvm::fatal_error ("Error: \"extendedTimeConstant\" must be positive.\n");
00318 ext_mass = (cvm::boltzmann() * temp * period * period)
00319 / (4.0 * PI * PI * tolerance * tolerance);
00320 cvm::log ("Computed fictitious mass: " + cvm::to_str(ext_mass) + " kcal/mol/(U/fs)^2 (U: colvar unit)");
00321
00322 {
00323 bool b_output_energy;
00324 get_keyval (conf, "outputEnergy", b_output_energy, false);
00325 if (b_output_energy) {
00326 enable (task_output_energy);
00327 }
00328 }
00329
00330 get_keyval (conf, "extendedLangevinDamping", ext_gamma, 0.0);
00331 if (ext_gamma < 0.0)
00332 cvm::fatal_error ("Error: \"extendedLangevinDamping\" may not be negative.\n");
00333 if (ext_gamma != 0.0) {
00334 enable (task_langevin);
00335 ext_gamma *= 1.0e-3;
00336 ext_sigma = std::sqrt(2.0 * cvm::boltzmann() * temp * ext_gamma * ext_mass / cvm::dt());
00337 }
00338 }
00339 }
00340
00341 {
00342 bool b_output_value;
00343 get_keyval (conf, "outputValue", b_output_value, true);
00344 if (b_output_value) {
00345 enable (task_output_value);
00346 }
00347 }
00348
00349 {
00350 bool b_output_velocity;
00351 get_keyval (conf, "outputVelocity", b_output_velocity, false);
00352 if (b_output_velocity) {
00353 enable (task_output_velocity);
00354 }
00355 }
00356
00357 {
00358 bool b_output_system_force;
00359 get_keyval (conf, "outputSystemForce", b_output_system_force, false);
00360 if (b_output_system_force) {
00361 enable (task_output_system_force);
00362 }
00363 }
00364
00365 {
00366 bool b_output_applied_force;
00367 get_keyval (conf, "outputAppliedForce", b_output_applied_force, false);
00368 if (b_output_applied_force) {
00369 enable (task_output_applied_force);
00370 }
00371 }
00372
00373 if (cvm::b_analysis)
00374 parse_analysis (conf);
00375
00376 if (cvm::debug())
00377 cvm::log ("Done initializing collective variable \""+this->name+"\".\n");
00378 }
00379
00380
00381
00382 void colvar::build_atom_list (void)
00383 {
00384
00385 std::list<int> temp_id_list;
00386
00387 for (size_t i = 0; i < cvcs.size(); i++) {
00388 for (size_t j = 0; j < cvcs[i]->atom_groups.size(); j++) {
00389 for (size_t k = 0; k < cvcs[i]->atom_groups[j]->size(); k++) {
00390 temp_id_list.push_back (cvcs[i]->atom_groups[j]->at(k).id);
00391 }
00392 }
00393 }
00394
00395 temp_id_list.sort();
00396 temp_id_list.unique();
00397 atom_ids = std::vector<int> (temp_id_list.begin(), temp_id_list.end());
00398 temp_id_list.clear();
00399
00400 atomic_gradients.resize (atom_ids.size());
00401 if (atom_ids.size()) {
00402 if (cvm::debug())
00403 cvm::log ("Colvar: created atom list with " + cvm::to_str(atom_ids.size()) + " atoms.\n");
00404 } else {
00405 cvm::log ("Warning: colvar components communicated no atom IDs.\n");
00406 }
00407 }
00408
00409
00410 void colvar::parse_analysis (std::string const &conf)
00411 {
00412
00413
00414
00415
00416
00417 runave_length = 0;
00418 bool b_runave = false;
00419 if (get_keyval (conf, "runAve", b_runave) && b_runave) {
00420
00421 enable (task_runave);
00422
00423 get_keyval (conf, "runAveLength", runave_length, 1000);
00424 get_keyval (conf, "runAveStride", runave_stride, 1);
00425
00426 if ((cvm::restart_out_freq % runave_stride) != 0)
00427 cvm::fatal_error ("Error: runAveStride must be commensurate with the restart frequency.\n");
00428
00429 std::string runave_outfile;
00430 get_keyval (conf, "runAveOutputFile", runave_outfile,
00431 std::string (cvm::output_prefix+"."+
00432 this->name+".runave.traj"));
00433
00434 size_t const this_cv_width = x.output_width (cvm::cv_width);
00435 runave_os.open (runave_outfile.c_str());
00436 runave_os << "# " << cvm::wrap_string ("step", cvm::it_width-2)
00437 << " "
00438 << cvm::wrap_string ("running average", this_cv_width)
00439 << " "
00440 << cvm::wrap_string ("running stddev", this_cv_width)
00441 << "\n";
00442 }
00443
00444 acf_length = 0;
00445 bool b_acf = false;
00446 if (get_keyval (conf, "corrFunc", b_acf) && b_acf) {
00447
00448 enable (task_corrfunc);
00449
00450 std::string acf_colvar_name;
00451 get_keyval (conf, "corrFuncWithColvar", acf_colvar_name, this->name);
00452 if (acf_colvar_name == this->name) {
00453 cvm::log ("Calculating auto-correlation function.\n");
00454 } else {
00455 cvm::log ("Calculating correlation function with \""+
00456 this->name+"\".\n");
00457 }
00458
00459 std::string acf_type_str;
00460 get_keyval (conf, "corrFuncType", acf_type_str, to_lower_cppstr (std::string ("velocity")));
00461 if (acf_type_str == to_lower_cppstr (std::string ("coordinate"))) {
00462 acf_type = acf_coor;
00463 } else if (acf_type_str == to_lower_cppstr (std::string ("velocity"))) {
00464 acf_type = acf_vel;
00465 enable (task_fdiff_velocity);
00466 if (acf_colvar_name.size())
00467 (cvm::colvar_p (acf_colvar_name))->enable (task_fdiff_velocity);
00468 } else if (acf_type_str == to_lower_cppstr (std::string ("coordinate_p2"))) {
00469 acf_type = acf_p2coor;
00470 } else {
00471 cvm::fatal_error ("Unknown type of correlation function, \""+
00472 acf_type_str+"\".\n");
00473 }
00474
00475 get_keyval (conf, "corrFuncOffset", acf_offset, 0);
00476 get_keyval (conf, "corrFuncLength", acf_length, 1000);
00477 get_keyval (conf, "corrFuncStride", acf_stride, 1);
00478
00479 if ((cvm::restart_out_freq % acf_stride) != 0)
00480 cvm::fatal_error ("Error: corrFuncStride must be commensurate with the restart frequency.\n");
00481
00482 get_keyval (conf, "corrFuncNormalize", acf_normalize, true);
00483 get_keyval (conf, "corrFuncOutputFile", acf_outfile,
00484 std::string (cvm::output_prefix+"."+this->name+
00485 ".corrfunc.dat"));
00486 }
00487 }
00488
00489
00490 void colvar::enable (colvar::task const &t)
00491 {
00492 switch (t) {
00493
00494 case task_output_system_force:
00495 enable (task_system_force);
00496 break;
00497
00498 case task_report_Jacobian_force:
00499 enable (task_Jacobian_force);
00500 enable (task_system_force);
00501 if (cvm::debug())
00502 cvm::log ("Adding the Jacobian force to the system force, "
00503 "rather than applying its opposite silently.\n");
00504 break;
00505
00506 case task_Jacobian_force:
00507
00508 if ( !tasks[task_extended_lagrangian] ) {
00509 enable (task_gradients);
00510
00511 if (!b_Jacobian_force)
00512 cvm::fatal_error ("Error: colvar \""+this->name+
00513 "\" does not have Jacobian forces implemented.\n");
00514 if (!b_linear)
00515 cvm::fatal_error ("Error: colvar \""+this->name+
00516 "\" must be defined as a linear combination "
00517 "to calculate the Jacobian force.\n");
00518 if (cvm::debug())
00519 cvm::log ("Enabling calculation of the Jacobian force "
00520 "on this colvar.\n");
00521 }
00522 fj.type (this->type());
00523 break;
00524
00525 case task_system_force:
00526 if (!tasks[task_extended_lagrangian]) {
00527 if (!b_inverse_gradients) {
00528 cvm::fatal_error ("Error: one or more of the components of "
00529 "colvar \""+this->name+
00530 "\" does not support system force calculation.\n");
00531 }
00532 cvm::request_system_force();
00533 }
00534 ft.type (this->type());
00535 ft_reported.type (this->type());
00536 break;
00537
00538 case task_output_applied_force:
00539 case task_lower_wall:
00540 case task_upper_wall:
00541
00542 enable (task_gradients);
00543 break;
00544
00545 case task_fdiff_velocity:
00546 x_old.type (this->type());
00547 v_fdiff.type (this->type());
00548 v_reported.type (this->type());
00549 break;
00550
00551 case task_output_velocity:
00552 enable (task_fdiff_velocity);
00553 break;
00554
00555 case task_grid:
00556 if (this->type() != colvarvalue::type_scalar)
00557 cvm::fatal_error ("Cannot calculate a grid for collective variable, \""+
00558 this->name+"\", because its value is not a scalar number.\n");
00559 break;
00560
00561 case task_extended_lagrangian:
00562 enable (task_gradients);
00563 v_reported.type (this->type());
00564 break;
00565
00566 case task_lower_boundary:
00567 case task_upper_boundary:
00568 if (this->type() != colvarvalue::type_scalar) {
00569 cvm::fatal_error ("Error: this colvar is not a scalar value "
00570 "and cannot produce a grid.\n");
00571 }
00572 break;
00573
00574
00575 case task_output_value:
00576 case task_runave:
00577 case task_corrfunc:
00578 case task_ntot:
00579 break;
00580
00581 case task_gradients:
00582 f.type (this->type());
00583 fb.type (this->type());
00584 break;
00585
00586 case task_collect_gradients:
00587 if (this->type() != colvarvalue::type_scalar)
00588 cvm::fatal_error ("Collecting atomic gradients for non-scalar collective variable \""+
00589 this->name+"\" is not yet implemented.\n");
00590 enable (task_gradients);
00591 if (atom_ids.size() == 0) {
00592 build_atom_list();
00593 }
00594 break;
00595 }
00596
00597
00598 tasks[t] = true;
00599 }
00600
00601
00602 void colvar::disable (colvar::task const &t)
00603 {
00604
00605 switch (t) {
00606 case task_gradients:
00607 disable (task_upper_wall);
00608 disable (task_lower_wall);
00609 disable (task_output_applied_force);
00610 disable (task_system_force);
00611 disable (task_Jacobian_force);
00612 break;
00613
00614 case task_system_force:
00615 disable (task_output_system_force);
00616 break;
00617
00618 case task_Jacobian_force:
00619 disable (task_report_Jacobian_force);
00620 break;
00621
00622 case task_fdiff_velocity:
00623 disable (task_output_velocity);
00624 break;
00625
00626 case task_lower_boundary:
00627 case task_upper_boundary:
00628 disable (task_grid);
00629 break;
00630
00631 case task_extended_lagrangian:
00632 case task_report_Jacobian_force:
00633 case task_output_value:
00634 case task_output_velocity:
00635 case task_output_applied_force:
00636 case task_output_system_force:
00637 case task_runave:
00638 case task_corrfunc:
00639 case task_grid:
00640 case task_lower_wall:
00641 case task_upper_wall:
00642 case task_ntot:
00643 break;
00644 }
00645
00646 tasks[t] = false;
00647 }
00648
00649
00650 colvar::~colvar()
00651 {
00652 if (cvm::b_analysis) {
00653
00654 if (acf.size()) {
00655 cvm::log ("Writing acf to file \""+acf_outfile+"\".\n");
00656
00657 std::ofstream acf_os (acf_outfile.c_str());
00658 if (! acf_os.good())
00659 cvm::fatal_error ("Cannot open file \""+acf_outfile+"\".\n");
00660 write_acf (acf_os);
00661 acf_os.close();
00662 }
00663
00664 if (runave_os.good()) {
00665 runave_os.close();
00666 }
00667 }
00668
00669 for (size_t i = 0; i < cvcs.size(); i++) {
00670 delete cvcs[i];
00671 }
00672 }
00673
00674
00675
00676
00677
00678
00679 void colvar::calc()
00680 {
00681 if (cvm::debug())
00682 cvm::log ("Calculating colvar \""+this->name+"\".\n");
00683
00684
00685
00686 x.reset();
00687 if (x.type() == colvarvalue::type_scalar) {
00688
00689
00690 for (size_t i = 0; i < cvcs.size(); i++) {
00691 cvm::increase_depth();
00692 (cvcs[i])->calc_value();
00693 cvm::decrease_depth();
00694 if (cvm::debug())
00695 cvm::log ("Colvar component no. "+cvm::to_str (i+1)+
00696 " within colvar \""+this->name+"\" has value "+
00697 cvm::to_str ((cvcs[i])->value(),
00698 cvm::cv_width, cvm::cv_prec)+".\n");
00699 x += (cvcs[i])->sup_coeff *
00700 ( ((cvcs[i])->sup_np != 1) ?
00701 std::pow ((cvcs[i])->value().real_value, (cvcs[i])->sup_np) :
00702 (cvcs[i])->value().real_value );
00703 }
00704 } else {
00705
00706 for (size_t i = 0; i < cvcs.size(); i++) {
00707 cvm::increase_depth();
00708 (cvcs[i])->calc_value();
00709 cvm::decrease_depth();
00710 if (cvm::debug())
00711 cvm::log ("Colvar component no. "+cvm::to_str (i+1)+
00712 " within colvar \""+this->name+"\" has value "+
00713 cvm::to_str ((cvcs[i])->value(),
00714 cvm::cv_width, cvm::cv_prec)+".\n");
00715 x += (cvcs[i])->sup_coeff * (cvcs[i])->value();
00716 }
00717 }
00718
00719 if (cvm::debug())
00720 cvm::log ("Colvar \""+this->name+"\" has value "+
00721 cvm::to_str (x, cvm::cv_width, cvm::cv_prec)+".\n");
00722
00723 if (tasks[task_gradients]) {
00724
00725 for (size_t i = 0; i < cvcs.size(); i++) {
00726 cvm::increase_depth();
00727 (cvcs[i])->calc_gradients();
00728 cvm::decrease_depth();
00729 }
00730 if (tasks[task_collect_gradients]) {
00731
00732 for (int a = 0; a < atomic_gradients.size(); a++) {
00733 atomic_gradients[a].reset();
00734 }
00735 for (size_t i = 0; i < cvcs.size(); i++) {
00736
00737 cvm::real coeff = (cvcs[i])->sup_coeff * cvm::real ((cvcs[i])->sup_np) *
00738 std::pow ((cvcs[i])->value().real_value, (cvcs[i])->sup_np-1);
00739
00740 for (size_t j = 0; j < cvcs[i]->atom_groups.size(); j++) {
00741
00742
00743
00744 if (cvcs[i]->atom_groups[j]->b_rotate) {
00745 cvm::rotation const rot_inv = cvcs[i]->atom_groups[j]->rot.inverse();
00746
00747 for (size_t k = 0; k < cvcs[i]->atom_groups[j]->size(); k++) {
00748 int a = std::lower_bound (atom_ids.begin(), atom_ids.end(),
00749 cvcs[i]->atom_groups[j]->at(k).id) - atom_ids.begin();
00750 atomic_gradients[a] += coeff *
00751 rot_inv.rotate (cvcs[i]->atom_groups[j]->at(k).grad);
00752 }
00753
00754 } else {
00755
00756 for (size_t k = 0; k < cvcs[i]->atom_groups[j]->size(); k++) {
00757 int a = std::lower_bound (atom_ids.begin(), atom_ids.end(),
00758 cvcs[i]->atom_groups[j]->at(k).id) - atom_ids.begin();
00759 atomic_gradients[a] += coeff * cvcs[i]->atom_groups[j]->at(k).grad;
00760 }
00761 }
00762 }
00763 }
00764 }
00765 }
00766
00767 if (tasks[task_system_force]) {
00768 ft.reset();
00769
00770 if(!tasks[task_extended_lagrangian] && (cvm::step_relative() > 0)) {
00771
00772 for (size_t i = 0; i < cvcs.size(); i++) {
00773 (cvcs[i])->calc_force_invgrads();
00774
00775 cvm::increase_depth();
00776 ft += (cvcs[i])->system_force() / ((cvcs[i])->sup_coeff * cvm::real (cvcs.size()));
00777 cvm::decrease_depth();
00778 }
00779 }
00780
00781 if (tasks[task_report_Jacobian_force]) {
00782
00783
00784 ft += fj;
00785 }
00786 }
00787
00788 if (tasks[task_fdiff_velocity]) {
00789
00790 if (cvm::step_relative() == 0)
00791 x_old = x;
00792 else {
00793 v_fdiff = fdiff_velocity (x_old, x);
00794 v_reported = v_fdiff;
00795 }
00796 }
00797
00798 if (tasks[task_extended_lagrangian]) {
00799
00800
00801
00802
00803 if (cvm::step_relative() == 0) {
00804 xr = x;
00805 vr = 0.0;
00806 }
00807
00808
00809 x_reported = xr;
00810 v_reported = vr;
00811
00812
00813
00814 ft_reported = (-0.5 * ext_force_k) * this->dist2_lgrad (xr, x);
00815
00816 } else {
00817
00818 x_reported = x;
00819 ft_reported = ft;
00820 }
00821
00822 if (cvm::debug())
00823 cvm::log ("Done calculating colvar \""+this->name+"\".\n");
00824 }
00825
00826
00827 cvm::real colvar::update()
00828 {
00829 if (cvm::debug())
00830 cvm::log ("Updating colvar \""+this->name+"\".\n");
00831
00832
00833
00834 f.reset();
00835
00836
00837
00838 f += fb;
00839
00840
00841 if (tasks[task_lower_wall] || tasks[task_upper_wall]) {
00842
00843
00844 colvarvalue fw (this->type());
00845
00846
00847
00848
00849 if ( (!tasks[task_upper_wall]) ||
00850 (this->dist2 (x, lower_wall) < this->dist2 (x, upper_wall)) ) {
00851
00852 cvm::real const grad = this->dist2_lgrad (x, lower_wall);
00853 if (grad < 0.0) {
00854 fw = -0.5 * lower_wall_k * grad;
00855 if (cvm::debug())
00856 cvm::log ("Applying a lower wall force ("+
00857 cvm::to_str (fw)+") to \""+this->name+"\".\n");
00858 f += fw;
00859
00860 }
00861
00862 } else {
00863
00864 cvm::real const grad = this->dist2_lgrad (x, upper_wall);
00865 if (grad > 0.0) {
00866 fw = -0.5 * upper_wall_k * grad;
00867 if (cvm::debug())
00868 cvm::log ("Applying an upper wall force ("+
00869 cvm::to_str (fw)+") to \""+this->name+"\".\n");
00870 f += fw;
00871 }
00872 }
00873 }
00874
00875 if (tasks[task_Jacobian_force]) {
00876
00877 cvm::increase_depth();
00878 for (size_t i = 0; i < cvcs.size(); i++) {
00879 (cvcs[i])->calc_Jacobian_derivative();
00880 }
00881 cvm::decrease_depth();
00882
00883 fj.reset();
00884 for (size_t i = 0; i < cvcs.size(); i++) {
00885
00886 fj += 1.0 / ( cvm::real (cvcs.size()) * cvm::real ((cvcs[i])->sup_coeff) ) *
00887 (cvcs[i])->Jacobian_derivative();
00888 }
00889 fj *= cvm::boltzmann() * cvm::temperature();
00890
00891
00892
00893 if (! tasks[task_report_Jacobian_force])
00894 f -= fj;
00895 }
00896
00897
00898 if (tasks[task_extended_lagrangian]) {
00899
00900 cvm::real dt = cvm::dt();
00901
00902
00903
00904
00905 fr = f;
00906 fr += (-0.5 * ext_force_k) * this->dist2_lgrad (xr, x);
00907 f = (-0.5 * ext_force_k) * this->dist2_rgrad (xr, x);
00908
00909
00910 vr += (0.5 * dt) * fr / ext_mass;
00911
00912 kinetic_energy = 0.5 * ext_mass * vr * vr;
00913 potential_energy = 0.5 * ext_force_k * this->dist2(xr, x);
00914
00915 if (tasks[task_langevin]) {
00916 vr -= dt * ext_gamma * vr.real_value;
00917 vr += dt * ext_sigma * cvm::rand_gaussian() / ext_mass;
00918 }
00919 vr += (0.5 * dt) * fr / ext_mass;
00920 xr += dt * vr;
00921 xr.apply_constraints();
00922 if (this->b_periodic) this->wrap (xr);
00923 }
00924
00925
00926 if (tasks[task_fdiff_velocity]) {
00927
00928 x_old = x;
00929 }
00930
00931 if (cvm::debug())
00932 cvm::log ("Done updating colvar \""+this->name+"\".\n");
00933 return (potential_energy + kinetic_energy);
00934 }
00935
00936
00937 void colvar::communicate_forces()
00938 {
00939 if (cvm::debug())
00940 cvm::log ("Communicating forces from colvar \""+this->name+"\".\n");
00941
00942 if (x.type() == colvarvalue::type_scalar) {
00943
00944 for (size_t i = 0; i < cvcs.size(); i++) {
00945 cvm::increase_depth();
00946 (cvcs[i])->apply_force (f * (cvcs[i])->sup_coeff *
00947 cvm::real ((cvcs[i])->sup_np) *
00948 (std::pow ((cvcs[i])->value().real_value,
00949 (cvcs[i])->sup_np-1)) );
00950 cvm::decrease_depth();
00951 }
00952
00953 } else {
00954
00955 for (size_t i = 0; i < cvcs.size(); i++) {
00956 cvm::increase_depth();
00957 (cvcs[i])->apply_force (f * (cvcs[i])->sup_coeff);
00958 cvm::decrease_depth();
00959 }
00960 }
00961
00962 if (cvm::debug())
00963 cvm::log ("Done communicating forces from colvar \""+this->name+"\".\n");
00964 }
00965
00966
00967
00968
00969
00970
00971
00972 bool colvar::periodic_boundaries (colvarvalue const &lb, colvarvalue const &ub) const
00973 {
00974 if ( (!tasks[task_lower_boundary]) || (!tasks[task_upper_boundary]) ) {
00975 cvm::fatal_error ("Error: requesting to histogram the "
00976 "collective variable \""+this->name+"\", but a "
00977 "pair of lower and upper boundaries must be "
00978 "defined.\n");
00979 }
00980
00981 if (period > 0.0) {
00982 if ( ((std::sqrt (this->dist2 (lb, ub))) / this->width)
00983 < 1.0E-10 ) {
00984 return true;
00985 }
00986 }
00987
00988 return false;
00989 }
00990
00991 bool colvar::periodic_boundaries() const
00992 {
00993 if ( (!tasks[task_lower_boundary]) || (!tasks[task_upper_boundary]) ) {
00994 cvm::fatal_error ("Error: requesting to histogram the "
00995 "collective variable \""+this->name+"\", but a "
00996 "pair of lower and upper boundaries must be "
00997 "defined.\n");
00998 }
00999
01000 return periodic_boundaries (lower_boundary, upper_boundary);
01001 }
01002
01003
01004 cvm::real colvar::dist2 (colvarvalue const &x1,
01005 colvarvalue const &x2) const
01006 {
01007 return (cvcs[0])->dist2 (x1, x2);
01008 }
01009
01010 colvarvalue colvar::dist2_lgrad (colvarvalue const &x1,
01011 colvarvalue const &x2) const
01012 {
01013 return (cvcs[0])->dist2_lgrad (x1, x2);
01014 }
01015
01016 colvarvalue colvar::dist2_rgrad (colvarvalue const &x1,
01017 colvarvalue const &x2) const
01018 {
01019 return (cvcs[0])->dist2_rgrad (x1, x2);
01020 }
01021
01022 cvm::real colvar::compare (colvarvalue const &x1,
01023 colvarvalue const &x2) const
01024 {
01025 return (cvcs[0])->compare (x1, x2);
01026 }
01027
01028 void colvar::wrap (colvarvalue &x) const
01029 {
01030 (cvcs[0])->wrap (x);
01031 return;
01032 }
01033
01034
01035
01036
01037 std::istream & colvar::read_restart (std::istream &is)
01038 {
01039 size_t const start_pos = is.tellg();
01040
01041 std::string conf;
01042 if ( !(is >> colvarparse::read_block ("colvar", conf)) ) {
01043
01044 is.clear();
01045 is.seekg (start_pos, std::ios::beg);
01046 is.setstate (std::ios::failbit);
01047 return is;
01048 }
01049
01050 {
01051 std::string check_name = "";
01052 if ( (get_keyval (conf, "name", check_name,
01053 std::string (""), colvarparse::parse_silent)) &&
01054 (check_name != name) ) {
01055 cvm::fatal_error ("Error: the state file does not match the "
01056 "configuration file, at colvar \""+name+"\".\n");
01057 }
01058 if (check_name.size() == 0) {
01059 cvm::fatal_error ("Error: Collective variable in the "
01060 "restart file without any identifier.\n");
01061 }
01062 }
01063
01064 if ( !(get_keyval (conf, "x", x,
01065 colvarvalue (x.type()), colvarparse::parse_silent)) ) {
01066 cvm::log ("Error: restart file does not contain "
01067 "the value of the colvar \""+
01068 name+"\" .\n");
01069 } else {
01070 cvm::log ("Restarting collective variable \""+name+"\" from value: "+
01071 cvm::to_str (x)+"\n");
01072 }
01073
01074 if (tasks[colvar::task_extended_lagrangian]) {
01075
01076 if ( !(get_keyval (conf, "extended_x", xr,
01077 colvarvalue (x.type()), colvarparse::parse_silent)) &&
01078 !(get_keyval (conf, "extended_v", vr,
01079 colvarvalue (x.type()), colvarparse::parse_silent)) ) {
01080 cvm::log ("Error: restart file does not contain "
01081 "\"extended_x\" or \"extended_v\" for the colvar \""+
01082 name+"\", but you requested \"extendedLagrangian\".\n");
01083 }
01084 }
01085
01086 if (tasks[task_extended_lagrangian]) {
01087 x_reported = xr;
01088 } else {
01089 x_reported = x;
01090 }
01091
01092 if (tasks[task_output_velocity]) {
01093
01094 if ( !(get_keyval (conf, "v", v_fdiff,
01095 colvarvalue (x.type()), colvarparse::parse_silent)) ) {
01096 cvm::log ("Error: restart file does not contain "
01097 "the velocity for the colvar \""+
01098 name+"\", but you requested \"outputVelocity\".\n");
01099 }
01100
01101 if (tasks[task_extended_lagrangian]) {
01102 v_reported = vr;
01103 } else {
01104 v_reported = v_fdiff;
01105 }
01106 }
01107
01108 return is;
01109 }
01110
01111
01112 std::istream & colvar::read_traj (std::istream &is)
01113 {
01114 size_t const start_pos = is.tellg();
01115
01116 if (tasks[task_output_value]) {
01117
01118 if (!(is >> x)) {
01119 cvm::log ("Error: in reading the value of colvar \""+
01120 this->name+"\" from trajectory.\n");
01121 is.clear();
01122 is.seekg (start_pos, std::ios::beg);
01123 is.setstate (std::ios::failbit);
01124 return is;
01125 }
01126
01127 if (tasks[task_extended_lagrangian]) {
01128 is >> xr;
01129 x_reported = xr;
01130 } else {
01131 x_reported = x;
01132 }
01133 }
01134
01135 if (tasks[task_output_velocity]) {
01136
01137 is >> v_fdiff;
01138
01139 if (tasks[task_extended_lagrangian]) {
01140 is >> vr;
01141 v_reported = vr;
01142 } else {
01143 v_reported = v_fdiff;
01144 }
01145 }
01146
01147 if (tasks[task_output_system_force]) {
01148
01149 is >> ft;
01150
01151 if (tasks[task_extended_lagrangian]) {
01152 is >> fr;
01153 ft_reported = fr;
01154 } else {
01155 ft_reported = ft;
01156 }
01157 }
01158
01159 if (tasks[task_output_applied_force]) {
01160 is >> f;
01161 }
01162
01163 return is;
01164 }
01165
01166
01167
01168
01169 std::ostream & colvar::write_restart (std::ostream &os) {
01170
01171 os << "colvar {\n"
01172 << " name " << name << "\n"
01173 << " x "
01174 << std::setprecision (cvm::cv_prec)
01175 << std::setw (cvm::cv_width)
01176 << x << "\n";
01177
01178 if (tasks[task_output_velocity]) {
01179 os << " v "
01180 << std::setprecision (cvm::cv_prec)
01181 << std::setw (cvm::cv_width)
01182 << v_reported << "\n";
01183 }
01184
01185 if (tasks[task_extended_lagrangian]) {
01186 os << " extended_x "
01187 << std::setprecision (cvm::cv_prec)
01188 << std::setw (cvm::cv_width)
01189 << xr << "\n"
01190 << " extended_v "
01191 << std::setprecision (cvm::cv_prec)
01192 << std::setw (cvm::cv_width)
01193 << vr << "\n";
01194 }
01195
01196 os << "}\n\n";
01197
01198 return os;
01199 }
01200
01201
01202 std::ostream & colvar::write_traj_label (std::ostream & os)
01203 {
01204 size_t const this_cv_width = x.output_width (cvm::cv_width);
01205
01206 os << " ";
01207
01208 if (tasks[task_output_value]) {
01209
01210 os << " "
01211 << cvm::wrap_string (this->name, this_cv_width);
01212
01213 if (tasks[task_extended_lagrangian]) {
01214
01215 os << " r_"
01216 << cvm::wrap_string (this->name, this_cv_width-2);
01217 }
01218 }
01219
01220 if (tasks[task_output_velocity]) {
01221
01222 os << " v_"
01223 << cvm::wrap_string (this->name, this_cv_width-2);
01224
01225 if (tasks[task_extended_lagrangian]) {
01226
01227 os << " vr_"
01228 << cvm::wrap_string (this->name, this_cv_width-3);
01229 }
01230 }
01231
01232 if (tasks[task_output_energy]) {
01233 os << " Ep_"
01234 << cvm::wrap_string (this->name, this_cv_width-3)
01235 << " Ek_"
01236 << cvm::wrap_string (this->name, this_cv_width-3);
01237 }
01238
01239 if (tasks[task_output_system_force]) {
01240
01241 os << " fs_"
01242 << cvm::wrap_string (this->name, this_cv_width-2);
01243
01244 if (tasks[task_extended_lagrangian]) {
01245
01246 os << " fr_"
01247 << cvm::wrap_string (this->name, this_cv_width-3);
01248 }
01249 }
01250
01251 if (tasks[task_output_applied_force]) {
01252 os << " fa_"
01253 << cvm::wrap_string (this->name, this_cv_width-2);
01254 }
01255
01256 return os;
01257 }
01258
01259
01260 std::ostream & colvar::write_traj (std::ostream &os)
01261 {
01262 os << " ";
01263
01264 if (tasks[task_output_value]) {
01265
01266 if (tasks[task_extended_lagrangian]) {
01267 os << " "
01268 << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
01269 << x;
01270 }
01271
01272 os << " "
01273 << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
01274 << x_reported;
01275 }
01276
01277 if (tasks[task_output_velocity]) {
01278
01279 if (tasks[task_extended_lagrangian]) {
01280 os << " "
01281 << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
01282 << v_fdiff;
01283 }
01284
01285 os << " "
01286 << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
01287 << v_reported;
01288 }
01289
01290 if (tasks[task_output_energy]) {
01291 os << " "
01292 << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
01293 << potential_energy
01294 << " "
01295 << kinetic_energy;
01296 }
01297
01298
01299 if (tasks[task_output_system_force]) {
01300
01301 if (tasks[task_extended_lagrangian]) {
01302 os << " "
01303 << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
01304 << ft;
01305 }
01306
01307 os << " "
01308 << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
01309 << ft_reported;
01310 }
01311
01312 if (tasks[task_output_applied_force]) {
01313 os << " "
01314 << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
01315 << f;
01316 }
01317
01318 return os;
01319 }
01320
01321
01322
01323
01324
01325 void colvar::analyse()
01326 {
01327 if (tasks[task_runave]) {
01328 calc_runave();
01329 }
01330
01331 if (tasks[task_corrfunc]) {
01332 calc_acf();
01333 }
01334 }
01335
01336
01337 inline void history_add_value (size_t const &history_length,
01338 std::list<colvarvalue> &history,
01339 colvarvalue const &new_value)
01340 {
01341 history.push_front (new_value);
01342 if (history.size() > history_length)
01343 history.pop_back();
01344 }
01345
01346 inline void history_incr (std::list< std::list<colvarvalue> > &history,
01347 std::list< std::list<colvarvalue> >::iterator &history_p)
01348 {
01349 if ((++history_p) == history.end())
01350 history_p = history.begin();
01351 }
01352
01353
01354 void colvar::calc_acf()
01355 {
01356
01357
01358
01359
01360
01361
01362 if (! (acf_x_history.size() || acf_v_history.size()) ) {
01363
01364
01365
01366 colvar *cfcv = (acf_colvar_name.size() ?
01367 cvm::colvar_p (acf_colvar_name) :
01368 this);
01369 if (cfcv->type() != this->type())
01370 cvm::fatal_error ("Error: correlation function between \""+cfcv->name+
01371 "\" and \""+this->name+"\" cannot be calculated, "
01372 "because their value types are different.\n");
01373 acf_nframes = 0;
01374
01375 cvm::log ("Colvar \""+this->name+"\": initializing ACF calculation.\n");
01376
01377 if (acf.size() < acf_length+1)
01378 acf.resize (acf_length+1, 0.0);
01379
01380 switch (acf_type) {
01381
01382 case acf_vel:
01383
01384 for (size_t i = 0; i < acf_stride; i++) {
01385 acf_v_history.push_back (std::list<colvarvalue>());
01386 }
01387 acf_v_history_p = acf_v_history.begin();
01388 break;
01389
01390 case acf_coor:
01391 case acf_p2coor:
01392
01393 for (size_t i = 0; i < acf_stride; i++) {
01394 acf_x_history.push_back (std::list<colvarvalue>());
01395 }
01396 acf_x_history_p = acf_x_history.begin();
01397 break;
01398
01399 default:
01400 break;
01401 }
01402
01403 } else {
01404
01405 colvar *cfcv = (acf_colvar_name.size() ?
01406 cvm::colvar_p (acf_colvar_name) :
01407 this);
01408
01409 switch (acf_type) {
01410
01411 case acf_vel:
01412
01413 if (tasks[task_fdiff_velocity]) {
01414
01415
01416
01417 v_reported = v_fdiff = fdiff_velocity (x_old, cfcv->value());
01418 }
01419
01420 calc_vel_acf ((*acf_v_history_p), cfcv->velocity());
01421
01422 history_add_value (acf_length+acf_offset, *acf_v_history_p, cfcv->velocity());
01423
01424 history_incr (acf_v_history, acf_v_history_p);
01425 break;
01426
01427 case acf_coor:
01428
01429 calc_coor_acf ((*acf_x_history_p), cfcv->value());
01430 history_add_value (acf_length+acf_offset, *acf_x_history_p, cfcv->value());
01431 history_incr (acf_x_history, acf_x_history_p);
01432 break;
01433
01434 case acf_p2coor:
01435
01436 calc_p2coor_acf ((*acf_x_history_p), cfcv->value());
01437 history_add_value (acf_length+acf_offset, *acf_x_history_p, cfcv->value());
01438 history_incr (acf_x_history, acf_x_history_p);
01439 break;
01440
01441 default:
01442 break;
01443 }
01444 }
01445
01446 if (tasks[task_fdiff_velocity]) {
01447
01448 x_old = x;
01449 }
01450 }
01451
01452
01453 void colvar::calc_vel_acf (std::list<colvarvalue> &v_list,
01454 colvarvalue const &v)
01455 {
01456
01457
01458 if (v_list.size() >= acf_length+acf_offset) {
01459 std::list<colvarvalue>::iterator vs_i = v_list.begin();
01460 std::vector<cvm::real>::iterator acf_i = acf.begin();
01461
01462 for (size_t i = 0; i < acf_offset; i++)
01463 vs_i++;
01464
01465
01466 *(acf_i++) += v.norm2();
01467
01468
01469
01470 colvarvalue::inner_opt (v, vs_i, v_list.end(), acf_i);
01471
01472 acf_nframes++;
01473 }
01474 }
01475
01476
01477 void colvar::calc_coor_acf (std::list<colvarvalue> &x_list,
01478 colvarvalue const &x)
01479 {
01480
01481 if (x_list.size() >= acf_length+acf_offset) {
01482 std::list<colvarvalue>::iterator xs_i = x_list.begin();
01483 std::vector<cvm::real>::iterator acf_i = acf.begin();
01484
01485 for (size_t i = 0; i < acf_offset; i++)
01486 xs_i++;
01487
01488 *(acf_i++) += x.norm2();
01489
01490 colvarvalue::inner_opt (x, xs_i, x_list.end(), acf_i);
01491
01492 acf_nframes++;
01493 }
01494 }
01495
01496
01497 void colvar::calc_p2coor_acf (std::list<colvarvalue> &x_list,
01498 colvarvalue const &x)
01499 {
01500
01501
01502 if (x_list.size() >= acf_length+acf_offset) {
01503 std::list<colvarvalue>::iterator xs_i = x_list.begin();
01504 std::vector<cvm::real>::iterator acf_i = acf.begin();
01505
01506 for (size_t i = 0; i < acf_offset; i++)
01507 xs_i++;
01508
01509
01510 *(acf_i++) += 1.0;
01511
01512 colvarvalue::p2leg_opt (x, xs_i, x_list.end(), acf_i);
01513
01514 acf_nframes++;
01515 }
01516 }
01517
01518
01519 void colvar::write_acf (std::ostream &os)
01520 {
01521 if (!acf_nframes)
01522 cvm::log ("Warning: ACF was not calculated (insufficient frames).\n");
01523 os.setf (std::ios::scientific, std::ios::floatfield);
01524 os << "# Autocorrelation function for collective variable \""
01525 << this->name << "\"\n";
01526
01527
01528 os << "# nframes = " << (acf_normalize ?
01529 acf_nframes - 1 :
01530 acf_nframes) << "\n";
01531
01532 cvm::real const acf_norm = acf.front() / cvm::real (acf_nframes);
01533 std::vector<cvm::real>::iterator acf_i;
01534 size_t it = acf_offset;
01535 for (acf_i = acf.begin(); acf_i != acf.end(); acf_i++) {
01536 os << std::setw (cvm::it_width) << acf_stride * (it++) << " "
01537 << std::setprecision (cvm::cv_prec)
01538 << std::setw (cvm::cv_width)
01539 << ( acf_normalize ?
01540 (*acf_i)/(acf_norm * cvm::real (acf_nframes)) :
01541 (*acf_i)/(cvm::real (acf_nframes)) ) << "\n";
01542 }
01543 }
01544
01545
01546 void colvar::calc_runave()
01547 {
01548 if (!x_history.size()) {
01549
01550 runave.type (x.type());
01551 runave.reset();
01552
01553
01554
01555 if (cvm::debug())
01556 cvm::log ("Colvar \""+this->name+
01557 "\": initializing running average calculation.\n");
01558
01559 acf_nframes = 0;
01560
01561 x_history.push_back (std::list<colvarvalue>());
01562 x_history_p = x_history.begin();
01563
01564 } else {
01565
01566 if ( (cvm::step_relative() % runave_stride) == 0) {
01567
01568 if ((*x_history_p).size() >= runave_length-1) {
01569
01570 runave = x;
01571 for (std::list<colvarvalue>::iterator xs_i = (*x_history_p).begin();
01572 xs_i != (*x_history_p).end(); xs_i++) {
01573 runave += (*xs_i);
01574 }
01575 runave *= 1.0 / cvm::real (runave_length);
01576 runave.apply_constraints();
01577
01578 runave_variance = 0.0;
01579 runave_variance += this->dist2 (x, runave);
01580 for (std::list<colvarvalue>::iterator xs_i = (*x_history_p).begin();
01581 xs_i != (*x_history_p).end(); xs_i++) {
01582 runave_variance += this->dist2 (x, (*xs_i));
01583 }
01584 runave_variance *= 1.0 / cvm::real (runave_length-1);
01585
01586 runave_os << std::setw (cvm::it_width) << cvm::step_relative()
01587 << " "
01588 << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
01589 << runave << " "
01590 << std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
01591 << std::sqrt (runave_variance) << "\n";
01592 }
01593
01594 history_add_value (runave_length, *x_history_p, x);
01595 }
01596 }
01597
01598 }
01599
01600