version 1.30 | version 1.31 |
---|
| |
| |
// -*- c++ -*- | // -*- c++ -*- |
| // This file is part of the Collective Variables module (Colvars). |
| // The original version of Colvars and its updates are located at: |
| // https://github.com/colvars/colvars |
| // Please update all Colvars source files before making any changes. |
| // If you wish to distribute your changes, please submit them to the |
| // Colvars repository at GitHub. |
| |
| |
#include "colvarmodule.h" | #include "colvarmodule.h" |
#include "colvarvalue.h" | #include "colvarvalue.h" |
| |
} | } |
| |
| |
colvar::colvar(std::string const &conf) | colvar::colvar() |
: colvarparse(conf) | { |
| // Initialize static array once and for all |
| init_cv_requires(); |
| } |
| |
| |
| int colvar::init(std::string const &conf) |
{ | { |
cvm::log("Initializing a new collective variable.\n"); | cvm::log("Initializing a new collective variable.\n"); |
| colvarparse::init(conf); |
| |
int error_code = COLVARS_OK; | int error_code = COLVARS_OK; |
| |
| colvarmodule *cv = cvm::main(); |
| |
get_keyval(conf, "name", this->name, | get_keyval(conf, "name", this->name, |
(std::string("colvar")+cvm::to_str(cvm::colvars.size()+1))); | (std::string("colvar")+cvm::to_str(cv->variables()->size()+1))); |
| |
if (cvm::colvar_by_name(this->name) != NULL) { | if ((cvm::colvar_by_name(this->name) != NULL) && |
| (cvm::colvar_by_name(this->name) != this)) { |
cvm::error("Error: this colvar cannot have the same name, \""+this->name+ | cvm::error("Error: this colvar cannot have the same name, \""+this->name+ |
"\", as another colvar.\n", | "\", as another colvar.\n", |
INPUT_ERROR); | INPUT_ERROR); |
return; | return INPUT_ERROR; |
} | } |
| |
// Initialize dependency members | // Initialize dependency members |
| |
| |
this->description = "colvar " + this->name; | this->description = "colvar " + this->name; |
| |
// Initialize static array once and for all | |
init_cv_requires(); | |
| |
kinetic_energy = 0.0; | kinetic_energy = 0.0; |
potential_energy = 0.0; | potential_energy = 0.0; |
| |
error_code |= init_components(conf); | error_code |= init_components(conf); |
if (error_code != COLVARS_OK) return; | if (error_code != COLVARS_OK) { |
| return cvm::get_error(); |
| } |
| |
size_t i; | size_t i; |
| |
| |
} | } |
} | } |
if (x.type() == colvarvalue::type_notset) { | if (x.type() == colvarvalue::type_notset) { |
cvm::error("Could not parse scripted colvar type."); | cvm::error("Could not parse scripted colvar type.", INPUT_ERROR); |
return; | return INPUT_ERROR; |
} | } |
| |
cvm::log(std::string("Expecting colvar value of type ") | cvm::log(std::string("Expecting colvar value of type ") |
| |
if (x.type() == colvarvalue::type_vector) { | if (x.type() == colvarvalue::type_vector) { |
int size; | int size; |
if (!get_keyval(conf, "scriptedFunctionVectorSize", size)) { | if (!get_keyval(conf, "scriptedFunctionVectorSize", size)) { |
cvm::error("Error: no size specified for vector scripted function."); | cvm::error("Error: no size specified for vector scripted function.", |
return; | INPUT_ERROR); |
| return INPUT_ERROR; |
} | } |
x.vector1d_value.resize(size); | x.vector1d_value.resize(size); |
} | } |
| |
} | } |
feature_states[f_cv_homogeneous]->enabled = homogeneous; | feature_states[f_cv_homogeneous]->enabled = homogeneous; |
} | } |
// Colvar is deemed periodic iff: | |
| // Colvar is deemed periodic if: |
// - it is homogeneous | // - it is homogeneous |
// - all cvcs are periodic | // - all cvcs are periodic |
// - all cvcs have the same period | // - all cvcs have the same period |
| if (cvcs[0]->b_periodic) { // TODO make this a CVC feature |
b_periodic = cvcs[0]->b_periodic && is_enabled(f_cv_homogeneous); | bool b_periodic = true; |
period = cvcs[0]->period; | period = cvcs[0]->period; |
for (i = 1; i < cvcs.size(); i++) { | for (i = 1; i < cvcs.size(); i++) { |
if (!cvcs[i]->b_periodic || cvcs[i]->period != period) { | if (!cvcs[i]->b_periodic || cvcs[i]->period != period) { |
b_periodic = false; | b_periodic = false; |
period = 0.0; | period = 0.0; |
| cvm::log("Warning: although one component is periodic, this colvar will " |
| "not be treated as periodic, either because the exponent is not " |
| "1, or because components of different periodicity are defined. " |
| "Make sure that you know what you are doing!"); |
} | } |
} | } |
feature_states[f_cv_periodic]->enabled = b_periodic; | feature_states[f_cv_periodic]->enabled = b_periodic; |
| } |
| |
// check that cvcs are compatible | // check that cvcs are compatible |
| |
for (i = 0; i < cvcs.size(); i++) { | for (i = 0; i < cvcs.size(); i++) { |
if ((cvcs[i])->b_periodic && !b_periodic) { | |
cvm::log("Warning: although this component is periodic, the colvar will " | |
"not be treated as periodic, either because the exponent is not " | |
"1, or because multiple components are present. Make sure that " | |
"you know what you are doing!"); | |
} | |
| |
// components may have different types only for scripted functions | // components may have different types only for scripted functions |
if (!is_enabled(f_cv_scripted) && (colvarvalue::check_types(cvcs[i]->value(), | if (!is_enabled(f_cv_scripted) && (colvarvalue::check_types(cvcs[i]->value(), |
| |
"by using components of different types. " | "by using components of different types. " |
"You must use the same type in order to " | "You must use the same type in order to " |
" sum them together.\n", INPUT_ERROR); | " sum them together.\n", INPUT_ERROR); |
return; | return INPUT_ERROR; |
} | } |
} | } |
| |
| |
// at this point, the colvar's type is defined | // at this point, the colvar's type is defined |
f.type(value()); | f.type(value()); |
f_accumulated.type(value()); | f_accumulated.type(value()); |
fb.type(value()); | |
| x_old.type(value()); |
| v_fdiff.type(value()); |
| v_reported.type(value()); |
| fj.type(value()); |
| ft.type(value()); |
| ft_reported.type(value()); |
| f_old.type(value()); |
| f_old.reset(); |
| |
| x_restart.type(value()); |
| after_restart = false; |
| |
| reset_bias_force(); |
| |
| // TODO use here information from the CVCs' own natural boundaries |
| error_code |= init_grid_parameters(conf); |
| |
| get_keyval(conf, "timeStepFactor", time_step_factor, 1); |
| |
| error_code |= init_extended_Lagrangian(conf); |
| error_code |= init_output_flags(conf); |
| |
| // Start in active state by default |
| enable(f_cv_active); |
| // Make sure dependency side-effects are correct |
| refresh_deps(); |
| |
| if (cvm::b_analysis) |
| parse_analysis(conf); |
| |
| if (cvm::debug()) |
| cvm::log("Done initializing collective variable \""+this->name+"\".\n"); |
| |
| return error_code; |
| } |
| |
| |
| int colvar::init_grid_parameters(std::string const &conf) |
| { |
| colvarmodule *cv = cvm::main(); |
| |
get_keyval(conf, "width", width, 1.0); | get_keyval(conf, "width", width, 1.0); |
if (width <= 0.0) { | if (width <= 0.0) { |
cvm::error("Error: \"width\" must be positive.\n", INPUT_ERROR); | cvm::error("Error: \"width\" must be positive.\n", INPUT_ERROR); |
return; | return INPUT_ERROR; |
} | } |
| |
// NOTE: not porting wall stuff to new deps, as this will change to a separate bias | |
// the grid functions will wait a little as well | |
| |
lower_boundary.type(value()); | lower_boundary.type(value()); |
lower_wall.type(value()); | |
| |
upper_boundary.type(value()); | upper_boundary.type(value()); |
upper_wall.type(value()); | upper_wall.type(value()); |
| |
provide(f_cv_lower_boundary); | provide(f_cv_lower_boundary); |
enable(f_cv_lower_boundary); | enable(f_cv_lower_boundary); |
} | } |
| std::string lw_conf, uw_conf; |
| |
get_keyval(conf, "lowerWallConstant", lower_wall_k, 0.0); | if (get_keyval(conf, "lowerWallConstant", lower_wall_k, 0.0, parse_silent)) { |
if (lower_wall_k > 0.0) { | cvm::log("Warning: lowerWallConstant and lowerWall are deprecated, " |
| "please define a harmonicWalls bias instead.\n"); |
| lower_wall.type(value()); |
get_keyval(conf, "lowerWall", lower_wall, lower_boundary); | get_keyval(conf, "lowerWall", lower_wall, lower_boundary); |
enable(f_cv_lower_wall); | lw_conf = std::string("\n\ |
| harmonicWalls {\n\ |
| name "+this->name+"lw\n\ |
| colvars "+this->name+"\n\ |
| forceConstant "+cvm::to_str(lower_wall_k*width*width)+"\n\ |
| lowerWalls "+cvm::to_str(lower_wall)+"\n\ |
| }\n"); |
| cv->append_new_config(lw_conf); |
} | } |
| |
if (get_keyval(conf, "upperBoundary", upper_boundary, upper_boundary)) { | if (get_keyval(conf, "upperBoundary", upper_boundary, upper_boundary)) { |
| |
enable(f_cv_upper_boundary); | enable(f_cv_upper_boundary); |
} | } |
| |
get_keyval(conf, "upperWallConstant", upper_wall_k, 0.0); | if (get_keyval(conf, "upperWallConstant", upper_wall_k, 0.0, parse_silent)) { |
if (upper_wall_k > 0.0) { | cvm::log("Warning: upperWallConstant and upperWall are deprecated, " |
| "please define a harmonicWalls bias instead.\n"); |
| upper_wall.type(value()); |
get_keyval(conf, "upperWall", upper_wall, upper_boundary); | get_keyval(conf, "upperWall", upper_wall, upper_boundary); |
enable(f_cv_upper_wall); | uw_conf = std::string("\n\ |
| harmonicWalls {\n\ |
| name "+this->name+"uw\n\ |
| colvars "+this->name+"\n\ |
| forceConstant "+cvm::to_str(upper_wall_k*width*width)+"\n\ |
| upperWalls "+cvm::to_str(upper_wall)+"\n\ |
| }\n"); |
| cv->append_new_config(uw_conf); |
| } |
| |
| if (lw_conf.size() && uw_conf.size()) { |
| if (lower_wall >= upper_wall) { |
| cvm::error("Error: the upper wall, "+ |
| cvm::to_str(upper_wall)+ |
| ", is not higher than the lower wall, "+ |
| cvm::to_str(lower_wall)+".\n", |
| INPUT_ERROR); |
| return INPUT_ERROR; |
| } |
} | } |
} | } |
| |
| |
", is not higher than the lower boundary, "+ | ", is not higher than the lower boundary, "+ |
cvm::to_str(lower_boundary)+".\n", | cvm::to_str(lower_boundary)+".\n", |
INPUT_ERROR); | INPUT_ERROR); |
} | return INPUT_ERROR; |
} | |
| |
if (is_enabled(f_cv_lower_wall) && is_enabled(f_cv_upper_wall)) { | |
if (lower_wall >= upper_wall) { | |
cvm::error("Error: the upper wall, "+ | |
cvm::to_str(upper_wall)+ | |
", is not higher than the lower wall, "+ | |
cvm::to_str(lower_wall)+".\n", | |
INPUT_ERROR); | |
} | } |
} | } |
| |
| |
cvm::error("Error: trying to expand boundaries that already " | cvm::error("Error: trying to expand boundaries that already " |
"cover a whole period of a periodic colvar.\n", | "cover a whole period of a periodic colvar.\n", |
INPUT_ERROR); | INPUT_ERROR); |
| return INPUT_ERROR; |
} | } |
if (expand_boundaries && hard_lower_boundary && hard_upper_boundary) { | if (expand_boundaries && hard_lower_boundary && hard_upper_boundary) { |
cvm::error("Error: inconsistent configuration " | cvm::error("Error: inconsistent configuration " |
"(trying to expand boundaries with both " | "(trying to expand boundaries with both " |
"hardLowerBoundary and hardUpperBoundary enabled).\n", | "hardLowerBoundary and hardUpperBoundary enabled).\n", |
INPUT_ERROR); | INPUT_ERROR); |
| return INPUT_ERROR; |
| } |
| |
| return COLVARS_OK; |
} | } |
| |
get_keyval(conf, "timeStepFactor", time_step_factor, 1); | |
| |
| int colvar::init_extended_Lagrangian(std::string const &conf) |
{ | { |
bool b_extended_Lagrangian; | bool b_extended_Lagrangian; |
get_keyval(conf, "extendedLagrangian", b_extended_Lagrangian, false); | get_keyval(conf, "extendedLagrangian", b_extended_Lagrangian, false); |
| |
enable(f_cv_extended_Lagrangian); | enable(f_cv_extended_Lagrangian); |
provide(f_cv_Langevin); | provide(f_cv_Langevin); |
| |
| // The extended mass will apply forces |
| enable(f_cv_gradient); |
| |
xr.type(value()); | xr.type(value()); |
vr.type(value()); | vr.type(value()); |
fr.type(value()); | fr.type(value()); |
| |
cvm::error("Error: a positive temperature must be provided, either " | cvm::error("Error: a positive temperature must be provided, either " |
"by enabling a thermostat, or through \"extendedTemp\".\n", | "by enabling a thermostat, or through \"extendedTemp\".\n", |
INPUT_ERROR); | INPUT_ERROR); |
| return INPUT_ERROR; |
} | } |
| |
get_keyval(conf, "extendedFluctuation", tolerance); | get_keyval(conf, "extendedFluctuation", tolerance); |
if (tolerance <= 0.0) { | if (tolerance <= 0.0) { |
cvm::error("Error: \"extendedFluctuation\" must be positive.\n", INPUT_ERROR); | cvm::error("Error: \"extendedFluctuation\" must be positive.\n", INPUT_ERROR); |
| return INPUT_ERROR; |
} | } |
ext_force_k = cvm::boltzmann() * temp / (tolerance * tolerance); | ext_force_k = cvm::boltzmann() * temp / (tolerance * tolerance); |
cvm::log("Computed extended system force constant: " + cvm::to_str(ext_force_k) + " kcal/mol/U^2"); | cvm::log("Computed extended system force constant: " + cvm::to_str(ext_force_k) + " kcal/mol/U^2"); |
| |
get_keyval(conf, "extendedLangevinDamping", ext_gamma, 1.0); | get_keyval(conf, "extendedLangevinDamping", ext_gamma, 1.0); |
if (ext_gamma < 0.0) { | if (ext_gamma < 0.0) { |
cvm::error("Error: \"extendedLangevinDamping\" may not be negative.\n", INPUT_ERROR); | cvm::error("Error: \"extendedLangevinDamping\" may not be negative.\n", INPUT_ERROR); |
| return INPUT_ERROR; |
} | } |
if (ext_gamma != 0.0) { | if (ext_gamma != 0.0) { |
enable(f_cv_Langevin); | enable(f_cv_Langevin); |
| |
ext_sigma = std::sqrt(2.0 * cvm::boltzmann() * temp * ext_gamma * ext_mass / cvm::dt()); | ext_sigma = std::sqrt(2.0 * cvm::boltzmann() * temp * ext_gamma * ext_mass / cvm::dt()); |
} | } |
} | } |
| |
| return COLVARS_OK; |
} | } |
| |
| |
| int colvar::init_output_flags(std::string const &conf) |
| { |
{ | { |
bool b_output_value; | bool b_output_value; |
get_keyval(conf, "outputValue", b_output_value, true); | get_keyval(conf, "outputValue", b_output_value, true); |
| |
if (get_keyval(conf, "outputSystemForce", temp, false, colvarparse::parse_silent)) { | if (get_keyval(conf, "outputSystemForce", temp, false, colvarparse::parse_silent)) { |
cvm::error("Option outputSystemForce is deprecated: only outputTotalForce is supported instead.\n" | cvm::error("Option outputSystemForce is deprecated: only outputTotalForce is supported instead.\n" |
"The two are NOT identical: see http://colvars.github.io/totalforce.html.\n", INPUT_ERROR); | "The two are NOT identical: see http://colvars.github.io/totalforce.html.\n", INPUT_ERROR); |
return; | return INPUT_ERROR; |
} | } |
} | } |
| |
| |
get_keyval_feature(this, conf, "outputAppliedForce", f_cv_output_applied_force, false); | get_keyval_feature(this, conf, "outputAppliedForce", f_cv_output_applied_force, false); |
get_keyval_feature(this, conf, "subtractAppliedForce", f_cv_subtract_applied_force, false); | get_keyval_feature(this, conf, "subtractAppliedForce", f_cv_subtract_applied_force, false); |
| |
// Start in active state by default | return COLVARS_OK; |
enable(f_cv_active); | |
// Make sure dependency side-effects are correct | |
refresh_deps(); | |
| |
x_old.type(value()); | |
v_fdiff.type(value()); | |
v_reported.type(value()); | |
fj.type(value()); | |
ft.type(value()); | |
ft_reported.type(value()); | |
f_old.type(value()); | |
f_old.reset(); | |
| |
if (cvm::b_analysis) | |
parse_analysis(conf); | |
| |
if (cvm::debug()) | |
cvm::log("Done initializing collective variable \""+this->name+"\".\n"); | |
} | } |
| |
| |
| |
| |
std::string runave_outfile; | std::string runave_outfile; |
get_keyval(conf, "runAveOutputFile", runave_outfile, | get_keyval(conf, "runAveOutputFile", runave_outfile, |
std::string(cvm::output_prefix+"."+ | std::string(cvm::output_prefix()+"."+ |
this->name+".runave.traj")); | this->name+".runave.traj")); |
| |
size_t const this_cv_width = x.output_width(cvm::cv_width); | size_t const this_cv_width = x.output_width(cvm::cv_width); |
| |
| |
get_keyval(conf, "corrFuncNormalize", acf_normalize, true); | get_keyval(conf, "corrFuncNormalize", acf_normalize, true); |
get_keyval(conf, "corrFuncOutputFile", acf_outfile, | get_keyval(conf, "corrFuncOutputFile", acf_outfile, |
std::string(cvm::output_prefix+"."+this->name+ | std::string(cvm::output_prefix()+"."+this->name+ |
".corrfunc.dat")); | ".corrfunc.dat")); |
} | } |
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); | return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); |
| |
} | } |
| |
// remove reference to this colvar from the CVM | // remove reference to this colvar from the CVM |
for (std::vector<colvar *>::iterator cvi = cvm::colvars.begin(); | colvarmodule *cv = cvm::main(); |
cvi != cvm::colvars.end(); | for (std::vector<colvar *>::iterator cvi = cv->variables()->begin(); |
| cvi != cv->variables()->end(); |
++cvi) { | ++cvi) { |
if ( *cvi == this) { | if ( *cvi == this) { |
cvm::colvars.erase(cvi); | cv->variables()->erase(cvi); |
break; | break; |
} | } |
} | } |
| |
cvm::log("Colvar \""+this->name+"\" has value "+ | cvm::log("Colvar \""+this->name+"\" has value "+ |
cvm::to_str(x, cvm::cv_width, cvm::cv_prec)+".\n"); | cvm::to_str(x, cvm::cv_width, cvm::cv_prec)+".\n"); |
| |
| if (after_restart) { |
| after_restart = false; |
| if (cvm::proxy->simulation_running()) { |
| cvm::real const jump2 = dist2(x, x_restart) / (width*width); |
| if (jump2 > 0.25) { |
| cvm::error("Error: the calculated value of colvar \""+name+ |
| "\":\n"+cvm::to_str(x)+"\n differs greatly from the value " |
| "last read from the state file:\n"+cvm::to_str(x_restart)+ |
| "\nPossible causes are changes in configuration, " |
| "wrong state file, or how PBC wrapping is handled.\n", |
| INPUT_ERROR); |
| return INPUT_ERROR; |
| } |
| } |
| } |
| |
return COLVARS_OK; | return COLVARS_OK; |
} | } |
| |
| |
if (cvm::debug()) | if (cvm::debug()) |
cvm::log("Calculating total force of colvar \""+this->name+"\".\n"); | cvm::log("Calculating total force of colvar \""+this->name+"\".\n"); |
| |
// if (!tasks[task_extended_lagrangian] && (cvm::step_relative() > 0)) { | |
// Disabled check to allow for explicit total force calculation | |
// even with extended Lagrangian | |
cvm::increase_depth(); | cvm::increase_depth(); |
| |
for (i = first_cvc, cvc_count = 0; | for (i = first_cvc, cvc_count = 0; |
| |
// get from the cvcs the total forces from the PREVIOUS step | // get from the cvcs the total forces from the PREVIOUS step |
for (size_t i = 0; i < cvcs.size(); i++) { | for (size_t i = 0; i < cvcs.size(); i++) { |
if (!cvcs[i]->is_enabled()) continue; | if (!cvcs[i]->is_enabled()) continue; |
| if (cvm::debug()) |
| cvm::log("Colvar component no. "+cvm::to_str(i+1)+ |
| " within colvar \""+this->name+"\" has total force "+ |
| cvm::to_str((cvcs[i])->total_force(), |
| cvm::cv_width, cvm::cv_prec)+".\n"); |
// linear combination is assumed | // linear combination is assumed |
ft += (cvcs[i])->total_force() * (cvcs[i])->sup_coeff / active_cvc_square_norm; | ft += (cvcs[i])->total_force() * (cvcs[i])->sup_coeff / active_cvc_square_norm; |
} | } |
| |
fj.reset(); | fj.reset(); |
for (size_t i = 0; i < cvcs.size(); i++) { | for (size_t i = 0; i < cvcs.size(); i++) { |
if (!cvcs[i]->is_enabled()) continue; | if (!cvcs[i]->is_enabled()) continue; |
| if (cvm::debug()) |
| cvm::log("Colvar component no. "+cvm::to_str(i+1)+ |
| " within colvar \""+this->name+"\" has Jacobian derivative"+ |
| cvm::to_str((cvcs[i])->Jacobian_derivative(), |
| cvm::cv_width, cvm::cv_prec)+".\n"); |
// linear combination is assumed | // linear combination is assumed |
fj += (cvcs[i])->Jacobian_derivative() * (cvcs[i])->sup_coeff / active_cvc_square_norm; | fj += (cvcs[i])->Jacobian_derivative() * (cvcs[i])->sup_coeff / active_cvc_square_norm; |
} | } |
| |
f -= fj; | f -= fj; |
} | } |
| |
// Wall force | |
colvarvalue fw(x); | |
fw.reset(); | |
| |
if (is_enabled(f_cv_lower_wall) || is_enabled(f_cv_upper_wall)) { | |
| |
if (cvm::debug()) | |
cvm::log("Calculating wall forces for colvar \""+this->name+"\".\n"); | |
| |
// For a periodic colvar, both walls may be applicable at the same time | |
// in which case we pick the closer one | |
if ( (!is_enabled(f_cv_upper_wall)) || | |
(this->dist2(x, lower_wall) < this->dist2(x, upper_wall)) ) { | |
| |
cvm::real const grad = this->dist2_lgrad(x, lower_wall); | |
if (grad < 0.0) { | |
fw = -0.5 * lower_wall_k * grad; | |
if (cvm::debug()) | |
cvm::log("Applying a lower wall force("+ | |
cvm::to_str(fw)+") to \""+this->name+"\".\n"); | |
} | |
| |
} else { | |
| |
cvm::real const grad = this->dist2_lgrad(x, upper_wall); | |
if (grad > 0.0) { | |
fw = -0.5 * upper_wall_k * grad; | |
if (cvm::debug()) | |
cvm::log("Applying an upper wall force("+ | |
cvm::to_str(fw)+") to \""+this->name+"\".\n"); | |
} | |
} | |
} | |
| |
// At this point f is the force f from external biases that will be applied to the | // At this point f is the force f from external biases that will be applied to the |
// extended variable if there is one | // extended variable if there is one |
| |
if (is_enabled(f_cv_extended_Lagrangian)) { | if (is_enabled(f_cv_extended_Lagrangian)) { |
| |
| if (cvm::debug()) { |
| cvm::log("Updating extended-Lagrangian degrees of freedom.\n"); |
| } |
| |
cvm::real dt = cvm::dt(); | cvm::real dt = cvm::dt(); |
colvarvalue f_ext(fr.type()); | colvarvalue f_ext(fr.type()); |
f_ext.reset(); | f_ext.reset(); |
| |
// f_ext: total force on extended variable (including harmonic spring) | // f_ext: total force on extended variable (including harmonic spring) |
// f: - initially, external biasing force | // f: - initially, external biasing force |
// - after this code block, colvar force to be applied to atomic coordinates | // - after this code block, colvar force to be applied to atomic coordinates |
// ie. spring force + wall force | // ie. spring force (fb_actual will be added just below) |
fr = f; | fr = f; |
f_ext = f + (-0.5 * ext_force_k) * this->dist2_lgrad(xr, x); | f_ext = f + (-0.5 * ext_force_k) * this->dist2_lgrad(xr, x); |
f = (-0.5 * ext_force_k) * this->dist2_rgrad(xr, x); | f = (-0.5 * ext_force_k) * this->dist2_rgrad(xr, x); |
| |
if (this->is_enabled(f_cv_periodic)) this->wrap(xr); | if (this->is_enabled(f_cv_periodic)) this->wrap(xr); |
} | } |
| |
f += fw; | // Now adding the force on the actual colvar (for those biases who |
| // bypass the extended Lagrangian mass) |
| f += fb_actual; |
| |
// Store force to be applied, possibly summed over several timesteps | // Store force to be applied, possibly summed over several timesteps |
f_accumulated += f; | f_accumulated += f; |
| |
void colvar::communicate_forces() | void colvar::communicate_forces() |
{ | { |
size_t i; | size_t i; |
if (cvm::debug()) | if (cvm::debug()) { |
cvm::log("Communicating forces from colvar \""+this->name+"\".\n"); | cvm::log("Communicating forces from colvar \""+this->name+"\".\n"); |
| cvm::log("Force to be applied: " + cvm::to_str(f_accumulated) + "\n"); |
| } |
| |
if (is_enabled(f_cv_scripted)) { | if (is_enabled(f_cv_scripted)) { |
std::vector<cvm::matrix2d<cvm::real> > func_grads; | std::vector<cvm::matrix2d<cvm::real> > func_grads; |
| |
} | } |
} | } |
| |
if ( !(get_keyval(conf, "x", x, | if ( !(get_keyval(conf, "x", x, x, colvarparse::parse_silent)) ) { |
colvarvalue(x.type()), colvarparse::parse_silent)) ) { | |
cvm::log("Error: restart file does not contain " | cvm::log("Error: restart file does not contain " |
"the value of the colvar \""+ | "the value of the colvar \""+ |
name+"\" .\n"); | name+"\" .\n"); |
} else { | } else { |
cvm::log("Restarting collective variable \""+name+"\" from value: "+ | cvm::log("Restarting collective variable \""+name+"\" from value: "+ |
cvm::to_str(x)+"\n"); | cvm::to_str(x)+"\n"); |
| x_restart = x; |
| after_restart = true; |
} | } |
| |
if (is_enabled(f_cv_extended_Lagrangian)) { | if (is_enabled(f_cv_extended_Lagrangian)) { |