00001 #include "colvarmodule.h"
00002 #include "colvarvalue.h"
00003 #include "colvarbias.h"
00004
00005
00006 colvarbias::colvarbias (std::string const &conf, char const *key)
00007 : colvarparse()
00008 {
00009 cvm::log ("Initializing a new \""+std::string (key)+"\" instance.\n");
00010
00011 size_t rank = 1;
00012 std::string const key_str (key);
00013
00014 if (colvarparse::to_lower_cppstr (key_str) == std::string ("abf")) {
00015 rank = cvm::n_abf_biases+1;
00016 }
00017 if (colvarparse::to_lower_cppstr (key_str) == std::string ("harmonic")) {
00018 rank = cvm::n_harm_biases+1;
00019 }
00020 if (colvarparse::to_lower_cppstr (key_str) == std::string ("histogram")) {
00021 rank = cvm::n_histo_biases+1;
00022 }
00023 if (colvarparse::to_lower_cppstr (key_str) == std::string ("metadynamics")) {
00024 rank = cvm::n_meta_biases+1;
00025 }
00026
00027 get_keyval (conf, "name", name, key_str+cvm::to_str (rank));
00028
00029
00030 std::vector<std::string> colvars_str;
00031 if (get_keyval (conf, "colvars", colvars_str)) {
00032 for (size_t i = 0; i < colvars_str.size(); i++) {
00033 add_colvar (colvars_str[i]);
00034 }
00035 }
00036
00037 if (!colvars.size()) {
00038 cvm::fatal_error ("Error: no collective variables specified.\n");
00039 }
00040 }
00041
00042
00043 void colvarbias::add_colvar (std::string const &cv_name)
00044 {
00045 if (colvar *cvp = cvm::colvar_p (cv_name)) {
00046 cvp->enable (colvar::task_gradients);
00047 if (cvm::debug())
00048 cvm::log ("Applying this bias to collective variable \""+
00049 cvp->name+"\".\n");
00050 colvars.push_back (cvp);
00051 colvar_forces.push_back (colvarvalue (cvp->type()));
00052 } else {
00053 cvm::fatal_error ("Error: cannot find a colvar named \""+
00054 cv_name+"\".\n");
00055 }
00056 }
00057
00058
00059 void colvarbias::communicate_forces()
00060 {
00061 for (size_t i = 0; i < colvars.size(); i++) {
00062 if (cvm::debug()) {
00063 cvm::log ("Communicating a force to colvar \""+
00064 colvars[i]->name+"\", of type \""+
00065 colvarvalue::type_desc[colvars[i]->type()]+"\".\n");
00066 }
00067 colvars[i]->add_bias_force (colvar_forces[i]);
00068 }
00069 }
00070
00071
00072
00073 colvarbias_harmonic::colvarbias_harmonic (std::string const &conf,
00074 char const *key)
00075 : colvarbias (conf, key),
00076 force_k_target_nsteps (0), targets_nsteps (0)
00077 {
00078 get_keyval (conf, "forceConstant", force_k, 1.0);
00079 for (size_t i = 0; i < colvars.size(); i++) {
00080 if (colvars[i]->width != 1.0)
00081 cvm::log ("The force constant for colvar \""+colvars[i]->name+
00082 "\" will be rescaled to "+
00083 cvm::to_str (force_k/(colvars[i]->width*colvars[i]->width))+
00084 " according to the specified width.\n");
00085 }
00086
00087
00088 colvar_centers.resize (colvars.size());
00089 for (size_t i = 0; i < colvars.size(); i++) {
00090 colvar_centers[i].type (colvars[i]->type());
00091 }
00092 if (get_keyval (conf, "centers", colvar_centers, colvar_centers)) {
00093 for (size_t i = 0; i < colvars.size(); i++) {
00094 colvar_centers[i].apply_constraints();
00095 }
00096 } else {
00097 colvar_centers.clear();
00098 cvm::fatal_error ("Error: must define the initial centers of the restraints.\n");
00099 }
00100
00101 if (colvar_centers.size() != colvars.size())
00102 cvm::fatal_error ("Error: number of harmonic centers does not match "
00103 "that of collective variables.\n");
00104
00105
00106
00107
00108
00109 colvar_targets = colvar_centers;
00110 if (get_keyval (conf, "targets", colvar_targets, colvar_targets)) {
00111
00112 for (size_t i = 0; i < colvar_targets.size(); i++) {
00113 colvar_targets[i].apply_constraints();
00114 }
00115
00116 get_keyval (conf, "targetsNumSteps", targets_nsteps, 0);
00117 if (!targets_nsteps)
00118 cvm::fatal_error ("Error: the number of steps for moving "
00119 "the restraint centers must be non-zero.\n");
00120 } else {
00121 colvar_targets.clear();
00122 }
00123
00124 if (get_keyval (conf, "forceConstantTarget", force_k_target, 0.0)) {
00125 get_keyval (conf, "forceConstantTargetNumSteps", force_k_target_nsteps, 1000);
00126 if (!force_k_target_nsteps)
00127 cvm::fatal_error ("Error: the number of steps for changing "
00128 "the force constant must be non-zero.\n");
00129 }
00130
00131 if (cvm::debug())
00132 cvm::log ("Done initializing a new harmonic restraint bias.\n");
00133 }
00134
00135
00136 void colvarbias_harmonic::update()
00137 {
00138 if (cvm::debug())
00139 cvm::log ("Updating the harmonic bias \""+this->name+"\".\n");
00140
00141 for (size_t i = 0; i < colvars.size(); i++) {
00142 colvar_forces[i] =
00143 (-0.5) * force_k /
00144 (colvars[i]->width * colvars[i]->width) *
00145 colvars[i]->dist2_lgrad (colvars[i]->value(),
00146 colvar_centers[i]);
00147 if (cvm::debug())
00148 cvm::log ("dist_grad["+cvm::to_str (i)+
00149 "] = "+cvm::to_str (colvars[i]->dist2_lgrad (colvars[i]->value(),
00150 colvar_centers[i]))+"\n");
00151 }
00152
00153 if (cvm::debug())
00154 cvm::log ("Current forces for the harmonic bias \""+
00155 this->name+"\": "+cvm::to_str (colvar_forces)+".\n");
00156
00157 if (targets_nsteps) {
00158
00159 if (!target_steps.size()) {
00160
00161
00162 target_steps.resize (colvars.size());
00163 for (size_t i = 0; i < colvars.size(); i++) {
00164 target_steps[i] = (::sqrt (colvars[i]->dist2 (colvar_centers[i],
00165 colvar_targets[i]))) /
00166 cvm::real (targets_nsteps - cvm::step_absolute());
00167 }
00168 if (cvm::debug())
00169 cvm::log ("Center movements for the harmonic bias \""+
00170 this->name+"\": "+cvm::to_str (target_steps)+".\n");
00171 }
00172
00173 if (cvm::debug())
00174 cvm::log ("Current centers for the harmonic bias \""+
00175 this->name+"\": "+cvm::to_str (colvar_centers)+".\n");
00176
00177 if (cvm::step_absolute() < targets_nsteps) {
00178
00179 for (size_t i = 0; i < colvars.size(); i++) {
00180 colvarvalue const d2grad =
00181 colvars[i]->dist2_lgrad (colvar_centers[i],
00182 colvar_targets[i]);
00183 colvar_centers[i] += target_steps[i] * (-1.0/d2grad.norm()) * d2grad;
00184 colvar_centers[i].apply_constraints();
00185 }
00186 }
00187 }
00188
00189 if (cvm::debug())
00190 cvm::log ("Done updating the harmonic bias \""+this->name+"\".\n");
00191 }
00192
00193
00194 std::istream & colvarbias_harmonic::read_restart (std::istream &is)
00195 {
00196 size_t const start_pos = is.tellg();
00197
00198 cvm::log ("Restarting harmonic bias \""+
00199 this->name+"\".\n");
00200
00201 std::string key, brace, conf;
00202 if ( !(is >> key) || !(key == "harmonic") ||
00203 !(is >> brace) || !(brace == "{") ||
00204 !(is >> colvarparse::read_block ("configuration", conf)) ) {
00205
00206 cvm::log ("Error: in reading restart configuration for harmonic bias \""+
00207 this->name+"\" at position "+
00208 cvm::to_str (is.tellg())+" in stream.\n");
00209 is.clear();
00210 is.seekg (start_pos, std::ios::beg);
00211 is.setstate (std::ios::failbit);
00212 return is;
00213 }
00214
00215
00216 std::string name = "";
00217
00218
00219 if ( (colvarparse::get_keyval (conf, "name", name, std::string (""), colvarparse::parse_silent)) &&
00220 (name != this->name) )
00221 cvm::fatal_error ("Error: in the restart file, the "
00222 "\"harmonic\" block has a wrong name\n");
00223
00224 if (name.size() == 0) {
00225 cvm::fatal_error ("Error: \"harmonic\" block in the restart file "
00226 "has no identifiers.\n");
00227 }
00228
00229 if (targets_nsteps) {
00230 cvm::log ("Reading the updated restraint centers from the restart.\n");
00231 if (!get_keyval (conf, "centers", colvar_centers))
00232 cvm::fatal_error ("Error: restraint centers are missing in the restart.\n");
00233 }
00234
00235 if (force_k_target_nsteps) {
00236 cvm::log ("Reading the updated force constant from the restart.\n");
00237 if (!get_keyval (conf, "forceConstant", force_k))
00238 cvm::fatal_error ("Error: force cosntant is missing in the restart.\n");
00239 }
00240
00241 is >> brace;
00242 if (brace != "}") {
00243 cvm::fatal_error ("Error: corrupt restart information for harmonic bias \""+
00244 this->name+"\": no matching brace at position "+
00245 cvm::to_str (is.tellg())+" in the restart file.\n");
00246 is.setstate (std::ios::failbit);
00247 }
00248 return is;
00249 }
00250
00251
00252 std::ostream & colvarbias_harmonic::write_restart (std::ostream &os)
00253 {
00254 os << "harmonic {\n"
00255 << " configuration {\n"
00256
00257 << " name " << this->name << "\n";
00258
00259 if (targets_nsteps) {
00260 os << " centers ";
00261 for (size_t i = 0; i < colvars.size(); i++) {
00262 os << " " << colvar_centers[i];
00263 }
00264 os << "\n";
00265 }
00266
00267 if (force_k_target_nsteps) {
00268 os << " forceConstant "
00269 << std::setprecision (cvm::en_prec)
00270 << std::setw (cvm::en_width) << force_k << "\n";
00271 }
00272
00273 os << " }\n"
00274 << "}\n\n";
00275
00276 return os;
00277 }
00278