00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <fstream>
00011 #include <list>
00012 #include <utility>
00013
00014 #include "colvarmodule.h"
00015 #include "colvarproxy.h"
00016 #include "colvarscript.h"
00017 #include "colvaratoms.h"
00018 #include "colvarmodule_utils.h"
00019
00020
00021
00022 colvarproxy_atoms::colvarproxy_atoms()
00023 {
00024 atoms_rms_applied_force_ = atoms_max_applied_force_ = 0.0;
00025 atoms_max_applied_force_id_ = -1;
00026 updated_masses_ = updated_charges_ = false;
00027 }
00028
00029
00030 colvarproxy_atoms::~colvarproxy_atoms()
00031 {
00032 reset();
00033 }
00034
00035
00036 int colvarproxy_atoms::reset()
00037 {
00038 atoms_ids.clear();
00039 atoms_refcount.clear();
00040 atoms_masses.clear();
00041 atoms_charges.clear();
00042 atoms_positions.clear();
00043 atoms_total_forces.clear();
00044 atoms_new_colvar_forces.clear();
00045 return COLVARS_OK;
00046 }
00047
00048
00049 int colvarproxy_atoms::add_atom_slot(int atom_id)
00050 {
00051 atoms_ids.push_back(atom_id);
00052 atoms_refcount.push_back(1);
00053 atoms_masses.push_back(1.0);
00054 atoms_charges.push_back(0.0);
00055 atoms_positions.push_back(cvm::rvector(0.0, 0.0, 0.0));
00056 atoms_total_forces.push_back(cvm::rvector(0.0, 0.0, 0.0));
00057 atoms_new_colvar_forces.push_back(cvm::rvector(0.0, 0.0, 0.0));
00058 return (atoms_ids.size() - 1);
00059 }
00060
00061
00062 int colvarproxy_atoms::init_atom(int )
00063 {
00064 return COLVARS_NOT_IMPLEMENTED;
00065 }
00066
00067
00068 int colvarproxy_atoms::check_atom_id(int )
00069 {
00070 return COLVARS_NOT_IMPLEMENTED;
00071 }
00072
00073
00074 int colvarproxy_atoms::init_atom(cvm::residue_id const & ,
00075 std::string const & ,
00076 std::string const & )
00077 {
00078 cvm::error("Error: initializing an atom by name and residue number is currently not supported.\n",
00079 COLVARS_NOT_IMPLEMENTED);
00080 return COLVARS_NOT_IMPLEMENTED;
00081 }
00082
00083
00084 int colvarproxy_atoms::check_atom_id(cvm::residue_id const &residue,
00085 std::string const &atom_name,
00086 std::string const &segment_id)
00087 {
00088 colvarproxy_atoms::init_atom(residue, atom_name, segment_id);
00089 return COLVARS_NOT_IMPLEMENTED;
00090 }
00091
00092
00093 void colvarproxy_atoms::clear_atom(int index)
00094 {
00095 if (((size_t) index) >= atoms_ids.size()) {
00096 cvm::error("Error: trying to disable an atom that was not previously requested.\n",
00097 COLVARS_INPUT_ERROR);
00098 }
00099 if (atoms_refcount[index] > 0) {
00100 atoms_refcount[index] -= 1;
00101 }
00102 }
00103
00104
00105 size_t colvarproxy_atoms::get_num_active_atoms() const
00106 {
00107 size_t result = 0;
00108 for (size_t i = 0; i < atoms_refcount.size(); i++) {
00109 if (atoms_refcount[i] > 0) result++;
00110 }
00111 return result;
00112 }
00113
00114
00115 int colvarproxy_atoms::load_atoms(char const * ,
00116 cvm::atom_group & ,
00117 std::string const & ,
00118 double)
00119 {
00120 return cvm::error("Error: loading atom identifiers from a file "
00121 "is currently not implemented.\n",
00122 COLVARS_NOT_IMPLEMENTED);
00123 }
00124
00125
00126 int colvarproxy_atoms::load_coords(char const * ,
00127 std::vector<cvm::atom_pos> & ,
00128 std::vector<int> const & ,
00129 std::string const & ,
00130 double)
00131 {
00132 return cvm::error("Error: loading atomic coordinates from a file "
00133 "is currently not implemented.\n",
00134 COLVARS_NOT_IMPLEMENTED);
00135 }
00136
00137
00138 void colvarproxy_atoms::compute_rms_atoms_applied_force()
00139 {
00140 atoms_rms_applied_force_ =
00141 compute_norm2_stats<cvm::rvector, 0, false>(atoms_new_colvar_forces);
00142 }
00143
00144
00145 void colvarproxy_atoms::compute_max_atoms_applied_force()
00146 {
00147 int minmax_index = -1;
00148 size_t const n_atoms_ids = atoms_ids.size();
00149 if ((n_atoms_ids > 0) && (n_atoms_ids == atoms_new_colvar_forces.size())) {
00150 atoms_max_applied_force_ =
00151 compute_norm2_stats<cvm::rvector, 1, true>(atoms_new_colvar_forces,
00152 &minmax_index);
00153 if (minmax_index >= 0) {
00154 atoms_max_applied_force_id_ = atoms_ids[minmax_index];
00155 } else {
00156 atoms_max_applied_force_id_ = -1;
00157 }
00158 } else {
00159 atoms_max_applied_force_ =
00160 compute_norm2_stats<cvm::rvector, 1, false>(atoms_new_colvar_forces);
00161 atoms_max_applied_force_id_ = -1;
00162 }
00163 }
00164
00165
00166
00167 colvarproxy_atom_groups::colvarproxy_atom_groups()
00168 {
00169 atom_groups_rms_applied_force_ = atom_groups_max_applied_force_ = 0.0;
00170 }
00171
00172
00173 colvarproxy_atom_groups::~colvarproxy_atom_groups()
00174 {
00175 reset();
00176 }
00177
00178
00179 int colvarproxy_atom_groups::reset()
00180 {
00181 atom_groups_ids.clear();
00182 atom_groups_refcount.clear();
00183 atom_groups_masses.clear();
00184 atom_groups_charges.clear();
00185 atom_groups_coms.clear();
00186 atom_groups_total_forces.clear();
00187 atom_groups_new_colvar_forces.clear();
00188 return COLVARS_OK;
00189 }
00190
00191
00192 int colvarproxy_atom_groups::add_atom_group_slot(int atom_group_id)
00193 {
00194 atom_groups_ids.push_back(atom_group_id);
00195 atom_groups_refcount.push_back(1);
00196 atom_groups_masses.push_back(1.0);
00197 atom_groups_charges.push_back(0.0);
00198 atom_groups_coms.push_back(cvm::rvector(0.0, 0.0, 0.0));
00199 atom_groups_total_forces.push_back(cvm::rvector(0.0, 0.0, 0.0));
00200 atom_groups_new_colvar_forces.push_back(cvm::rvector(0.0, 0.0, 0.0));
00201 return (atom_groups_ids.size() - 1);
00202 }
00203
00204
00205 int colvarproxy_atom_groups::scalable_group_coms()
00206 {
00207 return COLVARS_NOT_IMPLEMENTED;
00208 }
00209
00210
00211 int colvarproxy_atom_groups::init_atom_group(std::vector<int> const & )
00212 {
00213 cvm::error("Error: initializing a group outside of the Colvars module "
00214 "is currently not supported.\n",
00215 COLVARS_NOT_IMPLEMENTED);
00216 return COLVARS_NOT_IMPLEMENTED;
00217 }
00218
00219
00220 void colvarproxy_atom_groups::clear_atom_group(int index)
00221 {
00222 if (((size_t) index) >= atom_groups_ids.size()) {
00223 cvm::error("Error: trying to disable an atom group "
00224 "that was not previously requested.\n",
00225 COLVARS_INPUT_ERROR);
00226 }
00227 if (atom_groups_refcount[index] > 0) {
00228 atom_groups_refcount[index] -= 1;
00229 }
00230 }
00231
00232
00233 size_t colvarproxy_atom_groups::get_num_active_atom_groups() const
00234 {
00235 size_t result = 0;
00236 for (size_t i = 0; i < atom_groups_refcount.size(); i++) {
00237 if (atom_groups_refcount[i] > 0) result++;
00238 }
00239 return result;
00240 }
00241
00242
00243 void colvarproxy_atom_groups::compute_rms_atom_groups_applied_force()
00244 {
00245 atom_groups_rms_applied_force_ =
00246 compute_norm2_stats<cvm::rvector, 0, false>(atom_groups_new_colvar_forces);
00247 }
00248
00249
00250 void colvarproxy_atom_groups::compute_max_atom_groups_applied_force()
00251 {
00252 atom_groups_max_applied_force_ =
00253 compute_norm2_stats<cvm::rvector, 1, false>(atom_groups_new_colvar_forces);
00254 }
00255
00256
00257
00258 colvarproxy_smp::colvarproxy_smp()
00259 {
00260 b_smp_active = true;
00261 omp_lock_state = NULL;
00262 #if defined(_OPENMP)
00263 if (omp_get_thread_num() == 0) {
00264 omp_lock_state = new omp_lock_t;
00265 omp_init_lock(omp_lock_state);
00266 }
00267 #endif
00268 }
00269
00270
00271 colvarproxy_smp::~colvarproxy_smp()
00272 {
00273 #if defined(_OPENMP)
00274 if (omp_get_thread_num() == 0) {
00275 if (omp_lock_state) {
00276 delete omp_lock_state;
00277 }
00278 }
00279 #endif
00280 }
00281
00282
00283 int colvarproxy_smp::smp_enabled()
00284 {
00285 #if defined(_OPENMP)
00286 if (b_smp_active) {
00287 return COLVARS_OK;
00288 }
00289 return COLVARS_ERROR;
00290 #else
00291 return COLVARS_NOT_IMPLEMENTED;
00292 #endif
00293 }
00294
00295
00296 int colvarproxy_smp::smp_colvars_loop()
00297 {
00298 #if defined(_OPENMP)
00299 colvarmodule *cv = cvm::main();
00300 colvarproxy *proxy = cv->proxy;
00301 #pragma omp parallel for
00302 for (size_t i = 0; i < cv->variables_active_smp()->size(); i++) {
00303 colvar *x = (*(cv->variables_active_smp()))[i];
00304 int x_item = (*(cv->variables_active_smp_items()))[i];
00305 if (cvm::debug()) {
00306 cvm::log("["+cvm::to_str(proxy->smp_thread_id())+"/"+
00307 cvm::to_str(proxy->smp_num_threads())+
00308 "]: calc_colvars_items_smp(), i = "+cvm::to_str(i)+", cv = "+
00309 x->name+", cvc = "+cvm::to_str(x_item)+"\n");
00310 }
00311 x->calc_cvcs(x_item, 1);
00312 }
00313 return cvm::get_error();
00314 #else
00315 return COLVARS_NOT_IMPLEMENTED;
00316 #endif
00317 }
00318
00319
00320 int colvarproxy_smp::smp_biases_loop()
00321 {
00322 #if defined(_OPENMP)
00323 colvarmodule *cv = cvm::main();
00324 #pragma omp parallel
00325 {
00326 #pragma omp for
00327 for (size_t i = 0; i < cv->biases_active()->size(); i++) {
00328 colvarbias *b = (*(cv->biases_active()))[i];
00329 if (cvm::debug()) {
00330 cvm::log("Calculating bias \""+b->name+"\" on thread "+
00331 cvm::to_str(smp_thread_id())+"\n");
00332 }
00333 b->update();
00334 }
00335 }
00336 return cvm::get_error();
00337 #else
00338 return COLVARS_NOT_IMPLEMENTED;
00339 #endif
00340 }
00341
00342
00343 int colvarproxy_smp::smp_biases_script_loop()
00344 {
00345 #if defined(_OPENMP)
00346 colvarmodule *cv = cvm::main();
00347 #pragma omp parallel
00348 {
00349 #pragma omp single nowait
00350 {
00351 cv->calc_scripted_forces();
00352 }
00353 #pragma omp for
00354 for (size_t i = 0; i < cv->biases_active()->size(); i++) {
00355 colvarbias *b = (*(cv->biases_active()))[i];
00356 if (cvm::debug()) {
00357 cvm::log("Calculating bias \""+b->name+"\" on thread "+
00358 cvm::to_str(smp_thread_id())+"\n");
00359 }
00360 b->update();
00361 }
00362 }
00363 return cvm::get_error();
00364 #else
00365 return COLVARS_NOT_IMPLEMENTED;
00366 #endif
00367 }
00368
00369
00370
00371
00372 int colvarproxy_smp::smp_thread_id()
00373 {
00374 #if defined(_OPENMP)
00375 return omp_get_thread_num();
00376 #else
00377 return -1;
00378 #endif
00379 }
00380
00381
00382 int colvarproxy_smp::smp_num_threads()
00383 {
00384 #if defined(_OPENMP)
00385 return omp_get_max_threads();
00386 #else
00387 return -1;
00388 #endif
00389 }
00390
00391
00392 int colvarproxy_smp::smp_lock()
00393 {
00394 #if defined(_OPENMP)
00395 omp_set_lock(omp_lock_state);
00396 #endif
00397 return COLVARS_OK;
00398 }
00399
00400
00401 int colvarproxy_smp::smp_trylock()
00402 {
00403 #if defined(_OPENMP)
00404 return omp_test_lock(omp_lock_state) ? COLVARS_OK : COLVARS_ERROR;
00405 #else
00406 return COLVARS_OK;
00407 #endif
00408 }
00409
00410
00411 int colvarproxy_smp::smp_unlock()
00412 {
00413 #if defined(_OPENMP)
00414 omp_unset_lock(omp_lock_state);
00415 #endif
00416 return COLVARS_OK;
00417 }
00418
00419
00420
00421 colvarproxy_script::colvarproxy_script()
00422 {
00423 script = NULL;
00424 have_scripts = false;
00425 }
00426
00427
00428 colvarproxy_script::~colvarproxy_script()
00429 {
00430 if (script != NULL) {
00431 delete script;
00432 script = NULL;
00433 }
00434 }
00435
00436
00437 int colvarproxy_script::run_force_callback()
00438 {
00439 return COLVARS_NOT_IMPLEMENTED;
00440 }
00441
00442
00443 int colvarproxy_script::run_colvar_callback(std::string const & ,
00444 std::vector<const colvarvalue *> const & ,
00445 colvarvalue & )
00446 {
00447 return COLVARS_NOT_IMPLEMENTED;
00448 }
00449
00450
00451 int colvarproxy_script::run_colvar_gradient_callback(std::string const & ,
00452 std::vector<const colvarvalue *> const & ,
00453 std::vector<cvm::matrix2d<cvm::real> > & )
00454 {
00455 return COLVARS_NOT_IMPLEMENTED;
00456 }
00457
00458
00459
00460 colvarproxy::colvarproxy()
00461 {
00462 colvars = NULL;
00463
00464 engine_ready_ = true;
00465 b_simulation_running = true;
00466 b_simulation_continuing = false;
00467 b_delete_requested = false;
00468 version_int = -1;
00469 features_hash = 0;
00470 config_queue_ = reinterpret_cast<void *>(new std::list<std::pair<std::string, std::string> >);
00471 }
00472
00473
00474 colvarproxy::~colvarproxy()
00475 {
00476 close_output_streams();
00477 if (colvars != NULL) {
00478 delete colvars;
00479 colvars = NULL;
00480 }
00481 delete reinterpret_cast<std::list<std::pair<std::string, std::string> > *>(config_queue_);
00482 }
00483
00484
00485 bool colvarproxy::io_available()
00486 {
00487 return (smp_enabled() == COLVARS_OK && smp_thread_id() == 0) ||
00488 (smp_enabled() != COLVARS_OK);
00489 }
00490
00491
00492 int colvarproxy::reset()
00493 {
00494 int error_code = COLVARS_OK;
00495 error_code |= colvarproxy_atoms::reset();
00496 error_code |= colvarproxy_atom_groups::reset();
00497 return error_code;
00498 }
00499
00500
00501 int colvarproxy::request_deletion()
00502 {
00503 return cvm::error("Error: \"delete\" command is only available in VMD; "
00504 "please use \"reset\" instead.\n",
00505 COLVARS_NOT_IMPLEMENTED);
00506 }
00507
00508
00509 void colvarproxy::add_config(std::string const &cmd, std::string const &conf)
00510 {
00511 reinterpret_cast<std::list<std::pair<std::string, std::string> > *>(config_queue_)->push_back(std::make_pair(cmd, conf));
00512 }
00513
00514
00515 int colvarproxy::setup()
00516 {
00517 return COLVARS_OK;
00518 }
00519
00520
00521 int colvarproxy::parse_module_config()
00522 {
00523 int error_code = COLVARS_OK;
00524
00525 std::list<std::pair<std::string, std::string> > *config_queue = reinterpret_cast<std::list<std::pair<std::string, std::string> > *>(config_queue_);
00526 while (config_queue->size() > 0) {
00527 std::pair<std::string, std::string> const &p = config_queue->front();
00528 if (p.first == "config") {
00529 error_code |= colvars->read_config_string(p.second);
00530 } else if (p.first == "configfile") {
00531 error_code |= colvars->read_config_file(p.second.c_str());
00532 } else {
00533 error_code |= cvm::error(std::string("Error: invalid keyword \"") +
00534 p.first +
00535 std::string("\" in colvarproxy::setup()\n"),
00536 COLVARS_BUG_ERROR);
00537 }
00538 config_queue->pop_front();
00539 }
00540 return error_code;
00541 }
00542
00543
00544 int colvarproxy::update_input()
00545 {
00546 return COLVARS_OK;
00547 }
00548
00549
00550 int colvarproxy::update_output()
00551 {
00552 return COLVARS_OK;
00553 }
00554
00555
00556 int colvarproxy::end_of_step()
00557 {
00558
00559 updated_masses_ = updated_charges_ = false;
00560
00561
00562 compute_rms_atoms_applied_force();
00563 compute_max_atoms_applied_force();
00564 compute_rms_atom_groups_applied_force();
00565 compute_max_atom_groups_applied_force();
00566 compute_rms_volmaps_applied_force();
00567 compute_max_volmaps_applied_force();
00568
00569 if (cached_alch_lambda_changed) {
00570 send_alch_lambda();
00571 cached_alch_lambda_changed = false;
00572 }
00573 return COLVARS_OK;
00574 }
00575
00576
00577 int colvarproxy::post_run()
00578 {
00579 int error_code = COLVARS_OK;
00580 if (colvars->output_prefix().size()) {
00581 error_code |= colvars->write_restart_file(cvm::output_prefix()+".colvars.state");
00582 error_code |= colvars->write_output_files();
00583 }
00584 error_code |= flush_output_streams();
00585 return error_code;
00586 }
00587
00588
00589 void colvarproxy::print_input_atomic_data()
00590 {
00591 cvm::log(cvm::line_marker);
00592
00593 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00594 "atoms_ids = "+cvm::to_str(atoms_ids)+"\n");
00595 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00596 "atoms_refcount = "+cvm::to_str(atoms_refcount)+"\n");
00597 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00598 "atoms_masses = "+cvm::to_str(atoms_masses)+"\n");
00599 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00600 "atoms_charges = "+cvm::to_str(atoms_charges)+"\n");
00601 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00602 "atoms_positions = "+cvm::to_str(atoms_positions,
00603 cvm::cv_width,
00604 cvm::cv_prec)+"\n");
00605 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00606 "atoms_total_forces = "+cvm::to_str(atoms_total_forces,
00607 cvm::cv_width,
00608 cvm::cv_prec)+"\n");
00609
00610 cvm::log(cvm::line_marker);
00611
00612 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00613 "atom_groups_ids = "+cvm::to_str(atom_groups_ids)+"\n");
00614 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00615 "atom_groups_refcount = "+cvm::to_str(atom_groups_refcount)+"\n");
00616 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00617 "atom_groups_masses = "+cvm::to_str(atom_groups_masses)+"\n");
00618 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00619 "atom_groups_charges = "+cvm::to_str(atom_groups_charges)+"\n");
00620 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00621 "atom_groups_coms = "+cvm::to_str(atom_groups_coms,
00622 cvm::cv_width,
00623 cvm::cv_prec)+"\n");
00624 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00625 "atom_groups_total_forces = "+cvm::to_str(atom_groups_total_forces,
00626 cvm::cv_width,
00627 cvm::cv_prec)+"\n");
00628
00629 cvm::log(cvm::line_marker);
00630
00631 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00632 "volmaps_ids = "+cvm::to_str(volmaps_ids)+"\n");
00633 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00634 "volmaps_values = "+cvm::to_str(volmaps_values)+"\n");
00635
00636 cvm::log(cvm::line_marker);
00637 }
00638
00639
00640 void colvarproxy::print_output_atomic_data()
00641 {
00642 cvm::log(cvm::line_marker);
00643 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00644 "atoms_new_colvar_forces = "+cvm::to_str(atoms_new_colvar_forces,
00645 colvarmodule::cv_width,
00646 colvarmodule::cv_prec)+"\n");
00647 cvm::log(cvm::line_marker);
00648
00649 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00650 "atom_groups_new_colvar_forces = "+
00651 cvm::to_str(atom_groups_new_colvar_forces,
00652 colvarmodule::cv_width,
00653 colvarmodule::cv_prec)+"\n");
00654
00655 cvm::log(cvm::line_marker);
00656
00657 cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
00658 "volmaps_new_colvar_forces = "+
00659 cvm::to_str(volmaps_new_colvar_forces)+"\n");
00660
00661 cvm::log(cvm::line_marker);
00662 }
00663
00664
00665 void colvarproxy::log(std::string const &message)
00666 {
00667 fprintf(stdout, "colvars: %s", message.c_str());
00668 }
00669
00670
00671 void colvarproxy::error(std::string const &message)
00672 {
00673
00674 colvarproxy::log(message);
00675 }
00676
00677
00678 void colvarproxy::add_error_msg(std::string const &message)
00679 {
00680 std::istringstream is(message);
00681 std::string line;
00682 while (std::getline(is, line)) {
00683 error_output += line+"\n";
00684 }
00685 }
00686
00687
00688 void colvarproxy::clear_error_msgs()
00689 {
00690 error_output.clear();
00691 }
00692
00693
00694 std::string const & colvarproxy::get_error_msgs()
00695 {
00696 return error_output;
00697 }
00698
00699
00700 int colvarproxy::get_version_from_string(char const *version_string)
00701 {
00702 std::string const v(version_string);
00703 std::istringstream is(v.substr(0, 4) + v.substr(5, 2) + v.substr(8, 2));
00704 int newint;
00705 is >> newint;
00706 return newint;
00707 }
00708
00709