00001
00002
00003
00004
00005 #include "colvarmodule.h"
00006 #include "colvar.h"
00007 #include "colvarbias_abf.h"
00008
00010
00011 colvarbias_abf::colvarbias_abf (std::string const &conf, char const *key)
00012 : colvarbias (conf, key),
00013 gradients (NULL),
00014 samples (NULL)
00015 {
00016 if (cvm::temperature() == 0.0)
00017 cvm::log ("WARNING: ABF should not be run without a thermostat or at 0 Kelvin!\n");
00018
00019
00020
00021 get_keyval (conf, "applyBias", apply_bias, true);
00022 if (!apply_bias) cvm::log ("WARNING: ABF biases will *not* be applied!\n");
00023
00024 get_keyval (conf, "updateBias", update_bias, true);
00025 if (!update_bias) cvm::log ("WARNING: ABF biases will *not* be updated!\n");
00026
00027 get_keyval (conf, "hideJacobian", hide_Jacobian, false);
00028 if (hide_Jacobian) {
00029 cvm::log ("Jacobian (geometric) forces will be handled internally.\n");
00030 } else {
00031 cvm::log ("Jacobian (geometric) forces will be included in reported free energy gradients.\n");
00032 }
00033
00034 get_keyval (conf, "fullSamples", full_samples, 200);
00035 if ( full_samples <= 1 ) full_samples = 1;
00036 min_samples = full_samples / 2;
00037
00038
00039 get_keyval (conf, "inputPrefix", input_prefix, std::vector<std::string> ());
00040 get_keyval (conf, "outputFreq", output_freq, cvm::restart_out_freq);
00041 get_keyval (conf, "historyFreq", history_freq, 0);
00042 b_history_files = (history_freq > 0);
00043
00044
00045
00046 if (colvars.size() == 0) {
00047 cvm::fatal_error ("Error: no collective variables specified for the ABF bias.\n");
00048 }
00049
00050 for (size_t i = 0; i < colvars.size(); i++) {
00051
00052 if (colvars[i]->type() != colvarvalue::type_scalar) {
00053 cvm::fatal_error ("Error: ABF bias can only use scalar-type variables.\n");
00054 }
00055
00056 colvars[i]->enable (colvar::task_gradients);
00057
00058 if (update_bias) {
00059
00060 colvars[i]->enable (colvar::task_system_force);
00061
00062 if (!colvars[i]->tasks[colvar::task_extended_lagrangian]) {
00063
00064 colvars[i]->enable (colvar::task_Jacobian_force);
00065
00066
00067
00068
00069 if (hide_Jacobian) {
00070 if (colvars[i]->n_components() > 1) {
00071 cvm::log ("WARNING: colvar \"" + colvars[i]->name
00072 + "\" has multiple components; reporting its Jacobian forces\n");
00073 colvars[i]->enable (colvar::task_report_Jacobian_force);
00074 }
00075 } else {
00076 colvars[i]->enable (colvar::task_report_Jacobian_force);
00077 }
00078 }
00079 }
00080
00081
00082
00083 }
00084
00085 bin.assign (colvars.size(), 0);
00086 force_bin.assign (colvars.size(), 0);
00087 force = new cvm::real [colvars.size()];
00088
00089
00090 samples = new colvar_grid_count (colvars);
00091 gradients = new colvar_grid_gradient (colvars);
00092 gradients->samples = samples;
00093 samples->has_parent_data = true;
00094
00095
00096 if ( input_prefix.size() > 0 ) {
00097 read_gradients_samples ();
00098 }
00099
00100 cvm::log ("Finished ABF setup.\n");
00101 }
00102
00104 colvarbias_abf::~colvarbias_abf()
00105 {
00106 if (samples) {
00107 delete samples;
00108 samples = NULL;
00109 }
00110
00111 if (gradients) {
00112 delete gradients;
00113 gradients = NULL;
00114 }
00115
00116 delete [] force;
00117 }
00118
00119
00122
00123 cvm::real colvarbias_abf::update()
00124 {
00125 if (cvm::debug()) cvm::log ("Updating ABF bias " + this->name);
00126
00127 if (cvm::step_relative() == 0) {
00128
00129
00130
00131
00132
00133 if ( cvm::n_abf_biases == 1 && cvm::n_meta_biases == 0 ) {
00134
00135 output_prefix = cvm::output_prefix;
00136 } else {
00137 output_prefix = cvm::output_prefix + "." + this->name;
00138 }
00139
00140 for (size_t i=0; i<colvars.size(); i++) {
00141 bin[i] = samples->current_bin_scalar(i);
00142 }
00143
00144 } else {
00145
00146 for (size_t i=0; i<colvars.size(); i++) {
00147 bin[i] = samples->current_bin_scalar(i);
00148 }
00149
00150 if ( update_bias && samples->index_ok (force_bin) ) {
00151
00152
00153 for (size_t i=0; i<colvars.size(); i++) {
00154 force[i] = colvars[i]->system_force();
00155 }
00156 gradients->acc_force (force_bin, force);
00157 }
00158 }
00159
00160
00161 force_bin = bin;
00162
00163
00164 for (size_t i=0; i<colvars.size(); i++) {
00165 colvar_forces[i].reset();
00166 }
00167
00168
00169 if ( apply_bias && samples->index_ok (bin) ) {
00170
00171 size_t count = samples->value (bin);
00172 cvm::real fact = 1.0;
00173
00174
00175 if ( count < full_samples ) {
00176 fact = ( count < min_samples) ? 0.0 :
00177 (cvm::real (count - min_samples)) / (cvm::real (full_samples - min_samples));
00178 }
00179
00180 const cvm::real * grad = &(gradients->value (bin));
00181
00182 if ( fact != 0.0 ) {
00183
00184 if ( (colvars.size() == 1) && colvars[0]->periodic_boundaries() ) {
00185
00186 colvar_forces[0].real_value += fact * (grad[0] / cvm::real (count) - gradients->average ());
00187 } else {
00188 for (size_t i=0; i<colvars.size(); i++) {
00189
00190 colvar_forces[i].real_value += fact * grad[i] / cvm::real (count);
00191
00192 }
00193 }
00194 }
00195 }
00196
00197 if (output_freq && (cvm::step_absolute() % output_freq) == 0) {
00198 if (cvm::debug()) cvm::log ("ABF bias trying to write gradients and samples to disk");
00199 write_gradients_samples (output_prefix);
00200 }
00201 if (b_history_files && (cvm::step_absolute() % history_freq) == 0) {
00202
00203
00204 write_gradients_samples (output_prefix + ".hist", (cvm::step_absolute() > 0));
00205 }
00206 return 0.0;
00207 }
00208
00209
00210 void colvarbias_abf::write_gradients_samples (const std::string &prefix, bool append)
00211 {
00212 std::string samples_out_name = prefix + ".count";
00213 std::string gradients_out_name = prefix + ".grad";
00214 std::ios::openmode mode = (append ? std::ios::app : std::ios::out);
00215
00216 std::ofstream samples_os;
00217 std::ofstream gradients_os;
00218
00219 if (!append) cvm::backup_file (samples_out_name.c_str());
00220 samples_os.open (samples_out_name.c_str(), mode);
00221 if (!samples_os.good()) cvm::fatal_error ("Error opening ABF samples file " + samples_out_name + " for writing");
00222 samples->write_multicol (samples_os);
00223 samples_os.close ();
00224
00225 if (!append) cvm::backup_file (gradients_out_name.c_str());
00226 gradients_os.open (gradients_out_name.c_str(), mode);
00227 if (!gradients_os.good()) cvm::fatal_error ("Error opening ABF gradient file " + gradients_out_name + " for writing");
00228 gradients->write_multicol (gradients_os);
00229 gradients_os.close ();
00230
00231 if (colvars.size () == 1) {
00232 std::string pmf_out_name = prefix + ".pmf";
00233 if (!append) cvm::backup_file (pmf_out_name.c_str());
00234 std::ofstream pmf_os;
00235
00236 pmf_os.open (pmf_out_name.c_str(), mode);
00237 if (!pmf_os.good()) cvm::fatal_error ("Error opening pmf file " + pmf_out_name + " for writing");
00238 gradients->write_1D_integral (pmf_os);
00239 pmf_os << std::endl;
00240 pmf_os.close ();
00241 }
00242 return;
00243 }
00244
00245 void colvarbias_abf::read_gradients_samples ()
00246 {
00247 std::string samples_in_name, gradients_in_name;
00248
00249 for ( size_t i = 0; i < input_prefix.size(); i++ ) {
00250 samples_in_name = input_prefix[i] + ".count";
00251 gradients_in_name = input_prefix[i] + ".grad";
00252
00253
00254 std::ifstream is;
00255
00256 cvm::log ("Reading sample count from " + samples_in_name + " and gradients from " + gradients_in_name);
00257 is.open (samples_in_name.c_str());
00258 if (!is.good()) cvm::fatal_error ("Error opening ABF samples file " + samples_in_name + " for reading");
00259 samples->read_multicol (is, true);
00260 is.close ();
00261 is.clear();
00262
00263 is.open (gradients_in_name.c_str());
00264 if (!is.good()) cvm::fatal_error ("Error opening ABF gradient file " + gradients_in_name + " for reading");
00265 gradients->read_multicol (is, true);
00266 is.close ();
00267 }
00268 return;
00269 }
00270
00271
00272 std::ostream & colvarbias_abf::write_restart (std::ostream& os)
00273 {
00274
00275 std::ios::fmtflags flags (os.flags ());
00276 os.setf(std::ios::fmtflags (0), std::ios::floatfield);
00277
00278 os << "abf {\n"
00279 << " configuration {\n"
00280 << " name " << this->name << "\n";
00281 os << " }\n";
00282
00283 os << "samples\n";
00284 samples->write_raw (os, 8);
00285
00286 os << "\ngradient\n";
00287 gradients->write_raw (os);
00288
00289 os << "}\n\n";
00290
00291 os.flags (flags);
00292 return os;
00293 }
00294
00295
00296 std::istream & colvarbias_abf::read_restart (std::istream& is)
00297 {
00298 if ( input_prefix.size() > 0 ) {
00299 cvm::fatal_error ("ERROR: cannot provide both inputPrefix and restart information (colvarsInput)");
00300 }
00301
00302 size_t const start_pos = is.tellg();
00303
00304 cvm::log ("Restarting ABF bias \""+
00305 this->name+"\".\n");
00306 std::string key, brace, conf;
00307
00308 if ( !(is >> key) || !(key == "abf") ||
00309 !(is >> brace) || !(brace == "{") ||
00310 !(is >> colvarparse::read_block ("configuration", conf)) ) {
00311 cvm::log ("Error: in reading restart configuration for ABF bias \""+
00312 this->name+"\" at position "+
00313 cvm::to_str (is.tellg())+" in stream.\n");
00314 is.clear();
00315 is.seekg (start_pos, std::ios::beg);
00316 is.setstate (std::ios::failbit);
00317 return is;
00318 }
00319
00320 std::string name = "";
00321 if ( (colvarparse::get_keyval (conf, "name", name, std::string (""), colvarparse::parse_silent)) &&
00322 (name != this->name) )
00323 cvm::fatal_error ("Error: in the restart file, the "
00324 "\"abf\" block has wrong name (" + name + ")\n");
00325 if ( name == "" ) {
00326 cvm::fatal_error ("Error: \"abf\" block in the restart file has no name.\n");
00327 }
00328
00329 if ( !(is >> key) || !(key == "samples")) {
00330 cvm::log ("Error: in reading restart configuration for ABF bias \""+
00331 this->name+"\" at position "+
00332 cvm::to_str (is.tellg())+" in stream.\n");
00333 is.clear();
00334 is.seekg (start_pos, std::ios::beg);
00335 is.setstate (std::ios::failbit);
00336 return is;
00337 }
00338 if (! samples->read_raw (is)) {
00339 samples->read_raw_error();
00340 }
00341
00342 if ( !(is >> key) || !(key == "gradient")) {
00343 cvm::log ("Error: in reading restart configuration for ABF bias \""+
00344 this->name+"\" at position "+
00345 cvm::to_str (is.tellg())+" in stream.\n");
00346 is.clear();
00347 is.seekg (start_pos, std::ios::beg);
00348 is.setstate (std::ios::failbit);
00349 return is;
00350 }
00351 if (! gradients->read_raw (is)) {
00352 gradients->read_raw_error();
00353 }
00354
00355 is >> brace;
00356 if (brace != "}") {
00357 cvm::fatal_error ("Error: corrupt restart information for ABF bias \""+
00358 this->name+"\": no matching brace at position "+
00359 cvm::to_str (is.tellg())+" in the restart file.\n");
00360 is.setstate (std::ios::failbit);
00361 }
00362 return is;
00363 }
00364
00365
00366
00367
00369
00370 colvarbias_histogram::colvarbias_histogram (std::string const &conf, char const *key)
00371 : colvarbias (conf, key),
00372 grid (NULL)
00373 {
00374 get_keyval (conf, "outputfreq", output_freq, cvm::restart_out_freq);
00375
00376 if ( output_freq == 0 ) {
00377 cvm::fatal_error ("User required histogram with zero output frequency");
00378 }
00379
00380 grid = new colvar_grid_count (colvars);
00381 bin.assign (colvars.size(), 0);
00382
00383 out_name = cvm::output_prefix + "." + this->name + ".dat";
00384 cvm::log ("Histogram will be written to file " + out_name);
00385
00386 cvm::log ("Finished histogram setup.\n");
00387 }
00388
00390 colvarbias_histogram::~colvarbias_histogram()
00391 {
00392 if (grid_os.good()) grid_os.close();
00393
00394 if (grid) {
00395 delete grid;
00396 grid = NULL;
00397 }
00398 }
00399
00401 cvm::real colvarbias_histogram::update()
00402 {
00403 if (cvm::debug()) cvm::log ("Updating Grid bias " + this->name);
00404
00405 for (size_t i=0; i<colvars.size(); i++) {
00406 bin[i] = grid->current_bin_scalar(i);
00407 }
00408
00409 if ( grid->index_ok (bin) ) {
00410 grid->incr_count (bin);
00411 }
00412
00413 if (output_freq && (cvm::step_absolute() % output_freq) == 0) {
00414 if (cvm::debug()) cvm::log ("Histogram bias trying to write grid to disk");
00415
00416 grid_os.open (out_name.c_str());
00417 if (!grid_os.good()) cvm::fatal_error ("Error opening histogram file " + out_name + " for writing");
00418 grid->write_multicol (grid_os);
00419 grid_os.close ();
00420 }
00421 return 0.0;
00422 }
00423
00424
00425 std::istream & colvarbias_histogram::read_restart (std::istream& is)
00426 {
00427 size_t const start_pos = is.tellg();
00428
00429 cvm::log ("Restarting collective variable histogram \""+
00430 this->name+"\".\n");
00431 std::string key, brace, conf;
00432
00433 if ( !(is >> key) || !(key == "histogram") ||
00434 !(is >> brace) || !(brace == "{") ||
00435 !(is >> colvarparse::read_block ("configuration", conf)) ) {
00436 cvm::log ("Error: in reading restart configuration for histogram \""+
00437 this->name+"\" at position "+
00438 cvm::to_str (is.tellg())+" in stream.\n");
00439 is.clear();
00440 is.seekg (start_pos, std::ios::beg);
00441 is.setstate (std::ios::failbit);
00442 return is;
00443 }
00444
00445 int id = -1;
00446 std::string name = "";
00447 if ( (colvarparse::get_keyval (conf, "name", name, std::string (""), colvarparse::parse_silent)) &&
00448 (name != this->name) )
00449 cvm::fatal_error ("Error: in the restart file, the "
00450 "\"histogram\" block has a wrong name: different system?\n");
00451 if ( (id == -1) && (name == "") ) {
00452 cvm::fatal_error ("Error: \"histogram\" block in the restart file "
00453 "has no name.\n");
00454 }
00455
00456 if ( !(is >> key) || !(key == "grid")) {
00457 cvm::log ("Error: in reading restart configuration for histogram \""+
00458 this->name+"\" at position "+
00459 cvm::to_str (is.tellg())+" in stream.\n");
00460 is.clear();
00461 is.seekg (start_pos, std::ios::beg);
00462 is.setstate (std::ios::failbit);
00463 return is;
00464 }
00465 if (! grid->read_raw (is)) {
00466 grid->read_raw_error();
00467 }
00468
00469 is >> brace;
00470 if (brace != "}") {
00471 cvm::fatal_error ("Error: corrupt restart information for ABF bias \""+
00472 this->name+"\": no matching brace at position "+
00473 cvm::to_str (is.tellg())+" in the restart file.\n");
00474 is.setstate (std::ios::failbit);
00475 }
00476 return is;
00477 }
00478
00479 std::ostream & colvarbias_histogram::write_restart (std::ostream& os)
00480 {
00481 os << "histogram {\n"
00482 << " configuration {\n"
00483 << " name " << this->name << "\n";
00484 os << " }\n";
00485
00486 os << "grid\n";
00487 grid->write_raw (os, 8);
00488
00489 os << "}\n\n";
00490
00491 return os;
00492 }