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