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

colvarbias_alb.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 <iostream>
00011 #include <iomanip>
00012 #include <cstdlib>
00013 
00014 #include "colvarmodule.h"
00015 #include "colvarproxy.h"
00016 #include "colvarbias.h"
00017 #include "colvarbias_alb.h"
00018 
00019 #ifdef _MSC_VER
00020 #if _MSC_VER <= 1700
00021 #define copysign(A,B) _copysign(A,B)
00022 double fmax(double A, double B) { return ( A > B ? A : B ); }
00023 double fmin(double A, double B) { return ( A < B ? A : B ); }
00024 #endif
00025 #endif
00026 
00027 /* Note about nomenclature. Force constant is called a coupling
00028 * constant here to emphasize its changing in the code. Outwards,
00029 * everything is called a force constant to keep it consistent with
00030 * the rest of colvars.
00031 *
00032 */
00033 
00034 colvarbias_alb::colvarbias_alb(char const *key)
00035 : colvarbias(key), update_calls(0), b_equilibration(true)
00036 {
00037 }
00038 
00039 
00040 int colvarbias_alb::init(std::string const &conf)
00041 {
00042 colvarproxy *proxy = cvm::main()->proxy;
00043 colvarbias::init(conf);
00044 cvm::main()->cite_feature("ALB colvar bias implementation");
00045 
00046 enable(f_cvb_scalar_variables);
00047 
00048 size_t i;
00049 
00050 // get the initial restraint centers
00051 colvar_centers.resize(num_variables());
00052 
00053 means.resize(num_variables());
00054 ssd.resize(num_variables()); //sum of squares of differences from mean
00055 
00056 //setup force vectors
00057 max_coupling_range.resize(num_variables());
00058 max_coupling_rate.resize(num_variables());
00059 coupling_accum.resize(num_variables());
00060 set_coupling.resize(num_variables());
00061 current_coupling.resize(num_variables());
00062 coupling_rate.resize(num_variables());
00063 
00064 enable(f_cvb_apply_force);
00065 
00066 for (i = 0; i < num_variables(); i++) {
00067 colvar_centers[i].type(colvars[i]->value());
00068 //zero moments
00069 means[i] = ssd[i] = 0;
00070 
00071 //zero force some of the force vectors that aren't initialized
00072 coupling_accum[i] = current_coupling[i] = 0;
00073 
00074 }
00075 if (get_keyval(conf, "centers", colvar_centers, colvar_centers)) {
00076 for (i = 0; i < num_variables(); i++) {
00077 colvar_centers[i].apply_constraints();
00078 }
00079 } else {
00080 colvar_centers.clear();
00081 cvm::error("Error: must define the initial centers of adaptive linear bias .\n");
00082 }
00083 
00084 if (colvar_centers.size() != num_variables())
00085 cvm::error("Error: number of centers does not match "
00086 "that of collective variables.\n");
00087 
00088 if (!get_keyval(conf, "UpdateFrequency", update_freq, 0))
00089 cvm::error("Error: must set updateFrequency for adaptive linear bias.\n");
00090 
00091 //we split the time between updating and equilibrating
00092 update_freq /= 2;
00093 
00094 if (update_freq <= 1)
00095 cvm::error("Error: must set updateFrequency to greater than 2.\n");
00096 
00097 enable(f_cvb_history_dependent);
00098 
00099 get_keyval(conf, "outputCenters", b_output_centers, false);
00100 get_keyval(conf, "outputGradient", b_output_grad, false);
00101 get_keyval(conf, "outputCoupling", b_output_coupling, true);
00102 get_keyval(conf, "hardForceRange", b_hard_coupling_range, true);
00103 
00104 //initial guess
00105 if (!get_keyval(conf, "forceConstant", set_coupling, set_coupling))
00106 for (i =0 ; i < num_variables(); i++)
00107 set_coupling[i] = 0.;
00108 
00109 //how we're going to increase to that point
00110 for (i = 0; i < num_variables(); i++)
00111 coupling_rate[i] = (set_coupling[i] - current_coupling[i]) / update_freq;
00112 
00113 
00114 if (!get_keyval(conf, "forceRange", max_coupling_range, max_coupling_range)) {
00115 //set to default
00116 for (i = 0; i < num_variables(); i++) {
00117 if (proxy->target_temperature() > 0.0) {
00118 max_coupling_range[i] = 3 * proxy->target_temperature() *
00119 proxy->boltzmann();
00120 } else {
00121 max_coupling_range[i] = 3 * proxy->boltzmann();
00122 }
00123 }
00124 }
00125 
00126 if (!get_keyval(conf, "rateMax", max_coupling_rate, max_coupling_rate)) {
00127 //set to default
00128 for (i = 0; i < num_variables(); i++) {
00129 max_coupling_rate[i] = max_coupling_range[i] / (10 * update_freq);
00130 }
00131 }
00132 
00133 
00134 if (cvm::debug())
00135 cvm::log(" bias.\n");
00136 
00137 return COLVARS_OK;
00138 }
00139 
00140 
00141 colvarbias_alb::~colvarbias_alb()
00142 {
00143 }
00144 
00145 
00146 int colvarbias_alb::update()
00147 {
00148 colvarproxy *proxy = cvm::main()->proxy;
00149 
00150 bias_energy = 0.0;
00151 update_calls++;
00152 
00153 if (cvm::debug())
00154 cvm::log("Updating the adaptive linear bias \""+this->name+"\".\n");
00155 
00156 //log the moments of the CVs
00157 // Force and energy calculation
00158 bool finished_equil_flag = 1;
00159 cvm::real delta;
00160 for (size_t i = 0; i < num_variables(); i++) {
00161 colvar_forces[i] = -1.0 * restraint_force(restraint_convert_k(current_coupling[i], colvars[i]->width),
00162 colvars[i],
00163 colvar_centers[i]);
00164 bias_energy += restraint_potential(restraint_convert_k(current_coupling[i], colvars[i]->width),
00165 colvars[i],
00166 colvar_centers[i]);
00167 
00168 if (!b_equilibration) {
00169 //Welford, West, and Hanso online variance method
00170 
00171 delta = static_cast<cvm::real>(colvars[i]->value()) - means[i];
00172 means[i] += delta / update_calls;
00173 ssd[i] += delta * (static_cast<cvm::real>(colvars[i]->value()) - means[i]);
00174 
00175 } else {
00176 //check if we've reached the setpoint
00177 cvm::real const coupling_diff = current_coupling[i] - set_coupling[i];
00178 if ((coupling_rate[i] == 0) ||
00179 ((coupling_diff*coupling_diff) < (coupling_rate[i]*coupling_rate[i]))) {
00180 finished_equil_flag &= 1; //we continue equilibrating as long as we haven't reached all the set points
00181 }
00182 else {
00183 current_coupling[i] += coupling_rate[i];
00184 finished_equil_flag = 0;
00185 }
00186 
00187 
00188 //update max_coupling_range
00189 if (!b_hard_coupling_range && fabs(current_coupling[i]) > max_coupling_range[i]) {
00190 std::ostringstream logStream;
00191 logStream << "Coupling constant for "
00192 << colvars[i]->name
00193 << " has exceeded coupling range of "
00194 << max_coupling_range[i]
00195 << ".\n";
00196 
00197 max_coupling_range[i] *= 1.25;
00198 logStream << "Expanding coupling range to " << max_coupling_range[i] << ".\n";
00199 cvm::log(logStream.str());
00200 }
00201 
00202 
00203 }
00204 }
00205 
00206 if (b_equilibration && finished_equil_flag) {
00207 b_equilibration = false;
00208 update_calls = 0;
00209 }
00210 
00211 
00212 //now we update coupling constant, if necessary
00213 if (!b_equilibration && update_calls == update_freq) {
00214 
00215 //use estimated variance to take a step
00216 cvm::real step_size = 0;
00217 cvm::real temp;
00218 
00219 //reset means and sum of squares of differences
00220 for (size_t i = 0; i < num_variables(); i++) {
00221 
00222 temp = 2. * (means[i] / (static_cast<cvm::real> (colvar_centers[i])) - 1) * ssd[i] / (update_calls - 1);
00223 
00224 if (proxy->target_temperature() > 0.0) {
00225 step_size = temp / (proxy->target_temperature() * proxy->boltzmann());
00226 } else {
00227 step_size = temp / proxy->boltzmann();
00228 }
00229 
00230 means[i] = 0;
00231 ssd[i] = 0;
00232 
00233 //stochastic if we do that update or not
00234 if (num_variables() == 1 || rand() < RAND_MAX / ((int) num_variables())) {
00235 coupling_accum[i] += step_size * step_size;
00236 current_coupling[i] = set_coupling[i];
00237 set_coupling[i] += max_coupling_range[i] / sqrt(coupling_accum[i]) * step_size;
00238 coupling_rate[i] = (set_coupling[i] - current_coupling[i]) / update_freq;
00239 //set to the minimum rate and then put the sign back on it
00240 coupling_rate[i] = copysign(fmin(fabs(coupling_rate[i]), max_coupling_rate[i]), coupling_rate[i]);
00241 } else {
00242 coupling_rate[i] = 0;
00243 }
00244 
00245 }
00246 
00247 update_calls = 0;
00248 b_equilibration = true;
00249 
00250 }
00251 
00252 return COLVARS_OK;
00253 }
00254 
00255 
00256 int colvarbias_alb::set_state_params(std::string const &conf)
00257 {
00258 int error_code = colvarbias::set_state_params(conf);
00259 
00260 if (error_code != COLVARS_OK) {
00261 return error_code;
00262 }
00263 
00264 if (!get_keyval(conf, "setCoupling", set_coupling))
00265 cvm::error("Error: current setCoupling is missing from the restart.\n");
00266 
00267 if (!get_keyval(conf, "currentCoupling", current_coupling))
00268 cvm::error("Error: current setCoupling is missing from the restart.\n");
00269 
00270 if (!get_keyval(conf, "maxCouplingRange", max_coupling_range))
00271 cvm::error("Error: maxCouplingRange is missing from the restart.\n");
00272 
00273 if (!get_keyval(conf, "couplingRate", coupling_rate))
00274 cvm::error("Error: current setCoupling is missing from the restart.\n");
00275 
00276 if (!get_keyval(conf, "couplingAccum", coupling_accum))
00277 cvm::error("Error: couplingAccum is missing from the restart.\n");
00278 
00279 if (!get_keyval(conf, "mean", means))
00280 cvm::error("Error: current mean is missing from the restart.\n");
00281 
00282 if (!get_keyval(conf, "ssd", ssd))
00283 cvm::error("Error: current ssd is missing from the restart.\n");
00284 
00285 if (!get_keyval(conf, "updateCalls", update_calls))
00286 cvm::error("Error: current updateCalls is missing from the restart.\n");
00287 
00288 if (!get_keyval(conf, "b_equilibration", b_equilibration))
00289 cvm::error("Error: current updateCalls is missing from the restart.\n");
00290 
00291 return COLVARS_OK;
00292 }
00293 
00294 
00295 std::string const colvarbias_alb::get_state_params() const
00296 {
00297 std::ostringstream os;
00298 os << " setCoupling ";
00299 size_t i;
00300 for (i = 0; i < num_variables(); i++) {
00301 os << std::setprecision(cvm::en_prec)
00302 << std::setw(cvm::en_width) << set_coupling[i] << "\n";
00303 }
00304 os << " currentCoupling ";
00305 for (i = 0; i < num_variables(); i++) {
00306 os << std::setprecision(cvm::en_prec)
00307 << std::setw(cvm::en_width) << current_coupling[i] << "\n";
00308 }
00309 os << " maxCouplingRange ";
00310 for (i = 0; i < num_variables(); i++) {
00311 os << std::setprecision(cvm::en_prec)
00312 << std::setw(cvm::en_width) << max_coupling_range[i] << "\n";
00313 }
00314 os << " couplingRate ";
00315 for (i = 0; i < num_variables(); i++) {
00316 os << std::setprecision(cvm::en_prec)
00317 << std::setw(cvm::en_width) << coupling_rate[i] << "\n";
00318 }
00319 os << " couplingAccum ";
00320 for (i = 0; i < num_variables(); i++) {
00321 os << std::setprecision(cvm::en_prec)
00322 << std::setw(cvm::en_width) << coupling_accum[i] << "\n";
00323 }
00324 os << " mean ";
00325 for (i = 0; i < num_variables(); i++) {
00326 os << std::setprecision(cvm::en_prec)
00327 << std::setw(cvm::en_width) << means[i] << "\n";
00328 }
00329 os << " ssd ";
00330 for (i = 0; i < num_variables(); i++) {
00331 os << std::setprecision(cvm::en_prec)
00332 << std::setw(cvm::en_width) << ssd[i] << "\n";
00333 }
00334 os << " updateCalls " << update_calls << "\n";
00335 if (b_equilibration)
00336 os << " b_equilibration yes\n";
00337 else
00338 os << " b_equilibration no\n";
00339 
00340 return os.str();
00341 }
00342 
00343 
00344 std::ostream & colvarbias_alb::write_traj_label(std::ostream &os)
00345 {
00346 os << " ";
00347 
00348 if (b_output_energy)
00349 os << " E_"
00350 << cvm::wrap_string(this->name, cvm::en_width-2);
00351 
00352 if (b_output_coupling)
00353 for (size_t i = 0; i < current_coupling.size(); i++) {
00354 os << " ForceConst_" << i
00355 <<std::setw(cvm::en_width - 6 - (i / 10 + 1))
00356 << "";
00357 }
00358 
00359 if (b_output_grad)
00360 for (size_t i = 0; i < means.size(); i++) {
00361 os << "Grad_"
00362 << cvm::wrap_string(colvars[i]->name, cvm::cv_width - 4);
00363 }
00364 
00365 if (b_output_centers)
00366 for (size_t i = 0; i < num_variables(); i++) {
00367 size_t const this_cv_width = (colvars[i]->value()).output_width(cvm::cv_width);
00368 os << " x0_"
00369 << cvm::wrap_string(colvars[i]->name, this_cv_width-3);
00370 }
00371 
00372 return os;
00373 }
00374 
00375 
00376 std::ostream & colvarbias_alb::write_traj(std::ostream &os)
00377 {
00378 os << " ";
00379 
00380 if (b_output_energy)
00381 os << " "
00382 << std::setprecision(cvm::en_prec) << std::setw(cvm::en_width)
00383 << bias_energy;
00384 
00385 if (b_output_coupling)
00386 for (size_t i = 0; i < current_coupling.size(); i++) {
00387 os << " "
00388 << std::setprecision(cvm::en_prec) << std::setw(cvm::en_width)
00389 << current_coupling[i];
00390 }
00391 
00392 
00393 if (b_output_centers)
00394 for (size_t i = 0; i < num_variables(); i++) {
00395 os << " "
00396 << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
00397 << colvar_centers[i];
00398 }
00399 
00400 if (b_output_grad)
00401 for (size_t i = 0; i < means.size(); i++) {
00402 os << " "
00403 << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
00404 << -2.0 * (means[i] / (static_cast<cvm::real>(colvar_centers[i])) - 1) * ssd[i] / (fmax(update_calls, 2.0) - 1);
00405 
00406 }
00407 
00408 return os;
00409 }
00410 
00411 
00412 cvm::real colvarbias_alb::restraint_potential(cvm::real k,
00413 colvar const *x,
00414 colvarvalue const &xcenter) const
00415 {
00416 return k * (x->value() - xcenter);
00417 }
00418 
00419 
00420 colvarvalue colvarbias_alb::restraint_force(cvm::real k,
00421 colvar const * /* x */,
00422 colvarvalue const & /* xcenter */) const
00423 {
00424 return k;
00425 }
00426 
00427 
00428 cvm::real colvarbias_alb::restraint_convert_k(cvm::real k,
00429 cvm::real dist_measure) const
00430 {
00431 return k / dist_measure;
00432 }
00433 

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

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