| version 1.34 | version 1.35 |
|---|
| |
| | |
| // -*- c++ -*- | // -*- c++ -*- |
| | |
| // This file is part of the Collective Variables module (Colvars). | // This file is part of the Collective Variables module (Colvars). |
| // The original version of Colvars and its updates are located at: | // The original version of Colvars and its updates are located at: |
| // https://github.com/colvars/colvars | // https://github.com/colvars/colvars |
| |
| // If you wish to distribute your changes, please submit them to the | // If you wish to distribute your changes, please submit them to the |
| // Colvars repository at GitHub. | // Colvars repository at GitHub. |
| | |
| | |
| #include "colvarmodule.h" | #include "colvarmodule.h" |
| #include "colvarvalue.h" | #include "colvarvalue.h" |
| #include "colvarparse.h" | #include "colvarparse.h" |
| #include "colvar.h" | #include "colvar.h" |
| #include "colvarcomp.h" | #include "colvarcomp.h" |
| #include "colvarscript.h" | #include "colvarscript.h" |
| | |
| | // used in build_atom_list() |
| #include <algorithm> | #include <algorithm> |
| | |
| | |
| |
| | |
| | |
| colvar::colvar() | colvar::colvar() |
| | : prev_timestep(-1) |
| { | { |
| // Initialize static array once and for all | // Initialize static array once and for all |
| init_cv_requires(); | init_cv_requires(); |
| |
| | |
| // 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()); | |
| | |
| x_old.type(value()); | x_old.type(value()); |
| v_fdiff.type(value()); | v_fdiff.type(value()); |
| |
| | |
| reset_bias_force(); | reset_bias_force(); |
| | |
| | get_keyval(conf, "timeStepFactor", time_step_factor, 1); |
| | if (time_step_factor < 0) { |
| | cvm::error("Error: timeStepFactor must be positive.\n"); |
| | return COLVARS_ERROR; |
| | } |
| | if (time_step_factor != 1) { |
| | enable(f_cv_multiple_ts); |
| | } |
| | |
| // TODO use here information from the CVCs' own natural boundaries | // TODO use here information from the CVCs' own natural boundaries |
| error_code |= init_grid_parameters(conf); | error_code |= init_grid_parameters(conf); |
| | |
| get_keyval(conf, "timeStepFactor", time_step_factor, 1); | |
| | |
| error_code |= init_extended_Lagrangian(conf); | error_code |= init_extended_Lagrangian(conf); |
| error_code |= init_output_flags(conf); | error_code |= init_output_flags(conf); |
| | |
| // Start in active state by default | // Now that the children are defined we can solve dependencies |
| enable(f_cv_active); | enable(f_cv_active); |
| // Make sure dependency side-effects are correct | |
| refresh_deps(); | |
| | |
| if (cvm::b_analysis) | if (cvm::b_analysis) |
| parse_analysis(conf); | parse_analysis(conf); |
| |
| std::string const walls_conf("\n\ | std::string const walls_conf("\n\ |
| harmonicWalls {\n\ | harmonicWalls {\n\ |
| name "+this->name+"w\n\ | name "+this->name+"w\n\ |
| colvars "+this->name+"\n"+lw_conf+uw_conf+ | colvars "+this->name+"\n"+lw_conf+uw_conf+"\ |
| | timeStepFactor "+cvm::to_str(time_step_factor)+"\n"+ |
| "}\n"); | "}\n"); |
| cv->append_new_config(walls_conf); | cv->append_new_config(walls_conf); |
| } | } |
| |
| if ( (cvcp->period != 0.0) || (cvcp->wrap_center != 0.0) ) { | if ( (cvcp->period != 0.0) || (cvcp->wrap_center != 0.0) ) { |
| if ( (cvcp->function_type != std::string("distance_z")) && | if ( (cvcp->function_type != std::string("distance_z")) && |
| (cvcp->function_type != std::string("dihedral")) && | (cvcp->function_type != std::string("dihedral")) && |
| | (cvcp->function_type != std::string("polar_phi")) && |
| (cvcp->function_type != std::string("spin_angle")) ) { | (cvcp->function_type != std::string("spin_angle")) ) { |
| cvm::error("Error: invalid use of period and/or " | cvm::error("Error: invalid use of period and/or " |
| "wrapAround in a \""+ | "wrapAround in a \""+ |
| |
| "on an axis", "distanceZ"); | "on an axis", "distanceZ"); |
| error_code |= init_components_type<distance_xy>(conf, "distance projection " | error_code |= init_components_type<distance_xy>(conf, "distance projection " |
| "on a plane", "distanceXY"); | "on a plane", "distanceXY"); |
| | error_code |= init_components_type<polar_theta>(conf, "spherical polar angle theta", |
| | "polarTheta"); |
| | error_code |= init_components_type<polar_phi>(conf, "spherical azimuthal angle phi", |
| | "polarPhi"); |
| error_code |= init_components_type<distance_inv>(conf, "average distance " | error_code |= init_components_type<distance_inv>(conf, "average distance " |
| "weighted by inverse power", "distanceInv"); | "weighted by inverse power", "distanceInv"); |
| error_code |= init_components_type<distance_pairs>(conf, "N1xN2-long vector " | error_code |= init_components_type<distance_pairs>(conf, "N1xN2-long vector " |
| |
| } | } |
| | |
| | |
| int colvar::refresh_deps() | void colvar::do_feature_side_effects(int id) |
| { | { |
| // If enabled features are changed upstream, the features below should be refreshed | // If enabled features are changed upstream, the features below should be refreshed |
| if (is_enabled(f_cv_total_force_calc)) { | switch (id) { |
| | case f_cv_total_force_calc: |
| cvm::request_total_force(); | cvm::request_total_force(); |
| } | break; |
| if (is_enabled(f_cv_collect_gradient) && atom_ids.size() == 0) { | case f_cv_collect_gradient: |
| | if (atom_ids.size() == 0) { |
| build_atom_list(); | build_atom_list(); |
| } | } |
| return COLVARS_OK; | break; |
| | } |
| } | } |
| | |
| | |
| |
| | |
| colvar::~colvar() | colvar::~colvar() |
| { | { |
| | // There is no need to call free_children_deps() here |
| | // because the children are cvcs and will be deleted |
| | // just below |
| | |
| // Clear references to this colvar's cvcs as children | // Clear references to this colvar's cvcs as children |
| // for dependency purposes | // for dependency purposes |
| remove_all_children(); | remove_all_children(); |
| |
| (cvcs[i])->calc_gradients(); | (cvcs[i])->calc_gradients(); |
| // if requested, propagate (via chain rule) the gradients above | // if requested, propagate (via chain rule) the gradients above |
| // to the atoms used to define the roto-translation | // to the atoms used to define the roto-translation |
| // This could be integrated in the CVC base class | (cvcs[i])->calc_fit_gradients(); |
| for (size_t ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) { | if ((cvcs[i])->is_enabled(f_cvc_debug_gradient)) |
| if (cvcs[i]->atom_groups[ig]->b_fit_gradients) | (cvcs[i])->debug_gradients(); |
| cvcs[i]->atom_groups[ig]->calc_fit_gradients(); | |
| | |
| if (cvcs[i]->is_enabled(f_cvc_debug_gradient)) { | |
| cvm::log("Debugging gradients for " + cvcs[i]->description); | |
| cvcs[i]->debug_gradients(cvcs[i]->atom_groups[ig]); | |
| } | |
| } | |
| } | } |
| | |
| cvm::decrease_depth(); | cvm::decrease_depth(); |
| |
| size_t i; | size_t i; |
| | |
| if (is_enabled(f_cv_collect_gradient)) { | if (is_enabled(f_cv_collect_gradient)) { |
| | |
| if (is_enabled(f_cv_scripted)) { | |
| cvm::error("Collecting atomic gradients is not implemented for " | |
| "scripted colvars.", COLVARS_NOT_IMPLEMENTED); | |
| return COLVARS_NOT_IMPLEMENTED; | |
| } | |
| | |
| // Collect the atomic gradients inside colvar object | // Collect the atomic gradients inside colvar object |
| for (unsigned int a = 0; a < atomic_gradients.size(); a++) { | for (unsigned int a = 0; a < atomic_gradients.size(); a++) { |
| atomic_gradients[a].reset(); | atomic_gradients[a].reset(); |
| |
| f.type(value()); | f.type(value()); |
| f.reset(); | f.reset(); |
| | |
| | // If we are not active at this timestep, that's all we have to do |
| | // return with energy == zero |
| | if (!is_enabled(f_cv_active)) return 0.; |
| | |
| // add the biases' force, which at this point should already have | // add the biases' force, which at this point should already have |
| // been summed over each bias using this colvar | // been summed over each bias using this colvar |
| f += fb; | f += fb; |
| |
| } | } |
| | |
| cvm::real dt = cvm::dt(); | cvm::real dt = cvm::dt(); |
| | |
| | if (prev_timestep > -1) { |
| | // Keep track of slow timestep to integrate MTS colvars |
| | // the colvar checks the interval after waking up twice |
| | int n_timesteps = cvm::step_relative() - prev_timestep; |
| | if (n_timesteps != 0 && n_timesteps != time_step_factor) { |
| | cvm::error("Error: extended-Lagrangian " + description + " has timeStepFactor " + |
| | cvm::to_str(time_step_factor) + ", but was activated after " + cvm::to_str(n_timesteps) + |
| | " steps at timestep " + cvm::to_str(cvm::step_absolute()) + " (relative step: " + |
| | cvm::to_str(cvm::step_relative()) + ").\n" + |
| | "Make sure that this colvar is requested by biases at multiples of timeStepFactor.\n"); |
| | return 0.; |
| | } |
| | } |
| | prev_timestep = cvm::step_relative(); |
| | |
| | // Integrate with slow timestep |
| | dt *= cvm::real(time_step_factor); |
| | |
| colvarvalue f_ext(fr.type()); // force acting on the extended variable | colvarvalue f_ext(fr.type()); // force acting on the extended variable |
| f_ext.reset(); | f_ext.reset(); |
| | |
| |
| // bypass the extended Lagrangian mass) | // bypass the extended Lagrangian mass) |
| f += fb_actual; | f += fb_actual; |
| | |
| // Store force to be applied, possibly summed over several timesteps | |
| f_accumulated += f; | |
| | |
| if (is_enabled(f_cv_fdiff_velocity)) { | if (is_enabled(f_cv_fdiff_velocity)) { |
| // set it for the next step | // set it for the next step |
| x_old = x; | x_old = x; |
| |
| 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"); | cvm::log("Force to be applied: " + cvm::to_str(f) + "\n"); |
| } | } |
| | |
| if (is_enabled(f_cv_scripted)) { | if (is_enabled(f_cv_scripted)) { |
| |
| if (!cvcs[i]->is_enabled()) continue; | if (!cvcs[i]->is_enabled()) continue; |
| // cvc force is colvar force times colvar/cvc Jacobian | // cvc force is colvar force times colvar/cvc Jacobian |
| // (vector-matrix product) | // (vector-matrix product) |
| (cvcs[i])->apply_force(colvarvalue(f_accumulated.as_vector() * func_grads[grad_index++], | (cvcs[i])->apply_force(colvarvalue(f.as_vector() * func_grads[grad_index++], |
| cvcs[i]->value().type())); | cvcs[i]->value().type())); |
| } | } |
| } else if (x.type() == colvarvalue::type_scalar) { | } else if (x.type() == colvarvalue::type_scalar) { |
| | |
| for (i = 0; i < cvcs.size(); i++) { | for (i = 0; i < cvcs.size(); i++) { |
| if (!cvcs[i]->is_enabled()) continue; | if (!cvcs[i]->is_enabled()) continue; |
| (cvcs[i])->apply_force(f_accumulated * (cvcs[i])->sup_coeff * | (cvcs[i])->apply_force(f * (cvcs[i])->sup_coeff * |
| cvm::real((cvcs[i])->sup_np) * | cvm::real((cvcs[i])->sup_np) * |
| (std::pow((cvcs[i])->value().real_value, | (std::pow((cvcs[i])->value().real_value, |
| (cvcs[i])->sup_np-1)) ); | (cvcs[i])->sup_np-1)) ); |
| |
| | |
| for (i = 0; i < cvcs.size(); i++) { | for (i = 0; i < cvcs.size(); i++) { |
| if (!cvcs[i]->is_enabled()) continue; | if (!cvcs[i]->is_enabled()) continue; |
| (cvcs[i])->apply_force(f_accumulated * (cvcs[i])->sup_coeff); | (cvcs[i])->apply_force(f * (cvcs[i])->sup_coeff); |
| } | } |
| } | } |
| | |
| // Accumulated forces have been applied, impulse-style | |
| // Reset to start accumulating again | |
| f_accumulated.reset(); | |
| | |
| if (cvm::debug()) | if (cvm::debug()) |
| cvm::log("Done communicating forces from colvar \""+this->name+"\".\n"); | cvm::log("Done communicating forces from colvar \""+this->name+"\".\n"); |
| } | } |
| |
| cvm::error("ERROR: All CVCs are disabled for colvar " + this->name +"\n"); | cvm::error("ERROR: All CVCs are disabled for colvar " + this->name +"\n"); |
| return COLVARS_ERROR; | return COLVARS_ERROR; |
| } | } |
| cvc_flags.resize(0); | cvc_flags.clear(); |
| } | } |
| | |
| return COLVARS_OK; | return COLVARS_OK; |