Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

colvar.C

Go to the documentation of this file.
00001 // -*- c++ -*-
00002 
00003 // This file is part of the Collective Variables module (Colvars).
00004 // The original version of Colvars and its updates are located at:
00005 // https://github.com/Colvars/colvars
00006 // Please update all Colvars source files before making any changes.
00007 // If you wish to distribute your changes, please submit them to the
00008 // Colvars repository at GitHub.
00009 
00010 #include <list>
00011 #include <vector>
00012 #include <algorithm>
00013 #include <iostream>
00014 #include <iomanip>
00015 
00016 #include "colvarmodule.h"
00017 #include "colvarvalue.h"
00018 #include "colvarparse.h"
00019 #include "colvar.h"
00020 #include "colvarcomp.h"
00021 #include "colvarscript.h"
00022 
00023 #if (__cplusplus >= 201103L)
00024 std::map<std::string, std::function<colvar::cvc* (const std::string& subcv_conf)>> colvar::global_cvc_map = std::map<std::string, std::function<colvar::cvc* (const std::string& subcv_conf)>>();
00025 #endif
00026 
00027 colvar::colvar()
00028 {
00029 prev_timestep = -1L;
00030 after_restart = false;
00031 kinetic_energy = 0.0;
00032 potential_energy = 0.0;
00033 
00034 #ifdef LEPTON
00035 dev_null = 0.0;
00036 #endif
00037 
00038 expand_boundaries = false;
00039 
00040 description = "uninitialized colvar";
00041 colvar::init_dependencies();
00042 }
00043 
00044 
00047 bool colvar::compare_cvc(const colvar::cvc* const i, const colvar::cvc* const j)
00048 {
00049 return i->name < j->name;
00050 }
00051 
00052 
00053 int colvar::init(std::string const &conf)
00054 {
00055 cvm::log("Initializing a new collective variable.\n");
00056 colvarparse::set_string(conf);
00057 
00058 int error_code = COLVARS_OK;
00059 
00060 colvarmodule *cv = cvm::main();
00061 
00062 get_keyval(conf, "name", this->name,
00063 (std::string("colvar")+cvm::to_str(cv->variables()->size())));
00064 
00065 if ((cvm::colvar_by_name(this->name) != NULL) &&
00066 (cvm::colvar_by_name(this->name) != this)) {
00067 cvm::error("Error: this colvar cannot have the same name, \""+this->name+
00068 "\", as another colvar.\n",
00069 COLVARS_INPUT_ERROR);
00070 return COLVARS_INPUT_ERROR;
00071 }
00072 
00073 // Initialize dependency members
00074 // Could be a function defined in a different source file, for space?
00075 
00076 this->description = "colvar " + this->name;
00077 
00078 error_code |= init_components(conf);
00079 if (error_code != COLVARS_OK) {
00080 return cvm::get_error();
00081 }
00082 
00083 size_t i;
00084 
00085 #ifdef LEPTON
00086 error_code |= init_custom_function(conf);
00087 if (error_code != COLVARS_OK) {
00088 return cvm::get_error();
00089 }
00090 #endif
00091 
00092 // Setup colvar as scripted function of components
00093 if (get_keyval(conf, "scriptedFunction", scripted_function,
00094 "", colvarparse::parse_silent)) {
00095 
00096 enable(f_cv_scripted);
00097 cvm::log("This colvar uses scripted function \"" + scripted_function + "\".\n");
00098 cvm::main()->cite_feature("Scripted functions (Tcl)");
00099 
00100 std::string type_str;
00101 get_keyval(conf, "scriptedFunctionType", type_str, "scalar");
00102 
00103 x.type(colvarvalue::type_notset);
00104 int t;
00105 for (t = 0; t < colvarvalue::type_all; t++) {
00106 if (type_str == colvarvalue::type_keyword(colvarvalue::Type(t))) {
00107 x.type(colvarvalue::Type(t));
00108 break;
00109 }
00110 }
00111 if (x.type() == colvarvalue::type_notset) {
00112 cvm::error("Could not parse scripted colvar type.", COLVARS_INPUT_ERROR);
00113 return COLVARS_INPUT_ERROR;
00114 }
00115 
00116 cvm::log(std::string("Expecting colvar value of type ")
00117 + colvarvalue::type_desc(x.type()));
00118 
00119 if (x.type() == colvarvalue::type_vector) {
00120 int size;
00121 if (!get_keyval(conf, "scriptedFunctionVectorSize", size)) {
00122 cvm::error("Error: no size specified for vector scripted function.",
00123 COLVARS_INPUT_ERROR);
00124 return COLVARS_INPUT_ERROR;
00125 }
00126 x.vector1d_value.resize(size);
00127 }
00128 
00129 x_reported.type(x);
00130 
00131 // Sort array of cvcs based on their names
00132 // Note: default CVC names are in input order for same type of CVC
00133 std::sort(cvcs.begin(), cvcs.end(), colvar::compare_cvc);
00134 
00135 if(cvcs.size() > 1) {
00136 cvm::log("Sorted list of components for this scripted colvar:\n");
00137 for (i = 0; i < cvcs.size(); i++) {
00138 cvm::log(cvm::to_str(i+1) + " " + cvcs[i]->name);
00139 }
00140 }
00141 
00142 // Build ordered list of component values that will be
00143 // passed to the script
00144 for (i = 0; i < cvcs.size(); i++) {
00145 sorted_cvc_values.push_back(&(cvcs[i]->value()));
00146 }
00147 }
00148 
00149 if (!(is_enabled(f_cv_scripted) || is_enabled(f_cv_custom_function))) {
00150 colvarvalue const &cvc_value = (cvcs[0])->value();
00151 if (cvm::debug())
00152 cvm::log ("This collective variable is a "+
00153 colvarvalue::type_desc(cvc_value.type())+
00154 ((cvc_value.size() > 1) ? " with "+
00155 cvm::to_str(cvc_value.size())+" individual components.\n" :
00156 ".\n"));
00157 x.type(cvc_value);
00158 x_reported.type(cvc_value);
00159 }
00160 
00161 set_enabled(f_cv_scalar, (value().type() == colvarvalue::type_scalar));
00162 
00163 // If using scripted biases, any colvar may receive bias forces
00164 // and will need its gradient
00165 if (cvm::scripted_forces()) {
00166 enable(f_cv_gradient);
00167 }
00168 
00169 // check for linear combinations
00170 {
00171 bool lin = !(is_enabled(f_cv_scripted) || is_enabled(f_cv_custom_function));
00172 for (i = 0; i < cvcs.size(); i++) {
00173 
00174 // FIXME this is a reverse dependency, ie. cv feature depends on cvc flag
00175 // need to clarify this case
00176 // if ((cvcs[i])->b_debug_gradients)
00177 // enable(task_gradients);
00178 
00179 if ((cvcs[i])->sup_np != 1) {
00180 if (cvm::debug() && lin)
00181 cvm::log("Warning: You are using a non-linear polynomial "
00182 "combination to define this collective variable, "
00183 "some biasing methods may be unavailable.\n");
00184 lin = false;
00185 
00186 if ((cvcs[i])->sup_np < 0) {
00187 cvm::log("Warning: you chose a negative exponent in the combination; "
00188 "if you apply forces, the simulation may become unstable "
00189 "when the component \""+
00190 (cvcs[i])->function_type+"\" approaches zero.\n");
00191 }
00192 }
00193 }
00194 set_enabled(f_cv_linear, lin);
00195 }
00196 
00197 // Colvar is homogeneous if:
00198 // - it is linear (hence not scripted)
00199 // - all cvcs have coefficient 1 or -1
00200 // i.e. sum or difference of cvcs
00201 {
00202 bool homogeneous = is_enabled(f_cv_linear);
00203 for (i = 0; i < cvcs.size(); i++) {
00204 if (cvm::fabs(cvm::fabs(cvcs[i]->sup_coeff) - 1.0) > 1.0e-10) {
00205 homogeneous = false;
00206 }
00207 }
00208 set_enabled(f_cv_homogeneous, homogeneous);
00209 }
00210 
00211 // A single-component variable almost concides with its CVC object
00212 if ((cvcs.size() == 1) && is_enabled(f_cv_homogeneous)) {
00213 if ( !is_enabled(f_cv_scripted) && !is_enabled(f_cv_custom_function) &&
00214 (cvm::fabs(cvcs[0]->sup_coeff - 1.0) < 1.0e-10) &&
00215 (cvcs[0]->sup_np == 1) ) {
00216 enable(f_cv_single_cvc);
00217 }
00218 }
00219 
00220 // Colvar is deemed periodic if:
00221 // - it is homogeneous
00222 // - all cvcs are periodic
00223 // - all cvcs have the same period
00224 if (is_enabled(f_cv_homogeneous) && cvcs[0]->is_enabled(f_cvc_periodic)) {
00225 bool b_periodic = true;
00226 period = cvcs[0]->period;
00227 wrap_center = cvcs[0]->wrap_center;
00228 for (i = 1; i < cvcs.size(); i++) {
00229 if (!cvcs[i]->is_enabled(f_cvc_periodic) || cvcs[i]->period != period) {
00230 b_periodic = false;
00231 period = 0.0;
00232 cvm::log("Warning: although one component is periodic, this colvar will "
00233 "not be treated as periodic, either because the exponent is not "
00234 "1, or because components of different periodicity are defined. "
00235 "Make sure that you know what you are doing!");
00236 }
00237 }
00238 set_enabled(f_cv_periodic, b_periodic);
00239 }
00240 
00241 // Allow scripted/custom functions to be defined as periodic
00242 if ( (is_enabled(f_cv_scripted) || is_enabled(f_cv_custom_function)) && is_enabled(f_cv_scalar) ) {
00243 if (get_keyval(conf, "period", period, 0.)) {
00244 enable(f_cv_periodic);
00245 get_keyval(conf, "wrapAround", wrap_center, 0.);
00246 }
00247 }
00248 
00249 // check that cvcs are compatible
00250 
00251 for (i = 0; i < cvcs.size(); i++) {
00252 
00253 // components may have different types only for scripted functions
00254 if (!(is_enabled(f_cv_scripted) || is_enabled(f_cv_custom_function)) && (colvarvalue::check_types(cvcs[i]->value(),
00255 cvcs[0]->value())) ) {
00256 cvm::error("ERROR: you are defining this collective variable "
00257 "by using components of different types. "
00258 "You must use the same type in order to "
00259 "sum them together.\n", COLVARS_INPUT_ERROR);
00260 return COLVARS_INPUT_ERROR;
00261 }
00262 }
00263 
00264 active_cvc_square_norm = 0.;
00265 for (i = 0; i < cvcs.size(); i++) {
00266 active_cvc_square_norm += cvcs[i]->sup_coeff * cvcs[i]->sup_coeff;
00267 }
00268 
00269 // at this point, the colvar's type is defined
00270 f.type(value());
00271 
00272 x_old.type(value());
00273 v_fdiff.type(value());
00274 v_reported.type(value());
00275 fj.type(value());
00276 ft.type(value());
00277 ft_reported.type(value());
00278 f_old.type(value());
00279 f_old.reset();
00280 
00281 x_restart.type(value());
00282 
00283 reset_bias_force();
00284 
00285 get_keyval(conf, "timeStepFactor", time_step_factor, 1);
00286 if (time_step_factor < 0) {
00287 cvm::error("Error: timeStepFactor must be positive.\n");
00288 return COLVARS_ERROR;
00289 }
00290 if (time_step_factor != 1) {
00291 enable(f_cv_multiple_ts);
00292 }
00293 
00294 error_code |= init_grid_parameters(conf);
00295 
00296 // Detect if we have a single component that is an alchemical lambda
00297 if (is_enabled(f_cv_single_cvc) && cvcs[0]->function_type == "alchLambda") {
00298 enable(f_cv_external);
00299 }
00300 
00301 error_code |= init_extended_Lagrangian(conf);
00302 error_code |= init_output_flags(conf);
00303 
00304 // Now that the children are defined we can solve dependencies
00305 enable(f_cv_active);
00306 
00307 error_code |= parse_analysis(conf);
00308 
00309 if (cvm::debug())
00310 cvm::log("Done initializing collective variable \""+this->name+"\".\n");
00311 
00312 return error_code;
00313 }
00314 
00315 
00316 #ifdef LEPTON
00317 int colvar::init_custom_function(std::string const &conf)
00318 {
00319 std::string expr, expr_in; // expr_in is a buffer to remember expr after unsuccessful parsing
00320 std::vector<Lepton::ParsedExpression> pexprs;
00321 Lepton::ParsedExpression pexpr;
00322 size_t pos = 0; // current position in config string
00323 double *ref;
00324 
00325 if (!key_lookup(conf, "customFunction", &expr_in, &pos)) {
00326 return COLVARS_OK;
00327 }
00328 
00329 cvm::main()->cite_feature("Custom functions (Lepton)");
00330 
00331 enable(f_cv_custom_function);
00332 cvm::log("This colvar uses a custom function.\n");
00333 
00334 do {
00335 expr = expr_in;
00336 if (cvm::debug())
00337 cvm::log("Parsing expression \"" + expr + "\".\n");
00338 try {
00339 pexpr = Lepton::Parser::parse(expr);
00340 pexprs.push_back(pexpr);
00341 }
00342 catch (...) {
00343 cvm::error("Error parsing expression \"" + expr + "\".\n", COLVARS_INPUT_ERROR);
00344 return COLVARS_INPUT_ERROR;
00345 }
00346 
00347 try {
00348 value_evaluators.push_back(
00349 new Lepton::CompiledExpression(pexpr.createCompiledExpression()));
00350 // Define variables for cvc values
00351 // Stored in order: expr1, cvc1, cvc2, expr2, cvc1...
00352 for (size_t i = 0; i < cvcs.size(); i++) {
00353 for (size_t j = 0; j < cvcs[i]->value().size(); j++) {
00354 std::string vn = cvcs[i]->name +
00355 (cvcs[i]->value().size() > 1 ? cvm::to_str(j+1) : "");
00356 try {
00357 ref =&value_evaluators.back()->getVariableReference(vn);
00358 }
00359 catch (...) { // Variable is absent from expression
00360 // To keep the same workflow, we use a pointer to a double here
00361 // that will receive CVC values - even though none was allocated by Lepton
00362 ref = &dev_null;
00363 cvm::log("Warning: Variable " + vn + " is absent from expression \"" + expr + "\".\n");
00364 }
00365 value_eval_var_refs.push_back(ref);
00366 }
00367 }
00368 }
00369 catch (...) {
00370 cvm::error("Error compiling expression \"" + expr + "\".\n", COLVARS_INPUT_ERROR);
00371 return COLVARS_INPUT_ERROR;
00372 }
00373 } while (key_lookup(conf, "customFunction", &expr_in, &pos));
00374 
00375 
00376 // Now define derivative with respect to each scalar sub-component
00377 for (size_t i = 0; i < cvcs.size(); i++) {
00378 for (size_t j = 0; j < cvcs[i]->value().size(); j++) {
00379 std::string vn = cvcs[i]->name +
00380 (cvcs[i]->value().size() > 1 ? cvm::to_str(j+1) : "");
00381 // Element ordering: we want the
00382 // gradient vector of derivatives of all elements of the colvar
00383 // wrt to a given element of a cvc ([i][j])
00384 for (size_t c = 0; c < pexprs.size(); c++) {
00385 gradient_evaluators.push_back(
00386 new Lepton::CompiledExpression(pexprs[c].differentiate(vn).createCompiledExpression()));
00387 // and record the refs to each variable in those expressions
00388 for (size_t k = 0; k < cvcs.size(); k++) {
00389 for (size_t l = 0; l < cvcs[k]->value().size(); l++) {
00390 std::string vvn = cvcs[k]->name +
00391 (cvcs[k]->value().size() > 1 ? cvm::to_str(l+1) : "");
00392 try {
00393 ref = &gradient_evaluators.back()->getVariableReference(vvn);
00394 }
00395 catch (...) { // Variable is absent from derivative
00396 // To keep the same workflow, we use a pointer to a double here
00397 // that will receive CVC values - even though none was allocated by Lepton
00398 if (cvm::debug()) {
00399 cvm::log("Warning: Variable " + vvn + " is absent from derivative of \"" + expr + "\" wrt " + vn + ".\n");
00400 }
00401 ref = &dev_null;
00402 }
00403 grad_eval_var_refs.push_back(ref);
00404 }
00405 }
00406 }
00407 }
00408 }
00409 
00410 
00411 if (value_evaluators.size() == 0) {
00412 cvm::error("Error: no custom function defined.\n", COLVARS_INPUT_ERROR);
00413 return COLVARS_INPUT_ERROR;
00414 }
00415 
00416 std::string type_str;
00417 bool b_type_specified = get_keyval(conf, "customFunctionType",
00418 type_str, "scalar", parse_silent);
00419 x.type(colvarvalue::type_notset);
00420 int t;
00421 for (t = 0; t < colvarvalue::type_all; t++) {
00422 if (type_str == colvarvalue::type_keyword(colvarvalue::Type(t))) {
00423 x.type(colvarvalue::Type(t));
00424 break;
00425 }
00426 }
00427 if (x.type() == colvarvalue::type_notset) {
00428 cvm::error("Could not parse custom colvar type.", COLVARS_INPUT_ERROR);
00429 return COLVARS_INPUT_ERROR;
00430 }
00431 
00432 // Guess type based on number of expressions
00433 if (!b_type_specified) {
00434 if (value_evaluators.size() == 1) {
00435 x.type(colvarvalue::type_scalar);
00436 } else {
00437 x.type(colvarvalue::type_vector);
00438 }
00439 }
00440 
00441 if (x.type() == colvarvalue::type_vector) {
00442 x.vector1d_value.resize(value_evaluators.size());
00443 }
00444 
00445 x_reported.type(x);
00446 cvm::log(std::string("Expecting colvar value of type ")
00447 + colvarvalue::type_desc(x.type())
00448 + (x.type()==colvarvalue::type_vector ? " of size " + cvm::to_str(x.size()) : "")
00449 + ".\n");
00450 
00451 if (x.size() != value_evaluators.size()) {
00452 cvm::error("Error: based on custom function type, expected "
00453 + cvm::to_str(x.size()) + " scalar expressions, but "
00454 + cvm::to_str(value_evaluators.size()) + " were found.\n");
00455 return COLVARS_INPUT_ERROR;
00456 }
00457 
00458 return COLVARS_OK;
00459 }
00460 
00461 #else
00462 
00463 int colvar::init_custom_function(std::string const &conf)
00464 {
00465 
00466 std::string expr;
00467 size_t pos = 0;
00468 if (key_lookup(conf, "customFunction", &expr, &pos)) {
00469 std::string msg("Error: customFunction requires the Lepton library.");
00470 #if (__cplusplus < 201103L)
00471 // NOTE: this is not ideal; testing for the Lepton library's version would
00472 // be more accurate, but also less portable
00473 msg +=
00474 std::string(" Note also that recent versions of Lepton require C++11: "
00475 "please see https://colvars.github.io/README-c++11.html.");
00476 #endif
00477 return cvm::error(msg, COLVARS_NOT_IMPLEMENTED);
00478 }
00479 
00480 return COLVARS_OK;
00481 }
00482 
00483 #endif // #ifdef LEPTON
00484 
00485 
00486 int colvar::init_grid_parameters(std::string const &conf)
00487 {
00488 int error_code = COLVARS_OK;
00489 
00490 colvarmodule *cv = cvm::main();
00491 
00492 cvm::real default_width = width;
00493 
00494 if (!key_already_set("width")) {
00495 // The first time, check if the CVC has a width to provide
00496 default_width = 1.0;
00497 if (is_enabled(f_cv_single_cvc) && cvcs[0]->is_enabled(f_cvc_width)) {
00498 cvm::real const cvc_width = cvcs[0]->get_param("width");
00499 default_width = cvc_width;
00500 }
00501 }
00502 
00503 get_keyval(conf, "width", width, default_width);
00504 
00505 if (width <= 0.0) {
00506 cvm::error("Error: \"width\" must be positive.\n", COLVARS_INPUT_ERROR);
00507 return COLVARS_INPUT_ERROR;
00508 }
00509 
00510 lower_boundary.type(value());
00511 upper_boundary.type(value());
00512 lower_boundary.real_value = 0.0;
00513 upper_boundary.real_value = width; // Default to 1-wide grids
00514 
00515 if (is_enabled(f_cv_scalar)) {
00516 
00517 if (is_enabled(f_cv_single_cvc)) {
00518 // Get the default boundaries from the component
00519 if (cvcs[0]->is_enabled(f_cvc_lower_boundary)) {
00520 enable(f_cv_lower_boundary);
00521 enable(f_cv_hard_lower_boundary);
00522 lower_boundary =
00523 *(reinterpret_cast<colvarvalue const *>(cvcs[0]->get_param_ptr("lowerBoundary")));
00524 }
00525 if (cvcs[0]->is_enabled(f_cvc_upper_boundary)) {
00526 enable(f_cv_upper_boundary);
00527 enable(f_cv_hard_upper_boundary);
00528 upper_boundary =
00529 *(reinterpret_cast<colvarvalue const *>(cvcs[0]->get_param_ptr("upperBoundary")));
00530 }
00531 }
00532 
00533 if (get_keyval(conf, "lowerBoundary", lower_boundary, lower_boundary)) {
00534 enable(f_cv_lower_boundary);
00535 // Because this is the user's choice, we cannot assume it is a true
00536 // physical boundary
00537 disable(f_cv_hard_lower_boundary);
00538 }
00539 
00540 if (get_keyval(conf, "upperBoundary", upper_boundary, upper_boundary)) {
00541 enable(f_cv_upper_boundary);
00542 disable(f_cv_hard_upper_boundary);
00543 }
00544 
00545 // Parse legacy wall options and set up a harmonicWalls bias if needed
00546 cvm::real lower_wall_k = 0.0, upper_wall_k = 0.0;
00547 cvm::real lower_wall = 0.0, upper_wall = 0.0;
00548 std::string lw_conf, uw_conf;
00549 
00550 if (get_keyval(conf, "lowerWallConstant", lower_wall_k, 0.0,
00551 parse_silent)) {
00552 cvm::log("Reading legacy options lowerWall and lowerWallConstant: "
00553 "consider using a harmonicWalls restraint (caution: force constant would then be scaled by width^2).\n");
00554 if (!get_keyval(conf, "lowerWall", lower_wall)) {
00555 error_code |= cvm::error("Error: the value of lowerWall must be set "
00556 "explicitly.\n", COLVARS_INPUT_ERROR);
00557 }
00558 lw_conf = std::string("\n\
00559 lowerWallConstant "+cvm::to_str(lower_wall_k*width*width)+"\n\
00560 lowerWalls "+cvm::to_str(lower_wall)+"\n");
00561 }
00562 
00563 if (get_keyval(conf, "upperWallConstant", upper_wall_k, 0.0,
00564 parse_silent)) {
00565 cvm::log("Reading legacy options upperWall and upperWallConstant: "
00566 "consider using a harmonicWalls restraint (caution: force constant would then be scaled by width^2).\n");
00567 if (!get_keyval(conf, "upperWall", upper_wall)) {
00568 error_code |= cvm::error("Error: the value of upperWall must be set "
00569 "explicitly.\n", COLVARS_INPUT_ERROR);
00570 }
00571 uw_conf = std::string("\n\
00572 upperWallConstant "+cvm::to_str(upper_wall_k*width*width)+"\n\
00573 upperWalls "+cvm::to_str(upper_wall)+"\n");
00574 }
00575 
00576 if (lw_conf.size() && uw_conf.size()) {
00577 if (lower_wall >= upper_wall) {
00578 error_code |= cvm::error("Error: the upper wall, "+
00579 cvm::to_str(upper_wall)+
00580 ", is not higher than the lower wall, "+
00581 cvm::to_str(lower_wall)+".\n",
00582 COLVARS_INPUT_ERROR);
00583 }
00584 }
00585 
00586 if (lw_conf.size() || uw_conf.size()) {
00587 cvm::log("Generating a new harmonicWalls bias for compatibility purposes.\n");
00588 std::string const walls_conf("\n\
00589 harmonicWalls {\n\
00590 name "+this->name+"w\n\
00591 colvars "+this->name+"\n"+lw_conf+uw_conf+"\
00592 timeStepFactor "+cvm::to_str(time_step_factor)+"\n"+
00593 "}\n");
00594 error_code |= cv->append_new_config(walls_conf);
00595 }
00596 }
00597 
00598 get_keyval_feature(this, conf, "hardLowerBoundary", f_cv_hard_lower_boundary,
00599 is_enabled(f_cv_hard_lower_boundary));
00600 
00601 get_keyval_feature(this, conf, "hardUpperBoundary", f_cv_hard_upper_boundary,
00602 is_enabled(f_cv_hard_upper_boundary));
00603 
00604 // consistency checks for boundaries and walls
00605 if (is_enabled(f_cv_lower_boundary) && is_enabled(f_cv_upper_boundary)) {
00606 if (lower_boundary >= upper_boundary) {
00607 error_code |= cvm::error("Error: the upper boundary, "+
00608 cvm::to_str(upper_boundary)+
00609 ", is not higher than the lower boundary, "+
00610 cvm::to_str(lower_boundary)+".\n",
00611 COLVARS_INPUT_ERROR);
00612 }
00613 }
00614 
00615 get_keyval(conf, "expandBoundaries", expand_boundaries, expand_boundaries);
00616 if (expand_boundaries && periodic_boundaries()) {
00617 error_code |= cvm::error("Error: trying to expand boundaries that already "
00618 "cover a whole period of a periodic colvar.\n",
00619 COLVARS_INPUT_ERROR);
00620 }
00621 
00622 if (expand_boundaries && is_enabled(f_cv_hard_lower_boundary) &&
00623 is_enabled(f_cv_hard_upper_boundary)) {
00624 error_code |= cvm::error("Error: inconsistent configuration "
00625 "(trying to expand boundaries, but both "
00626 "hardLowerBoundary and hardUpperBoundary "
00627 "are enabled).\n", COLVARS_INPUT_ERROR);
00628 }
00629 
00630 return error_code;
00631 }
00632 
00633 
00634 int colvar::init_extended_Lagrangian(std::string const &conf)
00635 {
00636 colvarproxy *proxy = cvm::main()->proxy;
00637 get_keyval_feature(this, conf, "extendedLagrangian", f_cv_extended_Lagrangian, false);
00638 
00639 if (is_enabled(f_cv_extended_Lagrangian)) {
00640 cvm::real temp, tolerance, extended_period;
00641 
00642 cvm::log("Enabling the extended Lagrangian term for colvar \""+
00643 this->name+"\".\n");
00644 
00645 // Mark x_ext as uninitialized so we can initialize it to the colvar value when updating
00646 x_ext.type(colvarvalue::type_notset);
00647 v_ext.type(value());
00648 fr.type(value());
00649 const bool temp_provided = get_keyval(conf, "extendedTemp", temp,
00650 proxy->target_temperature());
00651 if (is_enabled(f_cv_external)) {
00652 // In the case of an "external" coordinate, there is no coupling potential:
00653 // only the fictitious mass is meaningful
00654 get_keyval(conf, "extendedMass", ext_mass);
00655 // Ensure that the computed restraint energy term is zero
00656 ext_force_k = 0.0;
00657 } else {
00658 // Standard case of coupling to a geometric colvar
00659 if (temp <= 0.0) { // Then a finite temperature is required
00660 if (temp_provided)
00661 cvm::error("Error: \"extendedTemp\" must be positive.\n", COLVARS_INPUT_ERROR);
00662 else
00663 cvm::error("Error: a positive temperature must be provided, either "
00664 "by enabling a thermostat, or through \"extendedTemp\".\n",
00665 COLVARS_INPUT_ERROR);
00666 return COLVARS_INPUT_ERROR;
00667 }
00668 get_keyval(conf, "extendedFluctuation", tolerance);
00669 if (tolerance <= 0.0) {
00670 cvm::error("Error: \"extendedFluctuation\" must be positive.\n", COLVARS_INPUT_ERROR);
00671 return COLVARS_INPUT_ERROR;
00672 }
00673 ext_force_k = proxy->boltzmann() * temp / (tolerance * tolerance);
00674 cvm::log("Computed extended system force constant: " + cvm::to_str(ext_force_k) + " [E]/U^2\n");
00675 
00676 get_keyval(conf, "extendedTimeConstant", extended_period, 200.0);
00677 if (extended_period <= 0.0) {
00678 cvm::error("Error: \"extendedTimeConstant\" must be positive.\n", COLVARS_INPUT_ERROR);
00679 }
00680 ext_mass = (proxy->boltzmann() * temp * extended_period * extended_period)
00681 / (4.0 * PI * PI * tolerance * tolerance);
00682 cvm::log("Computed fictitious mass: " + cvm::to_str(ext_mass) + " [E]/(U/fs)^2 (U: colvar unit)\n");
00683 }
00684 {
00685 bool b_output_energy;
00686 get_keyval(conf, "outputEnergy", b_output_energy, false);
00687 if (b_output_energy) {
00688 enable(f_cv_output_energy);
00689 }
00690 }
00691 
00692 get_keyval(conf, "extendedLangevinDamping", ext_gamma, 1.0);
00693 if (ext_gamma < 0.0) {
00694 cvm::error("Error: \"extendedLangevinDamping\" may not be negative.\n", COLVARS_INPUT_ERROR);
00695 return COLVARS_INPUT_ERROR;
00696 }
00697 if (ext_gamma != 0.0) {
00698 enable(f_cv_Langevin);
00699 ext_gamma *= 1.0e-3; // correct as long as input is required in ps-1 and cvm::dt() is in fs
00700 // Adjust Langevin sigma for slow time step if time_step_factor != 1
00701 ext_sigma = cvm::sqrt(2.0 * proxy->boltzmann() * temp * ext_gamma * ext_mass / (cvm::dt() * cvm::real(time_step_factor)));
00702 }
00703 
00704 get_keyval_feature(this, conf, "reflectingLowerBoundary", f_cv_reflecting_lower_boundary, false);
00705 get_keyval_feature(this, conf, "reflectingUpperBoundary", f_cv_reflecting_upper_boundary, false);
00706 }
00707 
00708 return COLVARS_OK;
00709 }
00710 
00711 
00712 int colvar::init_output_flags(std::string const &conf)
00713 {
00714 {
00715 bool b_output_value;
00716 get_keyval(conf, "outputValue", b_output_value, true);
00717 if (b_output_value) {
00718 enable(f_cv_output_value);
00719 }
00720 }
00721 
00722 {
00723 bool b_output_velocity;
00724 get_keyval(conf, "outputVelocity", b_output_velocity, false);
00725 if (b_output_velocity) {
00726 enable(f_cv_output_velocity);
00727 }
00728 }
00729 
00730 {
00731 bool temp;
00732 if (get_keyval(conf, "outputSystemForce", temp, false, colvarparse::parse_silent)) {
00733 cvm::error("Option outputSystemForce is deprecated: only outputTotalForce is supported instead.\n"
00734 "The two are NOT identical: see https://colvars.github.io/totalforce.html.\n", COLVARS_INPUT_ERROR);
00735 return COLVARS_INPUT_ERROR;
00736 }
00737 }
00738 
00739 get_keyval_feature(this, conf, "outputTotalForce", f_cv_output_total_force, false);
00740 get_keyval_feature(this, conf, "outputAppliedForce", f_cv_output_applied_force, false);
00741 get_keyval_feature(this, conf, "subtractAppliedForce", f_cv_subtract_applied_force, false);
00742 
00743 return COLVARS_OK;
00744 }
00745 
00746 #if (__cplusplus >= 201103L)
00747 // C++11
00748 template<typename def_class_name> int colvar::init_components_type(std::string const &,
00749 char const * /* def_desc */,
00750 char const *def_config_key) {
00751 // global_cvc_map is only supported in the C++11 case
00752 global_cvc_map[def_config_key] = [](const std::string& cvc_conf){return new def_class_name(cvc_conf);};
00753 // TODO: maybe it is better to do more check to avoid duplication in the map?
00754 return COLVARS_OK;
00755 }
00756 
00757 int colvar::init_components_type_from_global_map(const std::string& conf,
00758 const char* def_config_key) {
00759 #else
00760 template<typename def_class_name> int colvar::init_components_type(std::string const & conf,
00761 char const * /* def_desc */,
00762 char const *def_config_key) {
00763 #endif
00764 size_t def_count = 0;
00765 std::string def_conf = "";
00766 size_t pos = 0;
00767 while ( this->key_lookup(conf,
00768 def_config_key,
00769 &def_conf,
00770 &pos) ) {
00771 if (!def_conf.size()) continue;
00772 cvm::log("Initializing "
00773 "a new \""+std::string(def_config_key)+"\" component"+
00774 (cvm::debug() ? ", with configuration:\n"+def_conf
00775 : ".\n"));
00776 cvm::increase_depth();
00777 // only the following line is different from init_components_type
00778 // in the non-C++11 case
00779 #if (__cplusplus >= 201103L)
00780 cvc *cvcp = global_cvc_map.at(def_config_key)(def_conf);
00781 #else
00782 cvc *cvcp = new def_class_name(def_conf);
00783 #endif
00784 if (cvcp != NULL) {
00785 cvcs.push_back(cvcp);
00786 cvcp->check_keywords(def_conf, def_config_key);
00787 cvcp->set_function_type(def_config_key);
00788 if (cvm::get_error()) {
00789 cvm::error("Error: in setting up component \""+
00790 std::string(def_config_key)+"\".\n", COLVARS_INPUT_ERROR);
00791 return COLVARS_INPUT_ERROR;
00792 }
00793 cvm::decrease_depth();
00794 } else {
00795 cvm::decrease_depth();
00796 cvm::error("Error: in allocating component \""+
00797 std::string(def_config_key)+"\".\n",
00798 COLVARS_MEMORY_ERROR);
00799 return COLVARS_MEMORY_ERROR;
00800 }
00801 
00802 if ( (cvcp->period != 0.0) || (cvcp->wrap_center != 0.0) ) {
00803 if (! cvcp->is_enabled(f_cvc_periodic)) {
00804 cvm::error("Error: invalid use of period and/or "
00805 "wrapAround in a \""+
00806 std::string(def_config_key)+
00807 "\" component.\n"+
00808 "Period: "+cvm::to_str(cvcp->period) +
00809 " wrapAround: "+cvm::to_str(cvcp->wrap_center),
00810 COLVARS_INPUT_ERROR);
00811 return COLVARS_INPUT_ERROR;
00812 }
00813 }
00814 
00815 if ( ! cvcs.back()->name.size()) {
00816 std::ostringstream s;
00817 s << def_config_key << std::setfill('0') << std::setw(4) << ++def_count;
00818 cvcs.back()->name = s.str();
00819 /* pad cvc number for correct ordering when sorting by name */
00820 }
00821 
00822 cvcs.back()->setup();
00823 if (cvm::debug()) {
00824 cvm::log("Done initializing a \""+
00825 std::string(def_config_key)+
00826 "\" component"+
00827 (cvm::debug() ?
00828 ", named \""+cvcs.back()->name+"\""
00829 : "")+".\n");
00830 }
00831 def_conf = "";
00832 if (cvm::debug()) {
00833 cvm::log("Parsed "+cvm::to_str(cvcs.size())+
00834 " components at this time.\n");
00835 }
00836 }
00837 
00838 return COLVARS_OK;
00839 }
00840 
00841 int colvar::init_components(std::string const &conf)
00842 {
00843 int error_code = COLVARS_OK;
00844 size_t i = 0, j = 0;
00845 
00846 // in the non-C++11 case, the components are initialized directly by init_components_type;
00847 // in the C++11 case, the components are stored in the global_cvc_map at first
00848 // by init_components_type, and then the map is iterated to initialize all components.
00849 error_code |= init_components_type<distance>(conf, "distance", "distance");
00850 error_code |= init_components_type<distance_vec>(conf, "distance vector", "distanceVec");
00851 error_code |= init_components_type<cartesian>(conf, "Cartesian coordinates", "cartesian");
00852 error_code |= init_components_type<distance_dir>(conf, "distance vector "
00853 "direction", "distanceDir");
00854 error_code |= init_components_type<distance_z>(conf, "distance projection "
00855 "on an axis", "distanceZ");
00856 error_code |= init_components_type<distance_xy>(conf, "distance projection "
00857 "on a plane", "distanceXY");
00858 error_code |= init_components_type<polar_theta>(conf, "spherical polar angle theta",
00859 "polarTheta");
00860 error_code |= init_components_type<polar_phi>(conf, "spherical azimuthal angle phi",
00861 "polarPhi");
00862 error_code |= init_components_type<distance_inv>(conf, "average distance "
00863 "weighted by inverse power", "distanceInv");
00864 error_code |= init_components_type<distance_pairs>(conf, "N1xN2-long vector "
00865 "of pairwise distances", "distancePairs");
00866 error_code |= init_components_type<dipole_magnitude>(conf, "dipole magnitude",
00867 "dipoleMagnitude");
00868 error_code |= init_components_type<coordnum>(conf, "coordination "
00869 "number", "coordNum");
00870 error_code |= init_components_type<selfcoordnum>(conf, "self-coordination "
00871 "number", "selfCoordNum");
00872 error_code |= init_components_type<groupcoordnum>(conf, "group-coordination "
00873 "number", "groupCoord");
00874 error_code |= init_components_type<angle>(conf, "angle", "angle");
00875 error_code |= init_components_type<dipole_angle>(conf, "dipole angle", "dipoleAngle");
00876 error_code |= init_components_type<dihedral>(conf, "dihedral", "dihedral");
00877 error_code |= init_components_type<h_bond>(conf, "hydrogen bond", "hBond");
00878 error_code |= init_components_type<alpha_angles>(conf, "alpha helix", "alpha");
00879 error_code |= init_components_type<dihedPC>(conf, "dihedral "
00880 "principal component", "dihedralPC");
00881 error_code |= init_components_type<orientation>(conf, "orientation", "orientation");
00882 error_code |= init_components_type<orientation_angle>(conf, "orientation "
00883 "angle", "orientationAngle");
00884 error_code |= init_components_type<orientation_proj>(conf, "orientation "
00885 "projection", "orientationProj");
00886 error_code |= init_components_type<tilt>(conf, "tilt", "tilt");
00887 error_code |= init_components_type<spin_angle>(conf, "spin angle", "spinAngle");
00888 error_code |= init_components_type<rmsd>(conf, "RMSD", "rmsd");
00889 error_code |= init_components_type<gyration>(conf, "radius of "
00890 "gyration", "gyration");
00891 error_code |= init_components_type<inertia>(conf, "moment of "
00892 "inertia", "inertia");
00893 error_code |= init_components_type<inertia_z>(conf, "moment of inertia around an axis", "inertiaZ");
00894 error_code |= init_components_type<eigenvector>(conf, "eigenvector", "eigenvector");
00895 error_code |= init_components_type<alch_lambda>(conf, "alchemical coupling parameter", "alchLambda");
00896 error_code |= init_components_type<alch_Flambda>(conf, "force on alchemical coupling parameter", "alchFLambda");
00897 error_code |= init_components_type<gspath>(conf, "geometrical path collective variables (s)", "gspath");
00898 error_code |= init_components_type<gzpath>(conf, "geometrical path collective variables (z)", "gzpath");
00899 error_code |= init_components_type<linearCombination>(conf, "linear combination of other collective variables", "linearCombination");
00900 error_code |= init_components_type<gspathCV>(conf, "geometrical path collective variables (s) for other CVs", "gspathCV");
00901 error_code |= init_components_type<gzpathCV>(conf, "geometrical path collective variables (z) for other CVs", "gzpathCV");
00902 error_code |= init_components_type<aspathCV>(conf, "arithmetic path collective variables (s) for other CVs", "aspathCV");
00903 error_code |= init_components_type<azpathCV>(conf, "arithmetic path collective variables (s) for other CVs", "azpathCV");
00904 error_code |= init_components_type<euler_phi>(conf, "euler phi angle of the optimal orientation", "eulerPhi");
00905 error_code |= init_components_type<euler_psi>(conf, "euler psi angle of the optimal orientation", "eulerPsi");
00906 error_code |= init_components_type<euler_theta>(conf, "euler theta angle of the optimal orientation", "eulerTheta");
00907 #ifdef LEPTON
00908 error_code |= init_components_type<customColvar>(conf, "CV with support of the lepton custom function", "customColvar");
00909 #endif
00910 error_code |= init_components_type<neuralNetwork>(conf, "neural network CV for other CVs", "NeuralNetwork");
00911 
00912 error_code |= init_components_type<map_total>(conf, "total value of atomic map", "mapTotal");
00913 #if (__cplusplus >= 201103L)
00914 // iterate over all available CVC in the map
00915 for (auto it = global_cvc_map.begin(); it != global_cvc_map.end(); ++it) {
00916 error_code |= init_components_type_from_global_map(conf, it->first.c_str());
00917 // TODO: is it better to check the error code here?
00918 if (error_code != COLVARS_OK) {
00919 cvm::log("Failed to initialize " + it->first + " with the following configuration:\n");
00920 cvm::log(conf);
00921 // TODO: should it stop here?
00922 }
00923 }
00924 #endif
00925 if (!cvcs.size() || (error_code != COLVARS_OK)) {
00926 cvm::error("Error: no valid components were provided "
00927 "for this collective variable.\n",
00928 COLVARS_INPUT_ERROR);
00929 return COLVARS_INPUT_ERROR;
00930 }
00931 
00932 // Check for uniqueness of CVC names (esp. if user-provided)
00933 for (i = 0; i < cvcs.size(); i++) {
00934 for (j = i+1; j < cvcs.size(); j++) {
00935 if (cvcs[i]->name == cvcs[j]->name) {
00936 cvm::error("Components " + cvm::to_str(i) + " and " + cvm::to_str(j) +\
00937 " cannot have the same name \"" + cvcs[i]->name+ "\".\n", COLVARS_INPUT_ERROR);
00938 return COLVARS_INPUT_ERROR;
00939 }
00940 }
00941 }
00942 
00943 n_active_cvcs = cvcs.size();
00944 
00945 // Store list of children cvcs for dependency checking purposes
00946 for (i = 0; i < cvcs.size(); i++) {
00947 add_child(cvcs[i]);
00948 }
00949 
00950 cvm::log("All components initialized.\n");
00951 
00952 return COLVARS_OK;
00953 }
00954 
00955 
00956 void colvar::do_feature_side_effects(int id)
00957 {
00958 switch (id) {
00959 case f_cv_total_force_calc:
00960 cvm::request_total_force();
00961 break;
00962 case f_cv_collect_atom_ids:
00963 // Needed for getting gradients vias collect_gradients
00964 // or via atomic forces e.g. in Colvars Dashboard in VMD
00965 if (atom_ids.size() == 0) {
00966 build_atom_list();
00967 }
00968 break;
00969 }
00970 }
00971 
00972 
00973 void colvar::build_atom_list(void)
00974 {
00975 // If atomic gradients are requested, build full list of atom ids from all cvcs
00976 std::list<int> temp_id_list;
00977 
00978 for (size_t i = 0; i < cvcs.size(); i++) {
00979 for (size_t j = 0; j < cvcs[i]->atom_groups.size(); j++) {
00980 cvm::atom_group const &ag = *(cvcs[i]->atom_groups[j]);
00981 for (size_t k = 0; k < ag.size(); k++) {
00982 temp_id_list.push_back(ag[k].id);
00983 }
00984 if (ag.is_enabled(f_ag_fitting_group) && ag.is_enabled(f_ag_fit_gradients)) {
00985 cvm::atom_group const &fg = *(ag.fitting_group);
00986 for (size_t k = 0; k < fg.size(); k++) {
00987 temp_id_list.push_back(fg[k].id);
00988 }
00989 }
00990 }
00991 }
00992 
00993 temp_id_list.sort();
00994 temp_id_list.unique();
00995 
00996 std::list<int>::iterator li;
00997 for (li = temp_id_list.begin(); li != temp_id_list.end(); ++li) {
00998 atom_ids.push_back(*li);
00999 }
01000 
01001 temp_id_list.clear();
01002 
01003 atomic_gradients.resize(atom_ids.size());
01004 if (atom_ids.size()) {
01005 if (cvm::debug())
01006 cvm::log("Colvar: created atom list with " + cvm::to_str(atom_ids.size()) + " atoms.\n");
01007 } else {
01008 cvm::log("Warning: colvar components communicated no atom IDs.\n");
01009 }
01010 }
01011 
01012 
01013 int colvar::parse_analysis(std::string const &conf)
01014 {
01015 
01016 // if (cvm::debug())
01017 // cvm::log ("Parsing analysis flags for collective variable \""+
01018 // this->name+"\".\n");
01019 
01020 runave_length = 0;
01021 bool b_runave = false;
01022 if (get_keyval(conf, "runAve", b_runave) && b_runave) {
01023 
01024 enable(f_cv_runave);
01025 
01026 get_keyval(conf, "runAveLength", runave_length, 1000);
01027 get_keyval(conf, "runAveStride", runave_stride, 1);
01028 
01029 if ((cvm::restart_out_freq % runave_stride) != 0) {
01030 cvm::error("Error: runAveStride must be commensurate with the restart frequency.\n", COLVARS_INPUT_ERROR);
01031 }
01032 
01033 get_keyval(conf, "runAveOutputFile", runave_outfile, runave_outfile);
01034 }
01035 
01036 acf_length = 0;
01037 bool b_acf = false;
01038 if (get_keyval(conf, "corrFunc", b_acf) && b_acf) {
01039 
01040 enable(f_cv_corrfunc);
01041 
01042 get_keyval(conf, "corrFuncWithColvar", acf_colvar_name, this->name);
01043 if (acf_colvar_name == this->name) {
01044 cvm::log("Calculating auto-correlation function.\n");
01045 } else {
01046 cvm::log("Calculating correlation function with \""+
01047 this->name+"\".\n");
01048 }
01049 
01050 std::string acf_type_str;
01051 get_keyval(conf, "corrFuncType", acf_type_str, to_lower_cppstr(std::string("velocity")));
01052 if (acf_type_str == to_lower_cppstr(std::string("coordinate"))) {
01053 acf_type = acf_coor;
01054 } else if (acf_type_str == to_lower_cppstr(std::string("velocity"))) {
01055 acf_type = acf_vel;
01056 enable(f_cv_fdiff_velocity);
01057 colvar *cv2 = cvm::colvar_by_name(acf_colvar_name);
01058 if (cv2 == NULL) {
01059 return cvm::error("Error: collective variable \""+acf_colvar_name+
01060 "\" is not defined at this time.\n", COLVARS_INPUT_ERROR);
01061 }
01062 cv2->enable(f_cv_fdiff_velocity); // Manual dependency to object of same type
01063 } else if (acf_type_str == to_lower_cppstr(std::string("coordinate_p2"))) {
01064 acf_type = acf_p2coor;
01065 } else {
01066 cvm::log("Unknown type of correlation function, \""+
01067 acf_type_str+"\".\n");
01068 cvm::set_error_bits(COLVARS_INPUT_ERROR);
01069 }
01070 
01071 get_keyval(conf, "corrFuncOffset", acf_offset, 0);
01072 get_keyval(conf, "corrFuncLength", acf_length, 1000);
01073 get_keyval(conf, "corrFuncStride", acf_stride, 1);
01074 
01075 if ((cvm::restart_out_freq % acf_stride) != 0) {
01076 cvm::error("Error: corrFuncStride must be commensurate with the restart frequency.\n", COLVARS_INPUT_ERROR);
01077 }
01078 
01079 get_keyval(conf, "corrFuncNormalize", acf_normalize, true);
01080 get_keyval(conf, "corrFuncOutputFile", acf_outfile, acf_outfile);
01081 }
01082 return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
01083 }
01084 
01085 
01086 int colvar::init_dependencies() {
01087 size_t i;
01088 if (features().size() == 0) {
01089 for (i = 0; i < f_cv_ntot; i++) {
01090 modify_features().push_back(new feature);
01091 }
01092 
01093 init_feature(f_cv_active, "active", f_type_dynamic);
01094 // Do not require f_cvc_active in children, as some components may be disabled
01095 // Colvars must be either a linear combination, or scalar (and polynomial) or scripted/custom
01096 require_feature_alt(f_cv_active, f_cv_scalar, f_cv_linear, f_cv_scripted, f_cv_custom_function);
01097 
01098 init_feature(f_cv_awake, "awake", f_type_static);
01099 require_feature_self(f_cv_awake, f_cv_active);
01100 
01101 init_feature(f_cv_gradient, "gradient", f_type_dynamic);
01102 require_feature_children(f_cv_gradient, f_cvc_gradient);
01103 
01104 init_feature(f_cv_collect_gradient, "collect_gradient", f_type_dynamic);
01105 require_feature_self(f_cv_collect_gradient, f_cv_gradient);
01106 require_feature_self(f_cv_collect_gradient, f_cv_scalar);
01107 require_feature_self(f_cv_collect_gradient, f_cv_collect_atom_ids);
01108 // The following exclusions could be lifted by implementing the feature
01109 exclude_feature_self(f_cv_collect_gradient, f_cv_scripted);
01110 exclude_feature_self(f_cv_collect_gradient, f_cv_custom_function);
01111 require_feature_children(f_cv_collect_gradient, f_cvc_explicit_gradient);
01112 
01113 init_feature(f_cv_collect_atom_ids, "collect_atom_ids", f_type_dynamic);
01114 require_feature_children(f_cv_collect_atom_ids, f_cvc_collect_atom_ids);
01115 
01116 init_feature(f_cv_fdiff_velocity, "velocity_from_finite_differences", f_type_dynamic);
01117 
01118 // System force: either trivial (spring force); through extended Lagrangian, or calculated explicitly
01119 init_feature(f_cv_total_force, "total_force", f_type_dynamic);
01120 require_feature_alt(f_cv_total_force, f_cv_extended_Lagrangian, f_cv_total_force_calc);
01121 
01122 // Deps for explicit total force calculation
01123 init_feature(f_cv_total_force_calc, "total_force_calculation", f_type_dynamic);
01124 require_feature_self(f_cv_total_force_calc, f_cv_scalar);
01125 require_feature_self(f_cv_total_force_calc, f_cv_linear);
01126 require_feature_children(f_cv_total_force_calc, f_cvc_inv_gradient);
01127 require_feature_self(f_cv_total_force_calc, f_cv_Jacobian);
01128 
01129 init_feature(f_cv_Jacobian, "Jacobian_derivative", f_type_dynamic);
01130 require_feature_self(f_cv_Jacobian, f_cv_scalar);
01131 require_feature_self(f_cv_Jacobian, f_cv_linear);
01132 require_feature_children(f_cv_Jacobian, f_cvc_Jacobian);
01133 
01134 init_feature(f_cv_hide_Jacobian, "hide_Jacobian_force", f_type_user);
01135 require_feature_self(f_cv_hide_Jacobian, f_cv_Jacobian); // can only hide if calculated
01136 exclude_feature_self(f_cv_hide_Jacobian, f_cv_extended_Lagrangian);
01137 
01138 init_feature(f_cv_extended_Lagrangian, "extended_Lagrangian", f_type_user);
01139 require_feature_self(f_cv_extended_Lagrangian, f_cv_scalar);
01140 require_feature_self(f_cv_extended_Lagrangian, f_cv_gradient);
01141 
01142 init_feature(f_cv_Langevin, "Langevin_dynamics", f_type_user);
01143 require_feature_self(f_cv_Langevin, f_cv_extended_Lagrangian);
01144 
01145 init_feature(f_cv_external, "external", f_type_user);
01146 require_feature_self(f_cv_external, f_cv_single_cvc);
01147 
01148 init_feature(f_cv_single_cvc, "single_component", f_type_static);
01149 
01150 init_feature(f_cv_linear, "linear", f_type_static);
01151 
01152 init_feature(f_cv_scalar, "scalar", f_type_static);
01153 
01154 init_feature(f_cv_output_energy, "output_energy", f_type_user);
01155 
01156 init_feature(f_cv_output_value, "output_value", f_type_user);
01157 
01158 init_feature(f_cv_output_velocity, "output_velocity", f_type_user);
01159 require_feature_self(f_cv_output_velocity, f_cv_fdiff_velocity);
01160 
01161 init_feature(f_cv_output_applied_force, "output_applied_force", f_type_user);
01162 
01163 init_feature(f_cv_output_total_force, "output_total_force", f_type_user);
01164 require_feature_self(f_cv_output_total_force, f_cv_total_force);
01165 
01166 init_feature(f_cv_subtract_applied_force, "subtract_applied_force_from_total_force", f_type_user);
01167 require_feature_self(f_cv_subtract_applied_force, f_cv_total_force);
01168 
01169 init_feature(f_cv_lower_boundary, "lower_boundary", f_type_user);
01170 require_feature_self(f_cv_lower_boundary, f_cv_scalar);
01171 
01172 init_feature(f_cv_upper_boundary, "upper_boundary", f_type_user);
01173 require_feature_self(f_cv_upper_boundary, f_cv_scalar);
01174 
01175 init_feature(f_cv_hard_lower_boundary, "hard_lower_boundary", f_type_user);
01176 require_feature_self(f_cv_hard_lower_boundary, f_cv_lower_boundary);
01177 
01178 init_feature(f_cv_hard_upper_boundary, "hard_upper_boundary", f_type_user);
01179 require_feature_self(f_cv_hard_upper_boundary, f_cv_upper_boundary);
01180 
01181 init_feature(f_cv_reflecting_lower_boundary, "reflecting_lower_boundary", f_type_user);
01182 require_feature_self(f_cv_reflecting_lower_boundary, f_cv_lower_boundary);
01183 require_feature_self(f_cv_reflecting_lower_boundary, f_cv_extended_Lagrangian);
01184 
01185 init_feature(f_cv_reflecting_upper_boundary, "reflecting_upper_boundary", f_type_user);
01186 require_feature_self(f_cv_reflecting_upper_boundary, f_cv_upper_boundary);
01187 require_feature_self(f_cv_reflecting_upper_boundary, f_cv_extended_Lagrangian);
01188 
01189 init_feature(f_cv_grid, "grid", f_type_dynamic);
01190 require_feature_self(f_cv_grid, f_cv_scalar);
01191 
01192 init_feature(f_cv_runave, "running_average", f_type_user);
01193 
01194 init_feature(f_cv_corrfunc, "correlation_function", f_type_user);
01195 
01196 init_feature(f_cv_scripted, "scripted", f_type_user);
01197 
01198 init_feature(f_cv_custom_function, "custom_function", f_type_user);
01199 exclude_feature_self(f_cv_custom_function, f_cv_scripted);
01200 
01201 init_feature(f_cv_periodic, "periodic", f_type_static);
01202 require_feature_self(f_cv_periodic, f_cv_scalar);
01203 init_feature(f_cv_scalar, "scalar", f_type_static);
01204 init_feature(f_cv_linear, "linear", f_type_static);
01205 init_feature(f_cv_homogeneous, "homogeneous", f_type_static);
01206 
01207 // because total forces are obtained from the previous time step,
01208 // we cannot (currently) have colvar values and total forces for the same timestep
01209 init_feature(f_cv_multiple_ts, "multiple_timestep", f_type_static);
01210 exclude_feature_self(f_cv_multiple_ts, f_cv_total_force_calc);
01211 
01212 // check that everything is initialized
01213 for (i = 0; i < colvardeps::f_cv_ntot; i++) {
01214 if (is_not_set(i)) {
01215 cvm::error("Uninitialized feature " + cvm::to_str(i) + " in " + description);
01216 }
01217 }
01218 }
01219 
01220 // Initialize feature_states for each instance
01221 feature_states.reserve(f_cv_ntot);
01222 for (i = 0; i < f_cv_ntot; i++) {
01223 feature_states.push_back(feature_state(true, false));
01224 // Most features are available, so we set them so
01225 // and list exceptions below
01226 }
01227 
01228 feature_states[f_cv_fdiff_velocity].available =
01229 cvm::main()->proxy->simulation_running();
01230 
01231 return COLVARS_OK;
01232 }
01233 
01234 
01235 void colvar::setup()
01236 {
01237 // loop over all components to update masses and charges of all groups
01238 for (size_t i = 0; i < cvcs.size(); i++) {
01239 for (size_t ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
01240 cvm::atom_group *atoms = cvcs[i]->atom_groups[ig];
01241 atoms->setup();
01242 atoms->print_properties(name, i, ig);
01243 atoms->read_positions();
01244 }
01245 }
01246 }
01247 
01248 
01249 std::vector<std::vector<int> > colvar::get_atom_lists()
01250 {
01251 std::vector<std::vector<int> > lists;
01252 for (size_t i = 0; i < cvcs.size(); i++) {
01253 std::vector<std::vector<int> > li = cvcs[i]->get_atom_lists();
01254 lists.insert(lists.end(), li.begin(), li.end());
01255 }
01256 return lists;
01257 }
01258 
01259 
01260 std::vector<int> const &colvar::get_volmap_ids()
01261 {
01262 volmap_ids_.resize(cvcs.size());
01263 for (size_t i = 0; i < cvcs.size(); i++) {
01264 if (cvcs[i]->param_exists("mapID") == COLVARS_OK) {
01265 volmap_ids_[i] =
01266 *(reinterpret_cast<int const *>(cvcs[i]->get_param_ptr("mapID")));
01267 } else {
01268 volmap_ids_[i] = -1;
01269 }
01270 }
01271 return volmap_ids_;
01272 }
01273 
01274 
01275 colvar::~colvar()
01276 {
01277 // There is no need to call free_children_deps() here
01278 // because the children are cvcs and will be deleted
01279 // just below
01280 
01281 // Clear references to this colvar's cvcs as children
01282 // for dependency purposes
01283 remove_all_children();
01284 
01285 for (std::vector<cvc *>::reverse_iterator ci = cvcs.rbegin();
01286 ci != cvcs.rend();
01287 ++ci) {
01288 // clear all children of this cvc (i.e. its atom groups)
01289 // because the cvc base class destructor can't do it early enough
01290 // and we don't want to have each cvc derived class do it separately
01291 (*ci)->remove_all_children();
01292 delete *ci;
01293 }
01294 cvcs.clear();
01295 
01296 while (biases.size() > 0) {
01297 size_t const i = biases.size()-1;
01298 cvm::log("Warning: before deleting colvar " + name
01299 + ", deleting related bias " + biases[i]->name);
01300 delete biases[i];
01301 }
01302 biases.clear();
01303 
01304 // remove reference to this colvar from the module
01305 colvarmodule *cv = cvm::main();
01306 for (std::vector<colvar *>::iterator cvi = cv->variables()->begin();
01307 cvi != cv->variables()->end();
01308 ++cvi) {
01309 if ( *cvi == this) {
01310 cv->variables()->erase(cvi);
01311 break;
01312 }
01313 }
01314 
01315 cv->config_changed();
01316 
01317 #ifdef LEPTON
01318 for (std::vector<Lepton::CompiledExpression *>::iterator cei = value_evaluators.begin();
01319 cei != value_evaluators.end();
01320 ++cei) {
01321 if (*cei != NULL) delete (*cei);
01322 }
01323 value_evaluators.clear();
01324 
01325 for (std::vector<Lepton::CompiledExpression *>::iterator gei = gradient_evaluators.begin();
01326 gei != gradient_evaluators.end();
01327 ++gei) {
01328 if (*gei != NULL) delete (*gei);
01329 }
01330 gradient_evaluators.clear();
01331 #endif
01332 }
01333 
01334 
01335 
01336 // ******************** CALC FUNCTIONS ********************
01337 
01338 
01339 // Default schedule (everything is serialized)
01340 int colvar::calc()
01341 {
01342 // Note: if anything is added here, it should be added also in the SMP block of calc_colvars()
01343 int error_code = COLVARS_OK;
01344 if (is_enabled(f_cv_active)) {
01345 error_code |= update_cvc_flags();
01346 if (error_code != COLVARS_OK) return error_code;
01347 error_code |= calc_cvcs();
01348 if (error_code != COLVARS_OK) return error_code;
01349 error_code |= collect_cvc_data();
01350 }
01351 return error_code;
01352 }
01353 
01354 
01355 int colvar::calc_cvcs(int first_cvc, size_t num_cvcs)
01356 {
01357 if (cvm::debug())
01358 cvm::log("Calculating colvar \""+this->name+"\", components "+
01359 cvm::to_str(first_cvc)+" through "+cvm::to_str(first_cvc+num_cvcs)+".\n");
01360 
01361 colvarproxy *proxy = cvm::main()->proxy;
01362 int error_code = COLVARS_OK;
01363 
01364 error_code |= check_cvc_range(first_cvc, num_cvcs);
01365 if (error_code != COLVARS_OK) {
01366 return error_code;
01367 }
01368 
01369 if ((cvm::step_relative() > 0) && (!proxy->total_forces_same_step())){
01370 // Use Jacobian derivative from previous timestep
01371 error_code |= calc_cvc_total_force(first_cvc, num_cvcs);
01372 }
01373 // atom coordinates are updated by the next line
01374 error_code |= calc_cvc_values(first_cvc, num_cvcs);
01375 error_code |= calc_cvc_gradients(first_cvc, num_cvcs);
01376 error_code |= calc_cvc_Jacobians(first_cvc, num_cvcs);
01377 if (proxy->total_forces_same_step()){
01378 // Use Jacobian derivative from this timestep
01379 error_code |= calc_cvc_total_force(first_cvc, num_cvcs);
01380 }
01381 
01382 if (cvm::debug())
01383 cvm::log("Done calculating colvar \""+this->name+"\".\n");
01384 
01385 return error_code;
01386 }
01387 
01388 
01389 int colvar::collect_cvc_data()
01390 {
01391 if (cvm::debug())
01392 cvm::log("Calculating colvar \""+this->name+"\"'s properties.\n");
01393 
01394 colvarproxy *proxy = cvm::main()->proxy;
01395 int error_code = COLVARS_OK;
01396 
01397 if ((cvm::step_relative() > 0) && (!proxy->total_forces_same_step())){
01398 // Total force depends on Jacobian derivative from previous timestep
01399 // collect_cvc_total_forces() uses the previous value of jd
01400 error_code |= collect_cvc_total_forces();
01401 }
01402 error_code |= collect_cvc_values();
01403 error_code |= collect_cvc_gradients();
01404 error_code |= collect_cvc_Jacobians();
01405 if (proxy->total_forces_same_step()){
01406 // Use Jacobian derivative from this timestep
01407 error_code |= collect_cvc_total_forces();
01408 }
01409 error_code |= calc_colvar_properties();
01410 
01411 if (cvm::debug())
01412 cvm::log("Done calculating colvar \""+this->name+"\"'s properties.\n");
01413 
01414 return error_code;
01415 }
01416 
01417 
01418 int colvar::check_cvc_range(int first_cvc, size_t /* num_cvcs */)
01419 {
01420 if ((first_cvc < 0) || (first_cvc >= ((int) cvcs.size()))) {
01421 cvm::error("Error: trying to address a component outside the "
01422 "range defined for colvar \""+name+"\".\n", COLVARS_BUG_ERROR);
01423 return COLVARS_BUG_ERROR;
01424 }
01425 return COLVARS_OK;
01426 }
01427 
01428 
01429 int colvar::calc_cvc_values(int first_cvc, size_t num_cvcs)
01430 {
01431 size_t const cvc_max_count = num_cvcs ? num_cvcs : num_active_cvcs();
01432 size_t i, cvc_count;
01433 
01434 // calculate the value of the colvar
01435 
01436 if (cvm::debug())
01437 cvm::log("Calculating colvar components.\n");
01438 
01439 // First, calculate component values
01440 cvm::increase_depth();
01441 for (i = first_cvc, cvc_count = 0;
01442 (i < cvcs.size()) && (cvc_count < cvc_max_count);
01443 i++) {
01444 if (!cvcs[i]->is_enabled()) continue;
01445 cvc_count++;
01446 (cvcs[i])->read_data();
01447 (cvcs[i])->calc_value();
01448 if (cvm::debug())
01449 cvm::log("Colvar component no. "+cvm::to_str(i+1)+
01450 " within colvar \""+this->name+"\" has value "+
01451 cvm::to_str((cvcs[i])->value(),
01452 cvm::cv_width, cvm::cv_prec)+".\n");
01453 }
01454 cvm::decrease_depth();
01455 
01456 return COLVARS_OK;
01457 }
01458 
01459 
01460 int colvar::collect_cvc_values()
01461 {
01462 x.reset();
01463 
01464 // combine them appropriately, using either a scripted function or a polynomial
01465 if (is_enabled(f_cv_scripted)) {
01466 // cvcs combined by user script
01467 int res = cvm::proxy->run_colvar_callback(scripted_function, sorted_cvc_values, x);
01468 if (res == COLVARS_NOT_IMPLEMENTED) {
01469 cvm::error("Scripted colvars are not implemented.");
01470 return COLVARS_NOT_IMPLEMENTED;
01471 }
01472 if (res != COLVARS_OK) {
01473 cvm::error("Error running scripted colvar");
01474 return COLVARS_OK;
01475 }
01476 
01477 #ifdef LEPTON
01478 } else if (is_enabled(f_cv_custom_function)) {
01479 
01480 size_t l = 0; // index in the vector of variable references
01481 
01482 for (size_t i = 0; i < x.size(); i++) {
01483 // Fill Lepton evaluator variables with CVC values, serialized into scalars
01484 for (size_t j = 0; j < cvcs.size(); j++) {
01485 for (size_t k = 0; k < cvcs[j]->value().size(); k++) {
01486 *(value_eval_var_refs[l++]) = cvcs[j]->value()[k];
01487 }
01488 }
01489 x[i] = value_evaluators[i]->evaluate();
01490 }
01491 #endif
01492 
01493 } else if (x.type() == colvarvalue::type_scalar) {
01494 // polynomial combination allowed
01495 for (size_t i = 0; i < cvcs.size(); i++) {
01496 if (!cvcs[i]->is_enabled()) continue;
01497 x += (cvcs[i])->sup_coeff *
01498 ( ((cvcs[i])->sup_np != 1) ?
01499 cvm::integer_power((cvcs[i])->value().real_value, (cvcs[i])->sup_np) :
01500 (cvcs[i])->value().real_value );
01501 }
01502 } else {
01503 for (size_t i = 0; i < cvcs.size(); i++) {
01504 if (!cvcs[i]->is_enabled()) continue;
01505 x += (cvcs[i])->sup_coeff * (cvcs[i])->value();
01506 }
01507 }
01508 
01509 if (cvm::debug())
01510 cvm::log("Colvar \""+this->name+"\" has value "+
01511 cvm::to_str(x, cvm::cv_width, cvm::cv_prec)+".\n");
01512 
01513 if (after_restart) {
01514 if (cvm::proxy->simulation_running()) {
01515 cvm::real const jump2 = dist2(x, x_restart) / (width*width);
01516 if (jump2 > 0.25) {
01517 cvm::error("Error: the calculated value of colvar \""+name+
01518 "\":\n"+cvm::to_str(x)+"\n differs greatly from the value "
01519 "last read from the state file:\n"+cvm::to_str(x_restart)+
01520 "\nPossible causes are changes in configuration, "
01521 "wrong state file, or how PBC wrapping is handled.\n",
01522 COLVARS_INPUT_ERROR);
01523 return COLVARS_INPUT_ERROR;
01524 }
01525 }
01526 }
01527 
01528 return COLVARS_OK;
01529 }
01530 
01531 
01532 int colvar::calc_cvc_gradients(int first_cvc, size_t num_cvcs)
01533 {
01534 size_t const cvc_max_count = num_cvcs ? num_cvcs : num_active_cvcs();
01535 size_t i, cvc_count;
01536 
01537 if (cvm::debug())
01538 cvm::log("Calculating gradients of colvar \""+this->name+"\".\n");
01539 
01540 // calculate the gradients of each component
01541 cvm::increase_depth();
01542 for (i = first_cvc, cvc_count = 0;
01543 (i < cvcs.size()) && (cvc_count < cvc_max_count);
01544 i++) {
01545 if (!cvcs[i]->is_enabled()) continue;
01546 cvc_count++;
01547 
01548 if ((cvcs[i])->is_enabled(f_cvc_gradient)) {
01549 (cvcs[i])->calc_gradients();
01550 // if requested, propagate (via chain rule) the gradients above
01551 // to the atoms used to define the roto-translation
01552 (cvcs[i])->calc_fit_gradients();
01553 if ((cvcs[i])->is_enabled(f_cvc_debug_gradient))
01554 (cvcs[i])->debug_gradients();
01555 }
01556 
01557 cvm::decrease_depth();
01558 
01559 if (cvm::debug())
01560 cvm::log("Done calculating gradients of colvar \""+this->name+"\".\n");
01561 }
01562 
01563 return COLVARS_OK;
01564 }
01565 
01566 
01567 int colvar::collect_cvc_gradients()
01568 {
01569 size_t i;
01570 if (is_enabled(f_cv_collect_gradient)) {
01571 // Collect the atomic gradients inside colvar object
01572 for (unsigned int a = 0; a < atomic_gradients.size(); a++) {
01573 atomic_gradients[a].reset();
01574 }
01575 for (i = 0; i < cvcs.size(); i++) {
01576 if (!cvcs[i]->is_enabled()) continue;
01577 cvcs[i]->collect_gradients(atom_ids, atomic_gradients);
01578 }
01579 }
01580 return COLVARS_OK;
01581 }
01582 
01583 
01584 int colvar::calc_cvc_total_force(int first_cvc, size_t num_cvcs)
01585 {
01586 size_t const cvc_max_count = num_cvcs ? num_cvcs : num_active_cvcs();
01587 size_t i, cvc_count;
01588 
01589 if (is_enabled(f_cv_total_force_calc)) {
01590 if (cvm::debug())
01591 cvm::log("Calculating total force of colvar \""+this->name+"\".\n");
01592 
01593 cvm::increase_depth();
01594 
01595 for (i = first_cvc, cvc_count = 0;
01596 (i < cvcs.size()) && (cvc_count < cvc_max_count);
01597 i++) {
01598 if (!cvcs[i]->is_enabled()) continue;
01599 cvc_count++;
01600 (cvcs[i])->calc_force_invgrads();
01601 }
01602 cvm::decrease_depth();
01603 
01604 
01605 if (cvm::debug())
01606 cvm::log("Done calculating total force of colvar \""+this->name+"\".\n");
01607 }
01608 
01609 return COLVARS_OK;
01610 }
01611 
01612 
01613 int colvar::collect_cvc_total_forces()
01614 {
01615 if (is_enabled(f_cv_total_force_calc)) {
01616 ft.reset();
01617 
01618 if (cvm::step_relative() > 0) {
01619 // get from the cvcs the total forces from the PREVIOUS step
01620 for (size_t i = 0; i < cvcs.size(); i++) {
01621 if (!cvcs[i]->is_enabled()) continue;
01622 if (cvm::debug())
01623 cvm::log("Colvar component no. "+cvm::to_str(i+1)+
01624 " within colvar \""+this->name+"\" has total force "+
01625 cvm::to_str((cvcs[i])->total_force(),
01626 cvm::cv_width, cvm::cv_prec)+".\n");
01627 // linear combination is assumed
01628 ft += (cvcs[i])->total_force() * (cvcs[i])->sup_coeff / active_cvc_square_norm;
01629 }
01630 }
01631 
01632 if (!(is_enabled(f_cv_hide_Jacobian) && is_enabled(f_cv_subtract_applied_force))) {
01633 // add the Jacobian force to the total force, and don't apply any silent
01634 // correction internally: biases such as colvarbias_abf will handle it
01635 // If f_cv_hide_Jacobian is enabled, a force of -fj is present in ft due to the
01636 // Jacobian-compensating force
01637 ft += fj;
01638 }
01639 }
01640 
01641 return COLVARS_OK;
01642 }
01643 
01644 
01645 int colvar::calc_cvc_Jacobians(int first_cvc, size_t num_cvcs)
01646 {
01647 size_t const cvc_max_count = num_cvcs ? num_cvcs : num_active_cvcs();
01648 
01649 if (is_enabled(f_cv_Jacobian)) {
01650 cvm::increase_depth();
01651 size_t i, cvc_count;
01652 for (i = first_cvc, cvc_count = 0;
01653 (i < cvcs.size()) && (cvc_count < cvc_max_count);
01654 i++) {
01655 if (!cvcs[i]->is_enabled()) continue;
01656 cvc_count++;
01657 (cvcs[i])->calc_Jacobian_derivative();
01658 }
01659 cvm::decrease_depth();
01660 }
01661 
01662 return COLVARS_OK;
01663 }
01664 
01665 
01666 int colvar::collect_cvc_Jacobians()
01667 {
01668 colvarproxy *proxy = cvm::main()->proxy;
01669 if (is_enabled(f_cv_Jacobian)) {
01670 fj.reset();
01671 for (size_t i = 0; i < cvcs.size(); i++) {
01672 if (!cvcs[i]->is_enabled()) continue;
01673 if (cvm::debug())
01674 cvm::log("Colvar component no. "+cvm::to_str(i+1)+
01675 " within colvar \""+this->name+"\" has Jacobian derivative"+
01676 cvm::to_str((cvcs[i])->Jacobian_derivative(),
01677 cvm::cv_width, cvm::cv_prec)+".\n");
01678 // linear combination is assumed
01679 fj += (cvcs[i])->Jacobian_derivative() * (cvcs[i])->sup_coeff / active_cvc_square_norm;
01680 }
01681 fj *= proxy->boltzmann() * proxy->target_temperature();
01682 }
01683 
01684 return COLVARS_OK;
01685 }
01686 
01687 
01688 int colvar::calc_colvar_properties()
01689 {
01690 if (is_enabled(f_cv_fdiff_velocity)) {
01691 // calculate the velocity by finite differences
01692 if (cvm::step_relative() == 0) {
01693 x_old = x;
01694 v_fdiff.reset(); // Do not pretend we know anything about the actual velocity
01695 // eg. upon restarting. That would require saving v_fdiff or x_old to the state file
01696 } else {
01697 v_fdiff = fdiff_velocity(x_old, x);
01698 v_reported = v_fdiff;
01699 }
01700 }
01701 
01702 if (is_enabled(f_cv_extended_Lagrangian)) {
01703 // initialize the restraint center in the first step to the value
01704 // just calculated from the cvcs
01705 // Do the same if no simulation is running (eg. VMD postprocessing)
01706 if ((cvm::step_relative() == 0 && !after_restart) || x_ext.type() == colvarvalue::type_notset || !cvm::proxy->simulation_running()) {
01707 x_ext = x;
01708 if (is_enabled(f_cv_reflecting_lower_boundary) && x_ext < lower_boundary) {
01709 cvm::log("Warning: initializing extended coordinate to reflective lower boundary, as colvar value is below.");
01710 x_ext = lower_boundary;
01711 }
01712 if (is_enabled(f_cv_reflecting_upper_boundary) && x_ext > upper_boundary) {
01713 cvm::log("Warning: initializing extended coordinate to reflective upper boundary, as colvar value is above.");
01714 x_ext = upper_boundary;
01715 }
01716 
01717 v_ext.reset(); // (already 0; added for clarity)
01718 }
01719 
01720 // Special case of a repeated timestep (eg. multiple NAMD "run" statements)
01721 // revert values of the extended coordinate and velocity prior to latest integration
01722 if (cvm::proxy->simulation_running() && cvm::step_relative() == prev_timestep) {
01723 x_ext = prev_x_ext;
01724 v_ext = prev_v_ext;
01725 }
01726 // report the restraint center as "value"
01727 // These position and velocities come from integration at the _previous timestep_ in update_forces_energy()
01728 // But we report values at the beginning of the timestep (value at t=0 on the first timestep)
01729 x_reported = x_ext;
01730 v_reported = v_ext;
01731 // the "total force" with the extended Lagrangian is
01732 // calculated in update_forces_energy() below
01733 
01734 } else {
01735 
01736 if (is_enabled(f_cv_subtract_applied_force)) {
01737 // correct the total force only if it has been measured
01738 // TODO add a specific test instead of relying on sq norm
01739 if (ft.norm2() > 0.0) {
01740 ft -= f_old;
01741 }
01742 }
01743 
01744 x_reported = x;
01745 ft_reported = ft;
01746 }
01747 
01748 // At the end of the first update after a restart, we can reset the flag
01749 after_restart = false;
01750 return COLVARS_OK;
01751 }
01752 
01753 
01754 cvm::real colvar::update_forces_energy()
01755 {
01756 if (cvm::debug())
01757 cvm::log("Updating colvar \""+this->name+"\".\n");
01758 
01759 // set to zero the applied force
01760 f.type(value());
01761 f.reset();
01762 fr.reset();
01763 
01764 // If we are not active at this timestep, that's all we have to do
01765 // return with energy == zero
01766 if (!is_enabled(f_cv_active)) return 0.;
01767 
01768 // add the biases' force, which at this point should already have
01769 // been summed over each bias using this colvar
01770 // fb is already multiplied by the relevant time step factor for each bias
01771 f += fb;
01772 
01773 if (is_enabled(f_cv_Jacobian)) {
01774 // the instantaneous Jacobian force was not included in the reported total force;
01775 // instead, it is subtracted from the applied force (silent Jacobian correction)
01776 // This requires the Jacobian term for the *current* timestep
01777 // Need to scale it for impulse MTS
01778 if (is_enabled(f_cv_hide_Jacobian))
01779 f -= fj * cvm::real(time_step_factor);
01780 }
01781 
01782 // At this point f is the force f from external biases that will be applied to the
01783 // extended variable if there is one
01784 if (is_enabled(f_cv_extended_Lagrangian) && cvm::proxy->simulation_running()) {
01785 update_extended_Lagrangian();
01786 }
01787 
01788 if (!is_enabled(f_cv_external)) {
01789 // Now adding the force on the actual colvar (for those biases that
01790 // bypass the extended Lagrangian mass)
01791 f += fb_actual;
01792 }
01793 
01794 if (cvm::debug())
01795 cvm::log("Done updating colvar \""+this->name+"\".\n");
01796 return (potential_energy + kinetic_energy);
01797 }
01798 
01799 
01800 void colvar::update_extended_Lagrangian()
01801 {
01802 if (cvm::debug()) {
01803 cvm::log("Updating extended-Lagrangian degree of freedom.\n");
01804 }
01805 
01806 if (prev_timestep > -1L) {
01807 // Keep track of slow timestep to integrate MTS colvars
01808 // the colvar checks the interval after waking up twice
01809 cvm::step_number n_timesteps = cvm::step_relative() - prev_timestep;
01810 if (n_timesteps != 0 && n_timesteps != time_step_factor) {
01811 cvm::error("Error: extended-Lagrangian " + description + " has timeStepFactor " +
01812 cvm::to_str(time_step_factor) + ", but was activated after " + cvm::to_str(n_timesteps) +
01813 " steps at timestep " + cvm::to_str(cvm::step_absolute()) + " (relative step: " +
01814 cvm::to_str(cvm::step_relative()) + ").\n" +
01815 "Make sure that this colvar is requested by biases at multiples of timeStepFactor.\n");
01816 return;
01817 }
01818 }
01819 
01820 // Integrate with slow timestep (if time_step_factor != 1)
01821 cvm::real dt = cvm::dt() * cvm::real(time_step_factor);
01822 
01823 colvarvalue f_ext(fr.type()); // force acting on the extended variable
01824 f_ext.reset();
01825 
01826 if (is_enabled(f_cv_external)) {
01827 // There are no forces on the "actual colvar" bc there is no gradient wrt atomic coordinates
01828 // So we apply this to the extended DOF
01829 f += fb_actual;
01830 }
01831 
01832 fr = f;
01833 // External force has been scaled for a 1-timestep impulse, scale it back because we will
01834 // integrate it with the colvar's own timestep factor
01835 f_ext = f / cvm::real(time_step_factor);
01836 
01837 colvarvalue f_system(fr.type()); // force exterted by the system on the extended DOF
01838 
01839 if (is_enabled(f_cv_external)) {
01840 // Add "alchemical" force from external variable
01841 f_system = cvcs[0]->total_force();
01842 // f is now irrelevant because we are not applying atomic forces in the simulation
01843 // just driving the external variable lambda
01844 } else {
01845 // the total force is applied to the fictitious mass, while the
01846 // atoms only feel the harmonic force + wall force
01847 // fr: bias force on extended variable (without harmonic spring), for output in trajectory
01848 // f_ext: total force on extended variable (including harmonic spring)
01849 // f: - initially, external biasing force
01850 // - after this code block, colvar force to be applied to atomic coordinates
01851 // ie. spring force (fb_actual will be added just below)
01852 f_system = (-0.5 * ext_force_k) * this->dist2_lgrad(x_ext, x);
01853 f = -1.0 * f_system;
01854 // Coupling force is a slow force, to be applied to atomic coords impulse-style
01855 // over a single MD timestep
01856 f *= cvm::real(time_step_factor);
01857 }
01858 f_ext += f_system;
01859 
01860 if (is_enabled(f_cv_subtract_applied_force)) {
01861 // Report a "system" force without the biases on this colvar
01862 // that is, just the spring force (or alchemical force)
01863 ft_reported = f_system;
01864 } else {
01865 // The total force acting on the extended variable is f_ext
01866 // This will be used in the next timestep
01867 ft_reported = f_ext;
01868 }
01869 
01870 // backup in case we need to revert this integration timestep
01871 // if the same MD timestep is re-run
01872 prev_x_ext = x_ext;
01873 prev_v_ext = v_ext;
01874 
01875 // leapfrog: starting from x_i, f_i, v_(i-1/2)
01876 v_ext += (0.5 * dt) * f_ext / ext_mass;
01877 // Because of leapfrog, kinetic energy at time i is approximate
01878 kinetic_energy = 0.5 * ext_mass * v_ext * v_ext;
01879 potential_energy = 0.5 * ext_force_k * this->dist2(x_ext, x);
01880 // leap to v_(i+1/2)
01881 if (is_enabled(f_cv_Langevin)) {
01882 v_ext -= dt * ext_gamma * v_ext;
01883 colvarvalue rnd(x);
01884 rnd.set_random();
01885 v_ext += dt * ext_sigma * rnd / ext_mass;
01886 }
01887 v_ext += (0.5 * dt) * f_ext / ext_mass;
01888 x_ext += dt * v_ext;
01889 
01890 cvm::real delta = 0; // Length of overshoot past either reflecting boundary
01891 if ((is_enabled(f_cv_reflecting_lower_boundary) && (delta = x_ext - lower_boundary) < 0) ||
01892 (is_enabled(f_cv_reflecting_upper_boundary) && (delta = x_ext - upper_boundary) > 0)) {
01893 x_ext -= 2.0 * delta;
01894 v_ext *= -1.0;
01895 if ((is_enabled(f_cv_reflecting_lower_boundary) && (delta = x_ext - lower_boundary) < 0) ||
01896 (is_enabled(f_cv_reflecting_upper_boundary) && (delta = x_ext - upper_boundary) > 0)) {
01897 cvm::error("Error: extended coordinate value " + cvm::to_str(x_ext) + " is still outside boundaries after reflection.\n");
01898 }
01899 }
01900 
01901 x_ext.apply_constraints();
01902 this->wrap(x_ext);
01903 if (is_enabled(f_cv_external)) {
01904 // Colvar value is constrained to the extended value
01905 x = x_ext;
01906 cvcs[0]->set_value(x_ext);
01907 }
01908 }
01909 
01910 
01911 int colvar::end_of_step()
01912 {
01913 if (cvm::debug())
01914 cvm::log("End of step for colvar \""+this->name+"\".\n");
01915 
01916 if (is_enabled(f_cv_fdiff_velocity)) {
01917 x_old = x;
01918 }
01919 
01920 if (is_enabled(f_cv_subtract_applied_force)) {
01921 f_old = f;
01922 }
01923 
01924 prev_timestep = cvm::step_relative();
01925 
01926 return COLVARS_OK;
01927 }
01928 
01929 
01930 void colvar::communicate_forces()
01931 {
01932 size_t i;
01933 if (cvm::debug()) {
01934 cvm::log("Communicating forces from colvar \""+this->name+"\".\n");
01935 cvm::log("Force to be applied: " + cvm::to_str(f) + "\n");
01936 }
01937 
01938 if (is_enabled(f_cv_scripted)) {
01939 std::vector<cvm::matrix2d<cvm::real> > func_grads;
01940 func_grads.reserve(cvcs.size());
01941 for (i = 0; i < cvcs.size(); i++) {
01942 if (!cvcs[i]->is_enabled()) continue;
01943 func_grads.push_back(cvm::matrix2d<cvm::real> (x.size(),
01944 cvcs[i]->value().size()));
01945 }
01946 int res = cvm::proxy->run_colvar_gradient_callback(scripted_function, sorted_cvc_values, func_grads);
01947 
01948 if (res != COLVARS_OK) {
01949 if (res == COLVARS_NOT_IMPLEMENTED) {
01950 cvm::error("Colvar gradient scripts are not implemented.", COLVARS_NOT_IMPLEMENTED);
01951 } else {
01952 cvm::error("Error running colvar gradient script");
01953 }
01954 return;
01955 }
01956 
01957 int grad_index = 0; // index in the scripted gradients, to account for some components being disabled
01958 for (i = 0; i < cvcs.size(); i++) {
01959 if (!cvcs[i]->is_enabled()) continue;
01960 // cvc force is colvar force times colvar/cvc Jacobian
01961 // (vector-matrix product)
01962 (cvcs[i])->apply_force(colvarvalue(f.as_vector() * func_grads[grad_index++],
01963 cvcs[i]->value().type()));
01964 }
01965 
01966 #ifdef LEPTON
01967 } else if (is_enabled(f_cv_custom_function)) {
01968 
01969 size_t r = 0; // index in the vector of variable references
01970 size_t e = 0; // index of the gradient evaluator
01971 
01972 for (i = 0; i < cvcs.size(); i++) { // gradient with respect to cvc i
01973 cvm::matrix2d<cvm::real> jacobian (x.size(), cvcs[i]->value().size());
01974 for (size_t j = 0; j < cvcs[i]->value().size(); j++) { // j-th element
01975 for (size_t c = 0; c < x.size(); c++) { // derivative of scalar element c of the colvarvalue
01976 
01977 // Feed cvc values to the evaluator
01978 for (size_t k = 0; k < cvcs.size(); k++) { //
01979 for (size_t l = 0; l < cvcs[k]->value().size(); l++) {
01980 *(grad_eval_var_refs[r++]) = cvcs[k]->value()[l];
01981 }
01982 }
01983 jacobian[c][j] = gradient_evaluators[e++]->evaluate();
01984 }
01985 }
01986 // cvc force is colvar force times colvar/cvc Jacobian
01987 // (vector-matrix product)
01988 (cvcs[i])->apply_force(colvarvalue(f.as_vector() * jacobian,
01989 cvcs[i]->value().type()));
01990 }
01991 #endif
01992 
01993 } else if (x.type() == colvarvalue::type_scalar) {
01994 
01995 for (i = 0; i < cvcs.size(); i++) {
01996 if (!cvcs[i]->is_enabled()) continue;
01997 (cvcs[i])->apply_force(f * (cvcs[i])->sup_coeff *
01998 cvm::real((cvcs[i])->sup_np) *
01999 (cvm::integer_power((cvcs[i])->value().real_value,
02000 (cvcs[i])->sup_np-1)) );
02001 }
02002 
02003 } else {
02004 
02005 for (i = 0; i < cvcs.size(); i++) {
02006 if (!cvcs[i]->is_enabled()) continue;
02007 (cvcs[i])->apply_force(f * (cvcs[i])->sup_coeff);
02008 }
02009 }
02010 
02011 if (cvm::debug())
02012 cvm::log("Done communicating forces from colvar \""+this->name+"\".\n");
02013 }
02014 
02015 
02016 int colvar::set_cvc_flags(std::vector<bool> const &flags)
02017 {
02018 if (flags.size() != cvcs.size()) {
02019 cvm::error("ERROR: Wrong number of CVC flags provided.");
02020 return COLVARS_ERROR;
02021 }
02022 // We cannot enable or disable cvcs in the middle of a timestep or colvar evaluation sequence
02023 // so we store the flags that will be enforced at the next call to calc()
02024 cvc_flags = flags;
02025 return COLVARS_OK;
02026 }
02027 
02028 
02029 void colvar::update_active_cvc_square_norm()
02030 {
02031 active_cvc_square_norm = 0.0;
02032 for (size_t i = 0; i < cvcs.size(); i++) {
02033 if (cvcs[i]->is_enabled()) {
02034 active_cvc_square_norm += cvcs[i]->sup_coeff * cvcs[i]->sup_coeff;
02035 }
02036 }
02037 }
02038 
02039 
02040 int colvar::update_cvc_flags()
02041 {
02042 // Update the enabled/disabled status of cvcs if necessary
02043 if (cvc_flags.size()) {
02044 n_active_cvcs = 0;
02045 for (size_t i = 0; i < cvcs.size(); i++) {
02046 cvcs[i]->set_enabled(f_cvc_active, cvc_flags[i]);
02047 if (cvcs[i]->is_enabled()) {
02048 n_active_cvcs++;
02049 }
02050 }
02051 if (!n_active_cvcs) {
02052 cvm::error("ERROR: All CVCs are disabled for colvar " + this->name +"\n");
02053 return COLVARS_ERROR;
02054 }
02055 cvc_flags.clear();
02056 
02057 update_active_cvc_square_norm();
02058 }
02059 
02060 return COLVARS_OK;
02061 }
02062 
02063 
02064 int colvar::update_cvc_config(std::vector<std::string> const &confs)
02065 {
02066 cvm::log("Updating configuration for colvar \""+name+"\"\n");
02067 
02068 if (confs.size() != cvcs.size()) {
02069 return cvm::error("Error: Wrong number of CVC config strings. "
02070 "For those CVCs that are not being changed, try passing "
02071 "an empty string.", COLVARS_INPUT_ERROR);
02072 }
02073 
02074 int error_code = COLVARS_OK;
02075 int num_changes = 0;
02076 for (size_t i = 0; i < cvcs.size(); i++) {
02077 if (confs[i].size()) {
02078 std::string conf(confs[i]);
02079 cvm::increase_depth();
02080 error_code |= cvcs[i]->colvar::cvc::init(conf);
02081 error_code |= cvcs[i]->check_keywords(conf,
02082 cvcs[i]->config_key.c_str());
02083 cvm::decrease_depth();
02084 num_changes++;
02085 }
02086 }
02087 
02088 if (num_changes == 0) {
02089 cvm::log("Warning: no changes were applied through modifycvcs; "
02090 "please check that its argument is a list of strings.\n");
02091 }
02092 
02093 update_active_cvc_square_norm();
02094 
02095 return error_code;
02096 }
02097 
02098 
02099 int colvar::cvc_param_exists(std::string const &param_name)
02100 {
02101 if (is_enabled(f_cv_single_cvc)) {
02102 return cvcs[0]->param_exists(param_name);
02103 }
02104 return cvm::error("Error: calling colvar::cvc_param_exists() for a variable "
02105 "with more than one component.\n", COLVARS_NOT_IMPLEMENTED);
02106 }
02107 
02108 
02109 cvm::real colvar::get_cvc_param(std::string const &param_name)
02110 {
02111 if (is_enabled(f_cv_single_cvc)) {
02112 return cvcs[0]->get_param(param_name);
02113 }
02114 cvm::error("Error: calling colvar::get_cvc_param() for a variable "
02115 "with more than one component.\n", COLVARS_NOT_IMPLEMENTED);
02116 return 0.0;
02117 }
02118 
02119 
02120 void const *colvar::get_cvc_param_ptr(std::string const &param_name)
02121 {
02122 if (is_enabled(f_cv_single_cvc)) {
02123 return cvcs[0]->get_param_ptr(param_name);
02124 }
02125 cvm::error("Error: calling colvar::get_cvc_param() for a variable "
02126 "with more than one component.\n", COLVARS_NOT_IMPLEMENTED);
02127 return NULL;
02128 }
02129 
02130 
02131 colvarvalue const *colvar::get_cvc_param_grad(std::string const &param_name)
02132 {
02133 if (is_enabled(f_cv_single_cvc)) {
02134 return cvcs[0]->get_param_grad(param_name);
02135 }
02136 cvm::error("Error: calling colvar::get_cvc_param_grad() for a variable "
02137 "with more than one component.\n", COLVARS_NOT_IMPLEMENTED);
02138 return NULL;
02139 }
02140 
02141 
02142 int colvar::set_cvc_param(std::string const &param_name, void const *new_value)
02143 {
02144 if (is_enabled(f_cv_single_cvc)) {
02145 return cvcs[0]->set_param(param_name, new_value);
02146 }
02147 return cvm::error("Error: calling colvar::set_cvc_param() for a variable "
02148 "with more than one component.\n", COLVARS_NOT_IMPLEMENTED);
02149 }
02150 
02151 
02152 // ******************** METRIC FUNCTIONS ********************
02153 // Use the metrics defined by \link colvar::cvc \endlink objects
02154 
02155 
02156 bool colvar::periodic_boundaries(colvarvalue const &lb, colvarvalue const &ub) const
02157 {
02158 if (period > 0.0) {
02159 if ( ((cvm::sqrt(this->dist2(lb, ub))) / this->width)
02160 < 1.0E-10 ) {
02161 return true;
02162 }
02163 }
02164 
02165 return false;
02166 }
02167 
02168 bool colvar::periodic_boundaries() const
02169 {
02170 if ( (!is_enabled(f_cv_lower_boundary)) || (!is_enabled(f_cv_upper_boundary)) ) {
02171 // Return false if answer is unknown at this time
02172 return false;
02173 }
02174 
02175 return periodic_boundaries(lower_boundary, upper_boundary);
02176 }
02177 
02178 
02179 cvm::real colvar::dist2(colvarvalue const &x1,
02180 colvarvalue const &x2) const
02181 {
02182 if ( is_enabled(f_cv_scripted) || is_enabled(f_cv_custom_function) ) {
02183 if (is_enabled(f_cv_periodic) && is_enabled(f_cv_scalar)) {
02184 cvm::real diff = x1.real_value - x2.real_value;
02185 const cvm::real period_lower_boundary = wrap_center - period / 2.0;
02186 const cvm::real period_upper_boundary = wrap_center + period / 2.0;
02187 diff = (diff < period_lower_boundary ? diff + period : ( diff > period_upper_boundary ? diff - period : diff));
02188 return diff * diff;
02189 }
02190 }
02191 if (is_enabled(f_cv_homogeneous)) {
02192 return (cvcs[0])->dist2(x1, x2);
02193 } else {
02194 return x1.dist2(x2);
02195 }
02196 }
02197 
02198 colvarvalue colvar::dist2_lgrad(colvarvalue const &x1,
02199 colvarvalue const &x2) const
02200 {
02201 if ( is_enabled(f_cv_scripted) || is_enabled(f_cv_custom_function) ) {
02202 if (is_enabled(f_cv_periodic) && is_enabled(f_cv_scalar)) {
02203 cvm::real diff = x1.real_value - x2.real_value;
02204 const cvm::real period_lower_boundary = wrap_center - period / 2.0;
02205 const cvm::real period_upper_boundary = wrap_center + period / 2.0;
02206 diff = (diff < period_lower_boundary ? diff + period : ( diff > period_upper_boundary ? diff - period : diff));
02207 return 2.0 * diff;
02208 }
02209 }
02210 if (is_enabled(f_cv_homogeneous)) {
02211 return (cvcs[0])->dist2_lgrad(x1, x2);
02212 } else {
02213 return x1.dist2_grad(x2);
02214 }
02215 }
02216 
02217 colvarvalue colvar::dist2_rgrad(colvarvalue const &x1,
02218 colvarvalue const &x2) const
02219 {
02220 if ( is_enabled(f_cv_scripted) || is_enabled(f_cv_custom_function) ) {
02221 if (is_enabled(f_cv_periodic) && is_enabled(f_cv_scalar)) {
02222 cvm::real diff = x1.real_value - x2.real_value;
02223 const cvm::real period_lower_boundary = wrap_center - period / 2.0;
02224 const cvm::real period_upper_boundary = wrap_center + period / 2.0;
02225 diff = (diff < period_lower_boundary ? diff + period : ( diff > period_upper_boundary ? diff - period : diff));
02226 return (-2.0) * diff;
02227 }
02228 }
02229 if (is_enabled(f_cv_homogeneous)) {
02230 return (cvcs[0])->dist2_rgrad(x1, x2);
02231 } else {
02232 return x2.dist2_grad(x1);
02233 }
02234 }
02235 
02236 
02237 void colvar::wrap(colvarvalue &x_unwrapped) const
02238 {
02239 if (!is_enabled(f_cv_periodic)) {
02240 return;
02241 }
02242 
02243 if ( is_enabled(f_cv_scripted) || is_enabled(f_cv_custom_function) ) {
02244 // Scripted functions do their own wrapping, as cvcs might not be periodic
02245 cvm::real shift = cvm::floor((x_unwrapped.real_value - wrap_center) /
02246 period + 0.5);
02247 x_unwrapped.real_value -= shift * period;
02248 } else {
02249 cvcs[0]->wrap(x_unwrapped);
02250 }
02251 }
02252 
02253 
02254 // ******************** INPUT FUNCTIONS ********************
02255 
02256 std::istream & colvar::read_state(std::istream &is)
02257 {
02258 std::streampos const start_pos = is.tellg();
02259 
02260 std::string conf;
02261 if ( !(is >> colvarparse::read_block("colvar", &conf)) ) {
02262 // this is not a colvar block
02263 is.clear();
02264 is.seekg(start_pos, std::ios::beg);
02265 is.setstate(std::ios::failbit);
02266 return is;
02267 }
02268 
02269 {
02270 std::string check_name = "";
02271 get_keyval(conf, "name", check_name,
02272 std::string(""), colvarparse::parse_silent);
02273 if (check_name.size() == 0) {
02274 cvm::error("Error: Collective variable in the "
02275 "restart file without any identifier.\n", COLVARS_INPUT_ERROR);
02276 is.clear();
02277 is.seekg(start_pos, std::ios::beg);
02278 is.setstate(std::ios::failbit);
02279 return is;
02280 }
02281 
02282 if (check_name != name) {
02283 if (cvm::debug()) {
02284 cvm::log("Ignoring state of colvar \""+check_name+
02285 "\": this colvar is named \""+name+"\".\n");
02286 }
02287 is.seekg(start_pos, std::ios::beg);
02288 return is;
02289 }
02290 }
02291 
02292 if ( !(get_keyval(conf, "x", x, x, colvarparse::parse_silent)) ) {
02293 cvm::log("Error: restart file does not contain "
02294 "the value of the colvar \""+
02295 name+"\" .\n");
02296 } else {
02297 cvm::log("Restarting collective variable \""+name+"\" from value: "+
02298 cvm::to_str(x)+"\n");
02299 x_restart = x;
02300 after_restart = true;
02301 }
02302 
02303 if (is_enabled(f_cv_extended_Lagrangian)) {
02304 if ( !(get_keyval(conf, "extended_x", x_ext,
02305 colvarvalue(x.type()), colvarparse::parse_silent)) ||
02306 !(get_keyval(conf, "extended_v", v_ext,
02307 colvarvalue(x.type()), colvarparse::parse_silent)) ) {
02308 cvm::log("Error: restart file does not contain "
02309 "\"extended_x\" or \"extended_v\" for the colvar \""+
02310 name+"\", but you requested \"extendedLagrangian\".\n");
02311 }
02312 x_reported = x_ext;
02313 } else {
02314 x_reported = x;
02315 }
02316 
02317 if (is_enabled(f_cv_output_velocity)) {
02318 
02319 if ( !(get_keyval(conf, "v", v_fdiff,
02320 colvarvalue(x.type()), colvarparse::parse_silent)) ) {
02321 cvm::log("Error: restart file does not contain "
02322 "the velocity for the colvar \""+
02323 name+"\", but you requested \"outputVelocity\".\n");
02324 }
02325 
02326 if (is_enabled(f_cv_extended_Lagrangian)) {
02327 v_reported = v_ext;
02328 } else {
02329 v_reported = v_fdiff;
02330 }
02331 }
02332 
02333 return is;
02334 }
02335 
02336 
02337 std::istream & colvar::read_traj(std::istream &is)
02338 {
02339 std::streampos const start_pos = is.tellg();
02340 
02341 if (is_enabled(f_cv_output_value)) {
02342 
02343 if (!(is >> x)) {
02344 cvm::log("Error: in reading the value of colvar \""+
02345 this->name+"\" from trajectory.\n");
02346 is.clear();
02347 is.seekg(start_pos, std::ios::beg);
02348 is.setstate(std::ios::failbit);
02349 return is;
02350 }
02351 
02352 if (is_enabled(f_cv_extended_Lagrangian)) {
02353 is >> x_ext;
02354 x_reported = x_ext;
02355 } else {
02356 x_reported = x;
02357 }
02358 }
02359 
02360 if (is_enabled(f_cv_output_velocity)) {
02361 
02362 is >> v_fdiff;
02363 
02364 if (is_enabled(f_cv_extended_Lagrangian)) {
02365 is >> v_ext;
02366 v_reported = v_ext;
02367 } else {
02368 v_reported = v_fdiff;
02369 }
02370 }
02371 
02372 if (is_enabled(f_cv_output_total_force)) {
02373 is >> ft;
02374 ft_reported = ft;
02375 }
02376 
02377 if (is_enabled(f_cv_output_applied_force)) {
02378 is >> f;
02379 }
02380 
02381 return is;
02382 }
02383 
02384 
02385 // ******************** OUTPUT FUNCTIONS ********************
02386 
02387 std::ostream & colvar::write_state(std::ostream &os) {
02388 
02389 os << "colvar {\n"
02390 << " name " << name << "\n"
02391 << " x "
02392 << std::setprecision(cvm::cv_prec)
02393 << std::setw(cvm::cv_width)
02394 << x << "\n";
02395 
02396 if (is_enabled(f_cv_output_velocity)) {
02397 os << " v "
02398 << std::setprecision(cvm::cv_prec)
02399 << std::setw(cvm::cv_width)
02400 << v_reported << "\n";
02401 }
02402 
02403 if (is_enabled(f_cv_extended_Lagrangian)) {
02404 os << " extended_x "
02405 << std::setprecision(cvm::cv_prec)
02406 << std::setw(cvm::cv_width)
02407 << x_reported << "\n"
02408 << " extended_v "
02409 << std::setprecision(cvm::cv_prec)
02410 << std::setw(cvm::cv_width)
02411 << v_reported << "\n";
02412 }
02413 
02414 os << "}\n\n";
02415 
02416 if (runave_outfile.size() > 0) {
02417 cvm::main()->proxy->flush_output_stream(runave_outfile);
02418 }
02419 
02420 return os;
02421 }
02422 
02423 
02424 std::ostream & colvar::write_traj_label(std::ostream & os)
02425 {
02426 size_t const this_cv_width = x.output_width(cvm::cv_width);
02427 
02428 os << " ";
02429 
02430 if (is_enabled(f_cv_output_value)) {
02431 
02432 os << " "
02433 << cvm::wrap_string(this->name, this_cv_width);
02434 
02435 if (is_enabled(f_cv_extended_Lagrangian) && !is_enabled(f_cv_external)) {
02436 // extended DOF
02437 os << " r_"
02438 << cvm::wrap_string(this->name, this_cv_width-2);
02439 }
02440 }
02441 
02442 if (is_enabled(f_cv_output_velocity)) {
02443 
02444 os << " v_"
02445 << cvm::wrap_string(this->name, this_cv_width-2);
02446 
02447 if (is_enabled(f_cv_extended_Lagrangian) && !is_enabled(f_cv_external)) {
02448 // extended DOF
02449 os << " vr_"
02450 << cvm::wrap_string(this->name, this_cv_width-3);
02451 }
02452 }
02453 
02454 if (is_enabled(f_cv_output_energy)) {
02455 os << " Ep_"
02456 << cvm::wrap_string(this->name, this_cv_width-3)
02457 << " Ek_"
02458 << cvm::wrap_string(this->name, this_cv_width-3);
02459 }
02460 
02461 if (is_enabled(f_cv_output_total_force)) {
02462 os << " ft_"
02463 << cvm::wrap_string(this->name, this_cv_width-3);
02464 }
02465 
02466 if (is_enabled(f_cv_output_applied_force)) {
02467 os << " fa_"
02468 << cvm::wrap_string(this->name, this_cv_width-3);
02469 }
02470 
02471 return os;
02472 }
02473 
02474 
02475 std::ostream & colvar::write_traj(std::ostream &os)
02476 {
02477 os << " ";
02478 if (is_enabled(f_cv_output_value)) {
02479 
02480 if (is_enabled(f_cv_extended_Lagrangian) && !is_enabled(f_cv_external)) {
02481 os << " "
02482 << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
02483 << x;
02484 }
02485 
02486 os << " "
02487 << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
02488 << x_reported;
02489 }
02490 
02491 if (is_enabled(f_cv_output_velocity)) {
02492 
02493 if (is_enabled(f_cv_extended_Lagrangian) && !is_enabled(f_cv_external)) {
02494 os << " "
02495 << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
02496 << v_fdiff;
02497 }
02498 
02499 os << " "
02500 << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
02501 << v_reported;
02502 }
02503 
02504 if (is_enabled(f_cv_output_energy)) {
02505 os << " "
02506 << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
02507 << potential_energy
02508 << " "
02509 << kinetic_energy;
02510 }
02511 
02512 
02513 if (is_enabled(f_cv_output_total_force)) {
02514 os << " "
02515 << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
02516 << ft_reported;
02517 }
02518 
02519 if (is_enabled(f_cv_output_applied_force)) {
02520 os << " "
02521 << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
02522 << applied_force();
02523 }
02524 
02525 return os;
02526 }
02527 
02528 
02529 int colvar::write_output_files()
02530 {
02531 int error_code = COLVARS_OK;
02532 
02533 if (is_enabled(f_cv_corrfunc)) {
02534 if (acf.size()) {
02535 if (acf_outfile.size() == 0) {
02536 acf_outfile = std::string(cvm::output_prefix()+"."+this->name+
02537 ".corrfunc.dat");
02538 }
02539 cvm::log("Writing correlation function to file \""+acf_outfile+"\".\n");
02540 cvm::backup_file(acf_outfile.c_str());
02541 std::ostream &acf_os = cvm::proxy->output_stream(acf_outfile,
02542 "colvar ACF file");
02543 if (!acf_os) {
02544 error_code |= COLVARS_FILE_ERROR;
02545 } else {
02546 error_code |= write_acf(acf_os);
02547 }
02548 cvm::proxy->close_output_stream(acf_outfile);
02549 }
02550 }
02551 
02552 return error_code;
02553 }
02554 
02555 
02556 
02557 // ******************** ANALYSIS FUNCTIONS ********************
02558 
02559 int colvar::analyze()
02560 {
02561 int error_code = COLVARS_OK;
02562 
02563 if (is_enabled(f_cv_runave)) {
02564 error_code |= calc_runave();
02565 }
02566 
02567 if (is_enabled(f_cv_corrfunc)) {
02568 error_code |= calc_acf();
02569 }
02570 
02571 return error_code;
02572 }
02573 
02574 
02575 inline void history_add_value(size_t const &history_length,
02576 std::list<colvarvalue> &history,
02577 colvarvalue const &new_value)
02578 {
02579 history.push_front(new_value);
02580 if (history.size() > history_length)
02581 history.pop_back();
02582 }
02583 
02584 
02585 inline void history_incr(std::list< std::list<colvarvalue> > &history,
02586 std::list< std::list<colvarvalue> >::iterator &history_p)
02587 {
02588 if ((++history_p) == history.end())
02589 history_p = history.begin();
02590 }
02591 
02592 
02593 int colvar::calc_acf()
02594 {
02595 // using here an acf_stride-long list of vectors for either
02596 // coordinates (acf_x_history) or velocities (acf_v_history); each vector can
02597 // contain up to acf_length values, which are contiguous in memory
02598 // representation but separated by acf_stride in the time series;
02599 // the pointer to each vector is changed at every step
02600 
02601 colvar const *cfcv = cvm::colvar_by_name(acf_colvar_name);
02602 if (cfcv == NULL) {
02603 return cvm::error("Error: collective variable \""+acf_colvar_name+
02604 "\" is not defined at this time.\n", COLVARS_INPUT_ERROR);
02605 }
02606 
02607 if (acf_x_history.empty() && acf_v_history.empty()) {
02608 
02609 // first-step operations
02610 
02611 if (colvarvalue::check_types(cfcv->value(), value())) {
02612 cvm::error("Error: correlation function between \""+cfcv->name+
02613 "\" and \""+this->name+"\" cannot be calculated, "
02614 "because their value types are different.\n",
02615 COLVARS_INPUT_ERROR);
02616 }
02617 acf_nframes = 0;
02618 
02619 cvm::log("Colvar \""+this->name+"\": initializing correlation function "
02620 "calculation.\n");
02621 
02622 if (acf.size() < acf_length+1)
02623 acf.resize(acf_length+1, 0.0);
02624 
02625 size_t i;
02626 switch (acf_type) {
02627 
02628 case acf_vel:
02629 // allocate space for the velocities history
02630 for (i = 0; i < acf_stride; i++) {
02631 acf_v_history.push_back(std::list<colvarvalue>());
02632 }
02633 acf_v_history_p = acf_v_history.begin();
02634 break;
02635 
02636 case acf_coor:
02637 case acf_p2coor:
02638 // allocate space for the coordinates history
02639 for (i = 0; i < acf_stride; i++) {
02640 acf_x_history.push_back(std::list<colvarvalue>());
02641 }
02642 acf_x_history_p = acf_x_history.begin();
02643 break;
02644 
02645 case acf_notset:
02646 default:
02647 break;
02648 }
02649 
02650 } else if (cvm::step_relative() > prev_timestep) {
02651 
02652 switch (acf_type) {
02653 
02654 case acf_vel:
02655 
02656 calc_vel_acf((*acf_v_history_p), cfcv->velocity());
02657 history_add_value(acf_length+acf_offset, *acf_v_history_p,
02658 cfcv->velocity());
02659 history_incr(acf_v_history, acf_v_history_p);
02660 break;
02661 
02662 case acf_coor:
02663 
02664 calc_coor_acf((*acf_x_history_p), cfcv->value());
02665 history_add_value(acf_length+acf_offset, *acf_x_history_p,
02666 cfcv->value());
02667 history_incr(acf_x_history, acf_x_history_p);
02668 break;
02669 
02670 case acf_p2coor:
02671 
02672 calc_p2coor_acf((*acf_x_history_p), cfcv->value());
02673 history_add_value(acf_length+acf_offset, *acf_x_history_p,
02674 cfcv->value());
02675 history_incr(acf_x_history, acf_x_history_p);
02676 break;
02677 
02678 case acf_notset:
02679 default:
02680 break;
02681 }
02682 }
02683 
02684 return COLVARS_OK;
02685 }
02686 
02687 
02688 void colvar::calc_vel_acf(std::list<colvarvalue> &v_list,
02689 colvarvalue const &v)
02690 {
02691 // loop over stored velocities and add to the ACF, but only if the
02692 // length is sufficient to hold an entire row of ACF values
02693 if (v_list.size() >= acf_length+acf_offset) {
02694 std::list<colvarvalue>::iterator vs_i = v_list.begin();
02695 std::vector<cvm::real>::iterator acf_i = acf.begin();
02696 
02697 for (size_t i = 0; i < acf_offset; i++)
02698 ++vs_i;
02699 
02700 // current vel with itself
02701 *(acf_i) += v.norm2();
02702 ++acf_i;
02703 
02704 // inner products of previous velocities with current (acf_i and
02705 // vs_i are updated)
02706 colvarvalue::inner_opt(v, vs_i, v_list.end(), acf_i);
02707 
02708 acf_nframes++;
02709 }
02710 }
02711 
02712 
02713 void colvar::calc_coor_acf(std::list<colvarvalue> &x_list,
02714 colvarvalue const &x_now)
02715 {
02716 // same as above but for coordinates
02717 if (x_list.size() >= acf_length+acf_offset) {
02718 std::list<colvarvalue>::iterator xs_i = x_list.begin();
02719 std::vector<cvm::real>::iterator acf_i = acf.begin();
02720 
02721 for (size_t i = 0; i < acf_offset; i++)
02722 ++xs_i;
02723 
02724 *(acf_i++) += x.norm2();
02725 
02726 colvarvalue::inner_opt(x_now, xs_i, x_list.end(), acf_i);
02727 
02728 acf_nframes++;
02729 }
02730 }
02731 
02732 
02733 void colvar::calc_p2coor_acf(std::list<colvarvalue> &x_list,
02734 colvarvalue const &x_now)
02735 {
02736 // same as above but with second order Legendre polynomial instead
02737 // of just the scalar product
02738 if (x_list.size() >= acf_length+acf_offset) {
02739 std::list<colvarvalue>::iterator xs_i = x_list.begin();
02740 std::vector<cvm::real>::iterator acf_i = acf.begin();
02741 
02742 for (size_t i = 0; i < acf_offset; i++)
02743 ++xs_i;
02744 
02745 // value of P2(0) = 1
02746 *(acf_i++) += 1.0;
02747 
02748 colvarvalue::p2leg_opt(x_now, xs_i, x_list.end(), acf_i);
02749 
02750 acf_nframes++;
02751 }
02752 }
02753 
02754 
02755 int colvar::write_acf(std::ostream &os)
02756 {
02757 if (!acf_nframes) {
02758 return COLVARS_OK;
02759 }
02760 
02761 os.setf(std::ios::scientific, std::ios::floatfield);
02762 os << "# ";
02763 switch (acf_type) {
02764 case acf_vel:
02765 os << "Velocity";
02766 break;
02767 case acf_coor:
02768 os << "Coordinate";
02769 break;
02770 case acf_p2coor:
02771 os << "Coordinate (2nd Legendre poly)";
02772 break;
02773 case acf_notset:
02774 default:
02775 break;
02776 }
02777 
02778 if (acf_colvar_name == name) {
02779 os << " autocorrelation function for variable \""
02780 << this->name << "\"\n";
02781 } else {
02782 os << " correlation function between variables \"" //
02783 << this->name << "\" and \"" << acf_colvar_name << "\"\n";
02784 }
02785 
02786 os << "# Number of samples = ";
02787 if (acf_normalize) {
02788 os << (acf_nframes-1) << " (one DoF is used for normalization)\n";
02789 } else {
02790 os << acf_nframes << "\n";
02791 }
02792 
02793 os << "# " << cvm::wrap_string("step", cvm::it_width-2) << " "
02794 << cvm::wrap_string("corrfunc(step)", cvm::cv_width) << "\n";
02795 
02796 cvm::real const acf_norm = acf.front() / cvm::real(acf_nframes);
02797 
02798 std::vector<cvm::real>::iterator acf_i;
02799 size_t it = acf_offset;
02800 for (acf_i = acf.begin(); acf_i != acf.end(); ++acf_i) {
02801 os << std::setw(cvm::it_width) << acf_stride * (it++) << " "
02802 << std::setprecision(cvm::cv_prec)
02803 << std::setw(cvm::cv_width)
02804 << ( acf_normalize ?
02805 (*acf_i)/(acf_norm * cvm::real(acf_nframes)) :
02806 (*acf_i)/(cvm::real(acf_nframes)) ) << "\n";
02807 }
02808 
02809 return os.good() ? COLVARS_OK : COLVARS_FILE_ERROR;
02810 }
02811 
02812 
02813 int colvar::calc_runave()
02814 {
02815 int error_code = COLVARS_OK;
02816 colvarproxy *proxy = cvm::main()->proxy;
02817 
02818 if (x_history.empty()) {
02819 
02820 runave.type(value().type());
02821 runave.reset();
02822 
02823 // first-step operationsf
02824 
02825 if (cvm::debug())
02826 cvm::log("Colvar \""+this->name+
02827 "\": initializing running average calculation.\n");
02828 
02829 acf_nframes = 0;
02830 
02831 x_history.push_back(std::list<colvarvalue>());
02832 x_history_p = x_history.begin();
02833 
02834 } else {
02835 
02836 if ( (cvm::step_relative() % runave_stride) == 0 &&
02837 (cvm::step_relative() > prev_timestep) ) {
02838 
02839 if ((*x_history_p).size() >= runave_length-1) {
02840 
02841 if (runave_outfile.size() == 0) {
02842 runave_outfile = std::string(cvm::output_prefix()+"."+
02843 this->name+".runave.traj");
02844 }
02845 
02846 if (! proxy->output_stream_exists(runave_outfile)) {
02847 size_t const this_cv_width = x.output_width(cvm::cv_width);
02848 std::ostream &runave_os = proxy->output_stream(runave_outfile,
02849 "colvar running average");
02850 runave_os.setf(std::ios::scientific, std::ios::floatfield);
02851 runave_os << "# " << cvm::wrap_string("step", cvm::it_width-2)
02852 << " "
02853 << cvm::wrap_string("running average", this_cv_width)
02854 << " "
02855 << cvm::wrap_string("running stddev", this_cv_width)
02856 << "\n";
02857 }
02858 
02859 runave = x;
02860 std::list<colvarvalue>::iterator xs_i;
02861 for (xs_i = (*x_history_p).begin();
02862 xs_i != (*x_history_p).end(); ++xs_i) {
02863 runave += (*xs_i);
02864 }
02865 runave *= 1.0 / cvm::real(runave_length);
02866 runave.apply_constraints();
02867 
02868 runave_variance = 0.0;
02869 runave_variance += this->dist2(x, runave);
02870 for (xs_i = (*x_history_p).begin();
02871 xs_i != (*x_history_p).end(); ++xs_i) {
02872 runave_variance += this->dist2(x, (*xs_i));
02873 }
02874 runave_variance *= 1.0 / cvm::real(runave_length-1);
02875 
02876 if (runave_outfile.size() > 0) {
02877 std::ostream &runave_os = proxy->output_stream(runave_outfile);
02878 runave_os << std::setw(cvm::it_width) << cvm::step_relative()
02879 << " "
02880 << std::setprecision(cvm::cv_prec)
02881 << std::setw(cvm::cv_width)
02882 << runave << " "
02883 << std::setprecision(cvm::cv_prec)
02884 << std::setw(cvm::cv_width)
02885 << cvm::sqrt(runave_variance) << "\n";
02886 }
02887 }
02888 
02889 history_add_value(runave_length, *x_history_p, x);
02890 }
02891 }
02892 
02893 return error_code;
02894 }
02895 
02896 // Static members
02897 
02898 std::vector<colvardeps::feature *> colvar::cv_features;

Generated on Mon Nov 17 02:45:42 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /