diff --git a/doc/src/PDF/colvars-refman-lammps.pdf b/doc/src/PDF/colvars-refman-lammps.pdf index f1b4cae8bbd3dfc7fe49bbc6c62d13c44dda0de2..5acaf8260c66e8d3269b6742fac7760b563eec63 100644 Binary files a/doc/src/PDF/colvars-refman-lammps.pdf and b/doc/src/PDF/colvars-refman-lammps.pdf differ diff --git a/lib/colvars/colvar.cpp b/lib/colvars/colvar.cpp index dbf5fa5219ac04b1469425070e251ee545832f06..78aa2608cfd170cae7c1b159e7a617d9b34d771f 100644 --- a/lib/colvars/colvar.cpp +++ b/lib/colvars/colvar.cpp @@ -1144,9 +1144,9 @@ cvm::real colvar::update_forces_energy() // For a periodic colvar, both walls may be applicable at the same time // in which case we pick the closer one if ( (!is_enabled(f_cv_upper_wall)) || - (this->dist2(x, lower_wall) < this->dist2(x, upper_wall)) ) { + (this->dist2(x_reported, lower_wall) < this->dist2(x_reported, upper_wall)) ) { - cvm::real const grad = this->dist2_lgrad(x, lower_wall); + cvm::real const grad = this->dist2_lgrad(x_reported, lower_wall); if (grad < 0.0) { fw = -0.5 * lower_wall_k * grad; f += fw; @@ -1157,7 +1157,7 @@ cvm::real colvar::update_forces_energy() } else { - cvm::real const grad = this->dist2_lgrad(x, upper_wall); + cvm::real const grad = this->dist2_lgrad(x_reported, upper_wall); if (grad > 0.0) { fw = -0.5 * upper_wall_k * grad; f += fw; @@ -1177,15 +1177,21 @@ cvm::real colvar::update_forces_energy() // atoms only feel the harmonic force // fr: bias force on extended variable (without harmonic spring), for output in trajectory // f_ext: total force on extended variable (including harmonic spring) - // f: - initially, external biasing force + // f: - initially, external biasing force (including wall forces) // - after this code block, colvar force to be applied to atomic coordinates, ie. spring force fr = f; f_ext = f + (-0.5 * ext_force_k) * this->dist2_lgrad(xr, x); f = (-0.5 * ext_force_k) * this->dist2_rgrad(xr, x); - // The total force acting on the extended variable is f_ext - // This will be used in the next timestep - ft_reported = f_ext; + if (is_enabled(f_cv_subtract_applied_force)) { + // Report a "system" force without the biases on this colvar + // that is, just the spring force + ft_reported = (-0.5 * ext_force_k) * this->dist2_lgrad(xr, x); + } else { + // The total force acting on the extended variable is f_ext + // This will be used in the next timestep + ft_reported = f_ext; + } // leapfrog: starting from x_i, f_i, v_(i-1/2) vr += (0.5 * dt) * f_ext / ext_mass; diff --git a/lib/colvars/colvaratoms.cpp b/lib/colvars/colvaratoms.cpp index 0d0a339a69382cdae29ceb4a839201a58dc2869a..e8046a97d5d2db92b3048d6106b01da8d2ff0452 100644 --- a/lib/colvars/colvaratoms.cpp +++ b/lib/colvars/colvaratoms.cpp @@ -367,6 +367,7 @@ int cvm::atom_group::parse(std::string const &conf) cvm::error("Error: atomsColValue, if provided, must be non-zero.\n", INPUT_ERROR); } + // NOTE: calls to add_atom() and/or add_atom_id() are in the proxy-implemented function cvm::load_atoms(atoms_file_name.c_str(), *this, atoms_col, atoms_col_value); } } @@ -403,11 +404,21 @@ int cvm::atom_group::parse(std::string const &conf) } } + // We need to know the fitting options to decide whether the group is scalable + parse_error |= parse_fitting_options(group_conf); + + if (is_available(f_ag_scalable_com) && !b_rotate) { + enable(f_ag_scalable_com); + enable(f_ag_scalable); + } + if (is_enabled(f_ag_scalable) && !b_dummy) { + cvm::log("Enabling scalable calculation for group \""+this->key+"\".\n"); index = (cvm::proxy)->init_atom_group(atoms_ids); } - parse_error |= parse_fitting_options(group_conf); + bool b_print_atom_ids = false; + get_keyval(group_conf, "printAtomIDs", b_print_atom_ids, false, colvarparse::parse_silent); // TODO move this to colvarparse object check_keywords(group_conf, key.c_str()); @@ -427,6 +438,10 @@ int cvm::atom_group::parse(std::string const &conf) cvm::to_str(total_mass)+", total charge = "+ cvm::to_str(total_charge)+".\n"); + if (b_print_atom_ids) { + cvm::log("Internal definition of the atom group:\n"); + } + cvm::decrease_depth(); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); @@ -583,6 +598,21 @@ int cvm::atom_group::add_atom_name_residue_range(std::string const &psf_segid, } +std::string const cvm::atom_group::print_atom_ids() const +{ + size_t line_count = 0; + std::ostringstream os(""); + for (size_t i = 0; i < atoms_ids.size(); i++) { + os << " " << std::setw(9) << atoms_ids[i]; + if (++line_count == 7) { + os << "\n"; + line_count = 0; + } + } + return os.str(); +} + + int cvm::atom_group::parse_fitting_options(std::string const &group_conf) { bool b_defined_center = get_keyval(group_conf, "centerReference", b_center, false); @@ -1118,8 +1148,7 @@ void cvm::atom_group::apply_colvar_force(cvm::real const &force) log("Communicating a colvar force from atom group to the MD engine.\n"); } - if (b_dummy) - return; + if (b_dummy) return; if (noforce) { cvm::error("Error: sending a force to a group that has " @@ -1161,17 +1190,21 @@ void cvm::atom_group::apply_colvar_force(cvm::real const &force) void cvm::atom_group::apply_force(cvm::rvector const &force) { - if (b_dummy) - return; + if (cvm::debug()) { + log("Communicating a colvar force from atom group to the MD engine.\n"); + } + + if (b_dummy) return; if (noforce) { cvm::error("Error: sending a force to a group that has " - "\"disableForces\" defined.\n"); + "\"enableForces\" set to off.\n"); return; } if (is_enabled(f_ag_scalable)) { (cvm::proxy)->apply_atom_group_force(index, force); + return; } if (b_rotate) { diff --git a/lib/colvars/colvaratoms.h b/lib/colvars/colvaratoms.h index 7a4d031daa0c5136fa70f1d36bc85de328bc391b..a2a771a8a3f3f8a181c2f05035a826cc68b6a2a9 100644 --- a/lib/colvars/colvaratoms.h +++ b/lib/colvars/colvaratoms.h @@ -253,6 +253,8 @@ public: return atoms.size(); } + std::string const print_atom_ids() const; + /// \brief If this option is on, this group merely acts as a wrapper /// for a fixed position; any calls to atoms within or to /// functions that return disaggregated data will fail diff --git a/lib/colvars/colvarbias_abf.cpp b/lib/colvars/colvarbias_abf.cpp index e3690a4eadfbbc02c37af8ef526864d46df9bcba..1665ea61a9c577afea8cbe3a3d8c680729581aa2 100644 --- a/lib/colvars/colvarbias_abf.cpp +++ b/lib/colvars/colvarbias_abf.cpp @@ -80,6 +80,7 @@ int colvarbias_abf::init(std::string const &conf) if (update_bias) { // Request calculation of total force (which also checks for availability) + // TODO - change this to a dependency - needs ABF-specific features if(enable(f_cvb_get_total_force)) return cvm::get_error(); } @@ -133,6 +134,10 @@ int colvarbias_abf::init(std::string const &conf) // Data for eABF z-based estimator if (b_extended) { + // CZAR output files for stratified eABF + get_keyval(conf, "writeCZARwindowFile", b_czar_window_file, false, + colvarparse::parse_silent); + z_bin.assign(colvars.size(), 0); z_samples = new colvar_grid_count(colvars); z_samples->request_actual_value(); @@ -241,7 +246,7 @@ int colvarbias_abf::update() for (size_t i = 0; i < colvars.size(); i++) { // get total forces (lagging by 1 timestep) from colvars - // and subtract previous ABF force + // and subtract previous ABF force if necessary update_system_force(i); } gradients->acc_force(force_bin, system_force); @@ -457,28 +462,30 @@ void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool app if (z_gradients) { // Write eABF-related quantities + std::string z_samples_out_name = prefix + ".zcount"; - std::string z_gradients_out_name = prefix + ".zgrad"; - std::string czar_gradients_out_name = prefix + ".czar"; cvm::ofstream z_samples_os; - cvm::ofstream z_gradients_os; - cvm::ofstream czar_gradients_os; if (!append) cvm::backup_file(z_samples_out_name.c_str()); z_samples_os.open(z_samples_out_name.c_str(), mode); if (!z_samples_os.is_open()) { - cvm::error("Error opening ABF z sample file " + z_samples_out_name + " for writing"); + cvm::error("Error opening eABF z-histogram file " + z_samples_out_name + " for writing"); } z_samples->write_multicol(z_samples_os); z_samples_os.close(); - if (!append) cvm::backup_file(z_gradients_out_name.c_str()); - z_gradients_os.open(z_gradients_out_name.c_str(), mode); - if (!z_gradients_os.is_open()) { - cvm::error("Error opening ABF z gradient file " + z_gradients_out_name + " for writing"); + if (b_czar_window_file) { + std::string z_gradients_out_name = prefix + ".zgrad"; + cvm::ofstream z_gradients_os; + + if (!append) cvm::backup_file(z_gradients_out_name.c_str()); + z_gradients_os.open(z_gradients_out_name.c_str(), mode); + if (!z_gradients_os.is_open()) { + cvm::error("Error opening eABF z-gradient file " + z_gradients_out_name + " for writing"); + } + z_gradients->write_multicol(z_gradients_os); + z_gradients_os.close(); } - z_gradients->write_multicol(z_gradients_os); - z_gradients_os.close(); // Calculate CZAR estimator of gradients for (std::vector<int> ix = czar_gradients->new_index(); @@ -490,6 +497,9 @@ void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool app } } + std::string czar_gradients_out_name = prefix + ".czar.grad"; + cvm::ofstream czar_gradients_os; + if (!append) cvm::backup_file(czar_gradients_out_name.c_str()); czar_gradients_os.open(czar_gradients_out_name.c_str(), mode); if (!czar_gradients_os.is_open()) { @@ -499,17 +509,7 @@ void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool app czar_gradients_os.close(); if (colvars.size() == 1) { - std::string z_pmf_out_name = prefix + ".zpmf"; - if (!append) cvm::backup_file(z_pmf_out_name.c_str()); - cvm::ofstream z_pmf_os; - // Do numerical integration and output a PMF - z_pmf_os.open(z_pmf_out_name.c_str(), mode); - if (!z_pmf_os.is_open()) cvm::error("Error opening z pmf file " + z_pmf_out_name + " for writing"); - z_gradients->write_1D_integral(z_pmf_os); - z_pmf_os << std::endl; - z_pmf_os.close(); - - std::string czar_pmf_out_name = prefix + ".czarpmf"; + std::string czar_pmf_out_name = prefix + ".czar.pmf"; if (!append) cvm::backup_file(czar_pmf_out_name.c_str()); cvm::ofstream czar_pmf_os; // Do numerical integration and output a PMF @@ -520,8 +520,6 @@ void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool app czar_pmf_os.close(); } } - - return; } @@ -559,7 +557,7 @@ void colvarbias_abf::read_gradients_samples() std::ifstream is; - cvm::log("Reading sample count from " + samples_in_name + " and gradients from " + gradients_in_name); + cvm::log("Reading sample count from " + samples_in_name + " and gradient from " + gradients_in_name); is.open(samples_in_name.c_str()); if (!is.is_open()) cvm::error("Error opening ABF samples file " + samples_in_name + " for reading"); samples->read_multicol(is, true); @@ -572,17 +570,18 @@ void colvarbias_abf::read_gradients_samples() is.close(); if (z_gradients) { - cvm::log("Reading z sample count from " + z_samples_in_name + " and z gradients from " + z_gradients_in_name); + // Read eABF z-averaged data for CZAR + cvm::log("Reading z-histogram from " + z_samples_in_name + " and z-gradient from " + z_gradients_in_name); is.clear(); is.open(z_samples_in_name.c_str()); - if (!is.is_open()) cvm::error("Error opening ABF z samples file " + z_samples_in_name + " for reading"); + if (!is.is_open()) cvm::error("Error opening eABF z-histogram file " + z_samples_in_name + " for reading"); z_samples->read_multicol(is, true); is.close(); is.clear(); is.open(z_gradients_in_name.c_str()); - if (!is.is_open()) cvm::error("Error opening ABF z gradient file " + z_gradients_in_name + " for reading"); + if (!is.is_open()) cvm::error("Error opening eABF z-gradient file " + z_gradients_in_name + " for reading"); z_gradients->read_multicol(is, true); is.close(); } diff --git a/lib/colvars/colvarbias_abf.h b/lib/colvars/colvarbias_abf.h index a706bbb5ceb0dd5cc9ad504c2f55de32411b10ec..ee7624096835e52bf27dc02cbb1b96d10c6e9c81 100644 --- a/lib/colvars/colvarbias_abf.h +++ b/lib/colvars/colvarbias_abf.h @@ -40,6 +40,8 @@ private: int output_freq; /// Write combined files with a history of all output data? bool b_history_files; + /// Write CZAR output file for stratified eABF (.zgrad) + bool b_czar_window_file; size_t history_freq; /// Cap applied biasing force? diff --git a/lib/colvars/colvarbias_meta.cpp b/lib/colvars/colvarbias_meta.cpp index 596972253b6dd1cc4eab86d3ee3b5ed534b2b0a2..2aa88bd12a7f408804f23416dc2ba4828dcb13a6 100644 --- a/lib/colvars/colvarbias_meta.cpp +++ b/lib/colvars/colvarbias_meta.cpp @@ -159,6 +159,23 @@ int colvarbias_meta::init(std::string const &conf) cvm::log("The bias temperature is "+cvm::to_str(bias_temperature)+".\n"); } + + // for ebmeta + target_dist = NULL; + get_keyval(conf, "ebMeta", ebmeta, false); + if(ebmeta){ + target_dist = new colvar_grid_scalar(); + target_dist->init_from_colvars(colvars); + get_keyval(conf, "targetdistfile", target_dist_file); + std::ifstream targetdiststream(target_dist_file.c_str()); + target_dist->read_multicol(targetdiststream); + // normalize target distribution and multiply by effective volume = exp(differential entropy) + target_dist->multiply_constant(1.0/target_dist->integral()); + cvm::real volume = std::exp(target_dist->entropy()); + target_dist->multiply_constant(volume); + get_keyval(conf, "ebMetaEquilSteps", ebmeta_equil_steps, 0); + } + if (cvm::debug()) cvm::log("Done initializing the metadynamics bias \""+this->name+"\""+ ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+".\n"); @@ -186,6 +203,11 @@ colvarbias_meta::~colvarbias_meta() if (hills_traj_os.is_open()) hills_traj_os.close(); + if(target_dist) { + delete target_dist; + target_dist = NULL; + } + if (cvm::n_meta_biases > 0) cvm::n_meta_biases -= 1; } @@ -221,9 +243,7 @@ colvarbias_meta::create_hill(colvarbias_meta::hill const &h) // output to trajectory (if specified) if (hills_traj_os.is_open()) { hills_traj_os << (hills.back()).output_traj(); - if (cvm::debug()) { - hills_traj_os.flush(); - } + hills_traj_os.flush(); } has_data = true; @@ -258,8 +278,7 @@ colvarbias_meta::delete_hill(hill_iter &h) hills_traj_os << "# DELETED this hill: " << (hills.back()).output_traj() << "\n"; - if (cvm::debug()) - hills_traj_os.flush(); + hills_traj_os.flush(); } return hills.erase(h); @@ -381,38 +400,37 @@ int colvarbias_meta::update() ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ ": adding a new hill at step "+cvm::to_str(cvm::step_absolute())+".\n"); - switch (comm) { + cvm::real hills_scale=1.0; - case single_replica: - if (well_tempered) { - cvm::real hills_energy_sum_here = 0.0; - if (use_grids) { - std::vector<int> curr_bin = hills_energy->get_colvars_index(); - hills_energy_sum_here = hills_energy->value(curr_bin); - } else { - calc_hills(new_hills_begin, hills.end(), hills_energy_sum_here); - } - cvm::real const exp_weight = std::exp(-1.0*hills_energy_sum_here/(bias_temperature*cvm::boltzmann())); - create_hill(hill((hill_weight*exp_weight), colvars, hill_width)); + if (ebmeta) { + hills_scale *= 1.0/target_dist->value(target_dist->get_colvars_index()); + if(cvm::step_absolute() <= ebmeta_equil_steps) { + cvm::real const hills_lambda=(cvm::real(ebmeta_equil_steps - cvm::step_absolute()))/(cvm::real(ebmeta_equil_steps)); + hills_scale = hills_lambda + (1-hills_lambda)*hills_scale; + } + } + + if (well_tempered) { + cvm::real hills_energy_sum_here = 0.0; + if (use_grids) { + std::vector<int> curr_bin = hills_energy->get_colvars_index(); + hills_energy_sum_here = hills_energy->value(curr_bin); } else { - create_hill(hill(hill_weight, colvars, hill_width)); + calc_hills(new_hills_begin, hills.end(), hills_energy_sum_here); } + hills_scale *= std::exp(-1.0*hills_energy_sum_here/(bias_temperature*cvm::boltzmann())); + } + + switch (comm) { + + case single_replica: + + create_hill(hill(hill_weight*hills_scale, colvars, hill_width)); + break; case multiple_replicas: - if (well_tempered) { - cvm::real hills_energy_sum_here = 0.0; - if (use_grids) { - std::vector<int> curr_bin = hills_energy->get_colvars_index(); - hills_energy_sum_here = hills_energy->value(curr_bin); - } else { - calc_hills(new_hills_begin, hills.end(), hills_energy_sum_here); - } - cvm::real const exp_weight = std::exp(-1.0*hills_energy_sum_here/(bias_temperature*cvm::boltzmann())); - create_hill(hill((hill_weight*exp_weight), colvars, hill_width, replica_id)); - } else { - create_hill(hill(hill_weight, colvars, hill_width, replica_id)); - } + create_hill(hill(hill_weight*hills_scale, colvars, hill_width, replica_id)); if (replica_hills_os.is_open()) { replica_hills_os << hills.back(); } else { @@ -1507,7 +1525,9 @@ int colvarbias_meta::setup_output() ("."+replica_id) : ("") )+ ".hills.traj"); - hills_traj_os.open(traj_file_name.c_str()); + if (!hills_traj_os.is_open()) { + hills_traj_os.open(traj_file_name.c_str()); + } if (!hills_traj_os.is_open()) cvm::error("Error: in opening hills output file \"" + traj_file_name+"\".\n", FILE_ERROR); diff --git a/lib/colvars/colvarbias_meta.h b/lib/colvars/colvarbias_meta.h index c021b2ffeba4ce587e1de6b00b48183d3c5e6434..6936e9795454d702a8d825f8f2f0a278f28c1b42 100644 --- a/lib/colvars/colvarbias_meta.h +++ b/lib/colvars/colvarbias_meta.h @@ -147,6 +147,14 @@ protected: /// \brief Biasing temperature in well-tempered metadynamics cvm::real bias_temperature; + // EBmeta parameters + bool ebmeta; + colvar_grid_scalar* target_dist; + std::string target_dist_file; + cvm::real target_dist_volume; + size_t ebmeta_equil_steps; + + /// \brief Try to read the restart information by allocating new /// grids before replacing the current ones (used e.g. in /// multiple_replicas) diff --git a/lib/colvars/colvarcomp.cpp b/lib/colvars/colvarcomp.cpp index 73b1dbd81c132b5bcfc4f7f88b30933839f2096a..050e03f78ed520d7d4068a16734c28eb24ebffc4 100644 --- a/lib/colvars/colvarcomp.cpp +++ b/lib/colvars/colvarcomp.cpp @@ -84,15 +84,12 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf, if (is_available(f_cvc_scalable_com) && is_available(f_cvc_com_based)) { enable(f_cvc_scalable_com); enable(f_cvc_scalable); - group->enable(f_ag_scalable_com); - group->enable(f_ag_scalable); + // The CVC makes the feature available; + // the atom group will enable it unless it needs to compute a rotational fit + group->provide(f_ag_scalable_com); } // TODO check for other types of parallelism here - - if (is_enabled(f_cvc_scalable)) { - cvm::log("Will enable scalable calculation for group \""+group->key+"\".\n"); - } } if (group->parse(conf) == COLVARS_OK) { diff --git a/lib/colvars/colvardeps.cpp b/lib/colvars/colvardeps.cpp index 7736ea14bd1f5f66b786050f3d9102a365a3be6d..a44f86c2925661d410f4cc6a321ed1ccbdcf4f7b 100644 --- a/lib/colvars/colvardeps.cpp +++ b/lib/colvars/colvardeps.cpp @@ -449,8 +449,10 @@ void colvardeps::init_ag_requires() { // Features that are implemented (or not) by all atom groups feature_states[f_ag_active]->available = true; - feature_states[f_ag_scalable_com]->available = (cvm::proxy->scalable_group_coms() == COLVARS_OK); - feature_states[f_ag_scalable]->available = feature_states[f_ag_scalable_com]->available; + // f_ag_scalable_com is provided by the CVC iff it is COM-based + feature_states[f_ag_scalable_com]->available = false; + // TODO make f_ag_scalable depend on f_ag_scalable_com (or something else) + feature_states[f_ag_scalable]->available = true; } diff --git a/lib/colvars/colvarmodule.cpp b/lib/colvars/colvarmodule.cpp index ee5db06e300b6e006cd5a0a9fd19bff6d49a3c28..8e110275b21501208c725c270175ff46e1f11813 100644 --- a/lib/colvars/colvarmodule.cpp +++ b/lib/colvars/colvarmodule.cpp @@ -156,6 +156,12 @@ int colvarmodule::parse_global_params(std::string const &conf) read_index_file(index_file_name.c_str()); } + if (parse->get_keyval(conf, "smp", proxy->b_smp_active, proxy->b_smp_active)) { + if (proxy->b_smp_active == false) { + cvm::log("SMP parallelism has been disabled.\n"); + } + } + parse->get_keyval(conf, "analysis", b_analysis, b_analysis); parse->get_keyval(conf, "debugGradientsStepSize", debug_gradients_step_size, @@ -810,6 +816,7 @@ int colvarmodule::analyze() int colvarmodule::setup() { + if (this->size() == 0) return cvm::get_error(); // loop over all components of all colvars to reset masses of all groups for (std::vector<colvar *>::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) { @@ -867,25 +874,35 @@ int colvarmodule::reset() int colvarmodule::setup_input() { - // name of input state file - restart_in_name = proxy->input_prefix().size() ? - std::string(proxy->input_prefix()+".colvars.state") : - std::string("") ; + if (this->size() == 0) return cvm::get_error(); + + std::string restart_in_name(""); // read the restart configuration, if available - if (restart_in_name.size()) { + if (proxy->input_prefix().size()) { // read the restart file + restart_in_name = proxy->input_prefix(); std::ifstream input_is(restart_in_name.c_str()); if (!input_is.good()) { - cvm::error("Error: in opening restart file \""+ + // try by adding the suffix + input_is.clear(); + restart_in_name = restart_in_name+std::string(".colvars.state"); + input_is.open(restart_in_name.c_str()); + } + + if (!input_is.good()) { + cvm::error("Error: in opening input file \""+ std::string(restart_in_name)+"\".\n", FILE_ERROR); return COLVARS_ERROR; } else { + cvm::log(cvm::line_marker); cvm::log("Restarting from file \""+restart_in_name+"\".\n"); read_restart(input_is); if (cvm::get_error() != COLVARS_OK) { return COLVARS_ERROR; + } else { + proxy->input_prefix().clear(); } cvm::log(cvm::line_marker); } @@ -897,7 +914,9 @@ int colvarmodule::setup_input() int colvarmodule::setup_output() { - int error_code = 0; + if (this->size() == 0) return cvm::get_error(); + + int error_code = COLVARS_OK; // output state file (restart) restart_out_name = proxy->restart_output_prefix().size() ? @@ -1545,11 +1564,7 @@ std::list<std::string> colvarmodule::index_group_names; std::list<std::vector<int> > colvarmodule::index_groups; bool colvarmodule::use_scripted_forces = false; bool colvarmodule::scripting_after_biases = true; - -// file name prefixes std::string colvarmodule::output_prefix = ""; -std::string colvarmodule::restart_in_name = ""; - // i/o constants size_t const colvarmodule::it_width = 12; diff --git a/lib/colvars/colvarmodule.h b/lib/colvars/colvarmodule.h index 0b19d1f779dc95a404a01fe8266bcc9fb4e62ccc..c8df6c7b5eb9f54dc1e752a7fb3c72559c95ac19 100644 --- a/lib/colvars/colvarmodule.h +++ b/lib/colvars/colvarmodule.h @@ -4,7 +4,7 @@ #define COLVARMODULE_H #ifndef COLVARS_VERSION -#define COLVARS_VERSION "2016-10-05" +#define COLVARS_VERSION "2016-10-21" #endif #ifndef COLVARS_DEBUG @@ -12,6 +12,9 @@ #endif /*! \mainpage Main page +This is the Developer's documentation for the Collective Variables Module. + +You can browse the class hierarchy or the list of source files. */ /// \file colvarmodule.h @@ -154,9 +157,6 @@ public: /// Prefix for all output files for this run static std::string output_prefix; - /// input restart file name (determined from input_prefix) - static std::string restart_in_name; - /// Array of collective variables static std::vector<colvar *> colvars; @@ -197,6 +197,11 @@ public: return COLVARS_DEBUG; } + /// \brief How many objects are configured yet? + inline size_t const size() const + { + return colvars.size() + biases.size(); + } /// \brief Constructor \param config_name Configuration file name /// \param restart_name (optional) Restart file name diff --git a/lib/colvars/colvarparse.cpp b/lib/colvars/colvarparse.cpp index e222fa9ecf705b6cca4a4942527885380e79dd0e..86cd00ad29e504138f05e3959ca03fb38e62f6da 100644 --- a/lib/colvars/colvarparse.cpp +++ b/lib/colvars/colvarparse.cpp @@ -644,9 +644,9 @@ bool colvarparse::key_lookup(std::string const &conf, // find the matching closing brace - if (cvm::debug()) { - cvm::log("Multi-line value, config is now \""+line+"\".\n"); - } +// if (cvm::debug()) { +// cvm::log("Multi-line value, config is now \""+line+"\".\n"); +// } int brace_count = 1; @@ -689,9 +689,9 @@ bool colvarparse::key_lookup(std::string const &conf, line_end = nl; line.append(conf, line_begin, (line_end-line_begin)); - if (cvm::debug()) { - cvm::log("Added a new line, config is now \""+line+"\".\n"); - } +// if (cvm::debug()) { +// cvm::log("Added a new line, config is now \""+line+"\".\n"); +// } } if (brace_count < 0) { diff --git a/lib/colvars/colvarproxy.h b/lib/colvars/colvarproxy.h index 3d41cb58a7f3107b639de5ed8f10c12b9467e38f..59f6dc9bb21a57f02ced60741752c147e779aa84 100644 --- a/lib/colvars/colvarproxy.h +++ b/lib/colvars/colvarproxy.h @@ -25,7 +25,7 @@ public: colvarmodule *colvars; /// Default constructor - inline colvarproxy() : script(NULL) {} + inline colvarproxy() : script(NULL), b_smp_active(true) {} /// Default destructor virtual ~colvarproxy() {} @@ -80,7 +80,7 @@ public: /// configuration) std::string input_prefix_str, output_prefix_str, restart_output_prefix_str; - inline std::string input_prefix() + inline std::string & input_prefix() { return input_prefix_str; } @@ -116,12 +116,15 @@ public: // ***************** SHARED-MEMORY PARALLELIZATION ***************** - /// Whether or not threaded parallelization is available + /// Whether threaded parallelization is available (TODO: make this a cvm::deps feature) virtual int smp_enabled() { return COLVARS_NOT_IMPLEMENTED; } + /// Whether threaded parallelization should be used (TODO: make this a cvm::deps feature) + bool b_smp_active; + /// Distribute calculation of colvars (and their components) across threads virtual int smp_colvars_loop() { diff --git a/lib/colvars/colvarscript.cpp b/lib/colvars/colvarscript.cpp index 86b52ac819824a1496f1f15af2790a5a2bcb5bbd..a0269aa7a911d8a1f3321e8df9bd40a6283308b0 100644 --- a/lib/colvars/colvarscript.cpp +++ b/lib/colvars/colvarscript.cpp @@ -14,6 +14,36 @@ colvarscript::colvarscript(colvarproxy *p) { } + +extern "C" { + + // Generic hooks; NAMD and VMD have Tcl-specific versions in the respective proxies + + int run_colvarscript_command(int argc, const char **argv) + { + colvarproxy *cvp = cvm::proxy; + if (!cvp) { + return -1; + } + if (!cvp->script) { + cvm::error("Called run_colvarscript_command without a script object initialized.\n"); + return -1; + } + return cvp->script->run(argc, argv); + } + + const char * get_colvarscript_result() + { + colvarproxy *cvp = cvm::proxy; + if (!cvp->script) { + cvm::error("Called run_colvarscript_command without a script object initialized.\n"); + return ""; + } + return cvp->script->result.c_str(); + } +} + + /// Run method based on given arguments int colvarscript::run(int argc, char const *argv[]) { @@ -125,7 +155,7 @@ int colvarscript::run(int argc, char const *argv[]) { result = "Missing arguments\n" + help_string(); return COLVARSCRIPT_ERROR; } - proxy->input_prefix_str = argv[2]; + proxy->input_prefix() = argv[2]; if (colvars->setup_input() == COLVARS_OK) { return COLVARS_OK; } else { diff --git a/src/USER-COLVARS/colvarproxy_lammps.cpp b/src/USER-COLVARS/colvarproxy_lammps.cpp index dc97db194253e4a2ed8d6367da0b839ecdc51e31..350009f6bf9488b3f225caebe9064821343e1129 100644 --- a/src/USER-COLVARS/colvarproxy_lammps.cpp +++ b/src/USER-COLVARS/colvarproxy_lammps.cpp @@ -333,7 +333,10 @@ int colvarproxy_lammps::backup_file(char const *filename) int colvarproxy_lammps::smp_enabled() { - return COLVARS_OK; + if (b_smp_active) { + return COLVARS_OK; + } + return COLVARS_ERROR; }