version 1.21 | version 1.22 |
---|
| |
// -*- c++ -*- | // -*- c++ -*- |
| |
| // This file is part of the Collective Variables module (Colvars). |
| // The original version of Colvars and its updates are located at: |
| // https://github.com/colvars/colvars |
| // Please update all Colvars source files before making any changes. |
| // If you wish to distribute your changes, please submit them to the |
| // Colvars repository at GitHub. |
| |
#include <iostream> | #include <iostream> |
#include <sstream> | #include <sstream> |
#include <fstream> | #include <fstream> |
| |
| |
| |
colvarbias_meta::colvarbias_meta(char const *key) | colvarbias_meta::colvarbias_meta(char const *key) |
: colvarbias(key), | : colvarbias(key) |
new_hills_begin(hills.end()), | |
state_file_step(0) | |
{ | { |
| new_hills_begin = hills.end(); |
} | } |
| |
| |
| |
| |
provide(f_cvb_history_dependent); | provide(f_cvb_history_dependent); |
| |
| provide(f_cvb_calc_pmf); |
| enable(f_cvb_calc_pmf); |
| |
get_keyval(conf, "hillWeight", hill_weight, 0.0); | get_keyval(conf, "hillWeight", hill_weight, 0.0); |
if (hill_weight > 0.0) { | if (hill_weight > 0.0) { |
enable(f_cvb_apply_force); | enable(f_cvb_apply_force); |
| |
| |
get_keyval(conf, "hillWidth", hill_width, std::sqrt(2.0 * PI) / 2.0); | get_keyval(conf, "hillWidth", hill_width, std::sqrt(2.0 * PI) / 2.0); |
cvm::log("Half-widths of the Gaussian hills (sigma's):\n"); | cvm::log("Half-widths of the Gaussian hills (sigma's):\n"); |
for (size_t i = 0; i < colvars.size(); i++) { | for (size_t i = 0; i < num_variables(); i++) { |
cvm::log(colvars[i]->name+std::string(": ")+ | cvm::log(variables(i)->name+std::string(": ")+ |
cvm::to_str(0.5 * colvars[i]->width * hill_width)); | cvm::to_str(0.5 * variables(i)->width * hill_width)); |
} | } |
| |
{ | { |
| |
comm = single_replica; | comm = single_replica; |
} | } |
| |
// This implies gradients for all colvars | // in all cases, the first replica is this bias itself |
enable(f_cvb_apply_force); | if (replicas.size() == 0) { |
| replicas.push_back(this); |
| } |
| |
get_keyval(conf, "useGrids", use_grids, true); | get_keyval(conf, "useGrids", use_grids, true); |
| |
| |
| |
expand_grids = false; | expand_grids = false; |
size_t i; | size_t i; |
for (i = 0; i < colvars.size(); i++) { | for (i = 0; i < num_variables(); i++) { |
colvars[i]->enable(f_cv_grid); | variables(i)->enable(f_cv_grid); |
if (colvars[i]->expand_boundaries) { | if (variables(i)->expand_boundaries) { |
expand_grids = true; | expand_grids = true; |
cvm::log("Metadynamics bias \""+this->name+"\""+ | cvm::log("Metadynamics bias \""+this->name+"\""+ |
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ | ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ |
": Will expand grids when the colvar \""+ | ": Will expand grids when the colvar \""+ |
colvars[i]->name+"\" approaches its boundaries.\n"); | variables(i)->name+"\" approaches its boundaries.\n"); |
} | } |
} | } |
| |
| |
get_keyval(conf, "dumpFreeEnergyFile", dump_fes, true, colvarparse::parse_silent); | get_keyval(conf, "dumpFreeEnergyFile", dump_fes, true, colvarparse::parse_silent); |
if (get_keyval(conf, "saveFreeEnergyFile", dump_fes_save, false, colvarparse::parse_silent)) { | if (get_keyval(conf, "saveFreeEnergyFile", dump_fes_save, false, colvarparse::parse_silent)) { |
cvm::log("Option \"saveFreeEnergyFile\" is deprecated, " | cvm::log("Option \"saveFreeEnergyFile\" is deprecated, " |
"please use \"keepFreeEnergyFiles\" instead."); | "please use \"keepFreeEnergyFile\" instead."); |
} | } |
get_keyval(conf, "keepFreeEnergyFiles", dump_fes_save, dump_fes_save); | get_keyval(conf, "keepFreeEnergyFiles", dump_fes_save, dump_fes_save); |
| |
| |
| |
get_keyval(conf, "writeHillsTrajectory", b_hills_traj, false); | get_keyval(conf, "writeHillsTrajectory", b_hills_traj, false); |
| |
| init_well_tempered_params(conf); |
| init_ebmeta_params(conf); |
| |
| if (cvm::debug()) |
| cvm::log("Done initializing the metadynamics bias \""+this->name+"\""+ |
| ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+".\n"); |
| |
| save_delimiters = false; |
| return COLVARS_OK; |
| } |
| |
| |
| int colvarbias_meta::init_well_tempered_params(std::string const &conf) |
| { |
// for well-tempered metadynamics | // for well-tempered metadynamics |
get_keyval(conf, "wellTempered", well_tempered, false); | get_keyval(conf, "wellTempered", well_tempered, false); |
get_keyval(conf, "biasTemperature", bias_temperature, -1.0); | get_keyval(conf, "biasTemperature", bias_temperature, -1.0); |
| |
cvm::log("Well-tempered metadynamics is used.\n"); | cvm::log("Well-tempered metadynamics is used.\n"); |
cvm::log("The bias temperature is "+cvm::to_str(bias_temperature)+".\n"); | cvm::log("The bias temperature is "+cvm::to_str(bias_temperature)+".\n"); |
} | } |
| return COLVARS_OK; |
| } |
| |
| |
| int colvarbias_meta::init_ebmeta_params(std::string const &conf) |
| { |
// for ebmeta | // for ebmeta |
target_dist = NULL; | target_dist = NULL; |
get_keyval(conf, "ebMeta", ebmeta, false); | get_keyval(conf, "ebMeta", ebmeta, false); |
| |
get_keyval(conf, "ebMetaEquilSteps", ebmeta_equil_steps, 0); | 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"); | |
| |
save_delimiters = false; | |
return COLVARS_OK; | return COLVARS_OK; |
} | } |
| |
| |
delete target_dist; | delete target_dist; |
target_dist = NULL; | target_dist = NULL; |
} | } |
| |
if (cvm::n_meta_biases > 0) | |
cvm::n_meta_biases -= 1; | |
} | } |
| |
| |
| |
| |
int colvarbias_meta::update() | int colvarbias_meta::update() |
{ | { |
if (cvm::debug()) | int error_code = COLVARS_OK; |
cvm::log("Updating the metadynamics bias \""+this->name+"\""+ | |
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+".\n"); | |
| |
if (use_grids) { | // update base class |
| error_code |= colvarbias::update(); |
| |
std::vector<int> curr_bin = hills_energy->get_colvars_index(); | // update grid definition, if needed |
| error_code |= update_grid_params(); |
| // add new biasing energy/forces |
| error_code |= update_bias(); |
| // update grid content to reflect new bias |
| error_code |= update_grid_data(); |
| |
if (expand_grids) { | if (comm != single_replica && |
| (cvm::step_absolute() % replica_update_freq) == 0) { |
| // sync with the other replicas (if needed) |
| error_code |= replica_share(); |
| } |
| |
// first of all, expand the grids, if specified | error_code |= calc_energy(); |
if (cvm::debug()) | error_code |= calc_forces(); |
| |
| return error_code; |
| } |
| |
| |
| int colvarbias_meta::update_grid_params() |
| { |
| if (use_grids) { |
| |
| std::vector<int> curr_bin = hills_energy->get_colvars_index(); |
| if (cvm::debug()) { |
cvm::log("Metadynamics bias \""+this->name+"\""+ | cvm::log("Metadynamics bias \""+this->name+"\""+ |
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ | ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ |
": current coordinates on the grid: "+ | ": current coordinates on the grid: "+ |
cvm::to_str(curr_bin)+".\n"); | cvm::to_str(curr_bin)+".\n"); |
| } |
| |
| if (expand_grids) { |
| // first of all, expand the grids, if specified |
bool changed_grids = false; | bool changed_grids = false; |
int const min_buffer = | int const min_buffer = |
(3 * (size_t) std::floor(hill_width)) + 1; | (3 * (size_t) std::floor(hill_width)) + 1; |
| |
std::vector<colvarvalue> new_lower_boundaries(hills_energy->lower_boundaries); | std::vector<colvarvalue> new_lower_boundaries(hills_energy->lower_boundaries); |
std::vector<colvarvalue> new_upper_boundaries(hills_energy->upper_boundaries); | std::vector<colvarvalue> new_upper_boundaries(hills_energy->upper_boundaries); |
| |
for (size_t i = 0; i < colvars.size(); i++) { | for (size_t i = 0; i < num_variables(); i++) { |
| |
if (! colvars[i]->expand_boundaries) | if (! variables(i)->expand_boundaries) |
continue; | continue; |
| |
cvm::real &new_lb = new_lower_boundaries[i].real_value; | cvm::real &new_lb = new_lower_boundaries[i].real_value; |
| |
int &new_size = new_sizes[i]; | int &new_size = new_sizes[i]; |
bool changed_lb = false, changed_ub = false; | bool changed_lb = false, changed_ub = false; |
| |
if (!colvars[i]->hard_lower_boundary) | if (!variables(i)->hard_lower_boundary) |
if (curr_bin[i] < min_buffer) { | if (curr_bin[i] < min_buffer) { |
int const extra_points = (min_buffer - curr_bin[i]); | int const extra_points = (min_buffer - curr_bin[i]); |
new_lb -= extra_points * colvars[i]->width; | new_lb -= extra_points * variables(i)->width; |
new_size += extra_points; | new_size += extra_points; |
// changed offset in this direction => the pointer needs to | // changed offset in this direction => the pointer needs to |
// be changed, too | // be changed, too |
| |
cvm::log("Metadynamics bias \""+this->name+"\""+ | cvm::log("Metadynamics bias \""+this->name+"\""+ |
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ | ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ |
": new lower boundary for colvar \""+ | ": new lower boundary for colvar \""+ |
colvars[i]->name+"\", at "+ | variables(i)->name+"\", at "+ |
cvm::to_str(new_lower_boundaries[i])+".\n"); | cvm::to_str(new_lower_boundaries[i])+".\n"); |
} | } |
| |
if (!colvars[i]->hard_upper_boundary) | if (!variables(i)->hard_upper_boundary) |
if (curr_bin[i] > new_size - min_buffer - 1) { | if (curr_bin[i] > new_size - min_buffer - 1) { |
int const extra_points = (curr_bin[i] - (new_size - 1) + min_buffer); | int const extra_points = (curr_bin[i] - (new_size - 1) + min_buffer); |
new_ub += extra_points * colvars[i]->width; | new_ub += extra_points * variables(i)->width; |
new_size += extra_points; | new_size += extra_points; |
| |
changed_ub = true; | changed_ub = true; |
cvm::log("Metadynamics bias \""+this->name+"\""+ | cvm::log("Metadynamics bias \""+this->name+"\""+ |
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ | ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ |
": new upper boundary for colvar \""+ | ": new upper boundary for colvar \""+ |
colvars[i]->name+"\", at "+ | variables(i)->name+"\", at "+ |
cvm::to_str(new_upper_boundaries[i])+".\n"); | cvm::to_str(new_upper_boundaries[i])+".\n"); |
} | } |
| |
| |
| |
new_hills_energy_gradients->lower_boundaries = new_lower_boundaries; | new_hills_energy_gradients->lower_boundaries = new_lower_boundaries; |
new_hills_energy_gradients->upper_boundaries = new_upper_boundaries; | new_hills_energy_gradients->upper_boundaries = new_upper_boundaries; |
new_hills_energy_gradients->setup(new_sizes, 0.0, colvars.size()); | new_hills_energy_gradients->setup(new_sizes, 0.0, num_variables()); |
| |
new_hills_energy->map_grid(*hills_energy); | new_hills_energy->map_grid(*hills_energy); |
new_hills_energy_gradients->map_grid(*hills_energy_gradients); | new_hills_energy_gradients->map_grid(*hills_energy_gradients); |
| |
} | } |
} | } |
} | } |
| return COLVARS_OK; |
| } |
| |
| |
| int colvarbias_meta::update_bias() |
| { |
// add a new hill if the required time interval has passed | // add a new hill if the required time interval has passed |
if ((cvm::step_absolute() % new_hill_freq) == 0) { | if ((cvm::step_absolute() % new_hill_freq) == 0 && |
| is_enabled(f_cvb_history_dependent)) { |
| |
if (cvm::debug()) | if (cvm::debug()) { |
cvm::log("Metadynamics bias \""+this->name+"\""+ | cvm::log("Metadynamics bias \""+this->name+"\""+ |
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ | ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ |
": adding a new hill at step "+cvm::to_str(cvm::step_absolute())+".\n"); | ": adding a new hill at step "+cvm::to_str(cvm::step_absolute())+".\n"); |
| } |
| |
cvm::real hills_scale=1.0; | cvm::real hills_scale=1.0; |
| |
| |
} | } |
} | } |
| |
// sync with the other replicas (if needed) | return COLVARS_OK; |
if (comm != single_replica) { | |
| |
// reread the replicas registry | |
if ((cvm::step_absolute() % replica_update_freq) == 0) { | |
update_replicas_registry(); | |
// empty the output buffer | |
if (replica_hills_os.is_open()) | |
replica_hills_os.flush(); | |
| |
read_replica_files(); | |
} | |
} | |
| |
// calculate the biasing energy and forces | |
bias_energy = 0.0; | |
for (size_t ir = 0; ir < colvars.size(); ir++) { | |
colvar_forces[ir].reset(); | |
} | |
if (comm == multiple_replicas) | |
for (size_t ir = 0; ir < replicas.size(); ir++) { | |
replicas[ir]->bias_energy = 0.0; | |
for (size_t ic = 0; ic < colvars.size(); ic++) { | |
replicas[ir]->colvar_forces[ic].reset(); | |
} | |
} | } |
| |
if (use_grids) { | |
| |
// get the forces from the grid | |
| |
| int colvarbias_meta::update_grid_data() |
| { |
if ((cvm::step_absolute() % grids_freq) == 0) { | if ((cvm::step_absolute() % grids_freq) == 0) { |
// map the most recent gaussians to the grids | // map the most recent gaussians to the grids |
project_hills(new_hills_begin, hills.end(), | project_hills(new_hills_begin, hills.end(), |
| |
} | } |
} | } |
| |
std::vector<int> curr_bin = hills_energy->get_colvars_index(); | return COLVARS_OK; |
if (cvm::debug()) | } |
| |
| |
| int colvarbias_meta::calc_energy(std::vector<colvarvalue> const &values) |
| { |
| size_t ir = 0; |
| |
| for (ir = 0; ir < replicas.size(); ir++) { |
| replicas[ir]->bias_energy = 0.0; |
| } |
| |
| std::vector<int> const curr_bin = values.size() ? |
| hills_energy->get_colvars_index(values) : |
| hills_energy->get_colvars_index(); |
| |
| if (hills_energy->index_ok(curr_bin)) { |
| // index is within the grid: get the energy from there |
| for (ir = 0; ir < replicas.size(); ir++) { |
| |
| bias_energy += replicas[ir]->hills_energy->value(curr_bin); |
| if (cvm::debug()) { |
cvm::log("Metadynamics bias \""+this->name+"\""+ | cvm::log("Metadynamics bias \""+this->name+"\""+ |
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ | ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ |
": current coordinates on the grid: "+ | ": current coordinates on the grid: "+ |
cvm::to_str(curr_bin)+".\n"); | cvm::to_str(curr_bin)+".\n"); |
| cvm::log("Grid energy = "+cvm::to_str(bias_energy)+".\n"); |
| } |
| } |
| } else { |
| // off the grid: compute analytically only the hills at the grid's edges |
| for (ir = 0; ir < replicas.size(); ir++) { |
| calc_hills(replicas[ir]->hills_off_grid.begin(), |
| replicas[ir]->hills_off_grid.end(), |
| bias_energy, |
| values); |
| } |
| } |
| |
if (hills_energy->index_ok(curr_bin)) { | // now include the hills that have not been binned yet (starting |
| // from new_hills_begin) |
| |
| for (ir = 0; ir < replicas.size(); ir++) { |
| calc_hills(replicas[ir]->new_hills_begin, |
| replicas[ir]->hills.end(), |
| bias_energy); |
| if (cvm::debug()) { |
| cvm::log("Hills energy = "+cvm::to_str(bias_energy)+".\n"); |
| } |
| } |
| |
// within the grid: add the energy and the forces from there | return COLVARS_OK; |
| } |
| |
bias_energy += hills_energy->value(curr_bin); | |
for (size_t ic = 0; ic < colvars.size(); ic++) { | int colvarbias_meta::calc_forces(std::vector<colvarvalue> const &values) |
cvm::real const *f = &(hills_energy_gradients->value(curr_bin)); | { |
colvar_forces[ic].real_value += -1.0 * f[ic]; | size_t ir = 0, ic = 0; |
// the gradients are stored, not the forces | for (ir = 0; ir < replicas.size(); ir++) { |
| for (ic = 0; ic < num_variables(); ic++) { |
| replicas[ir]->colvar_forces[ic].reset(); |
} | } |
if (comm == multiple_replicas) | } |
for (size_t ir = 0; ir < replicas.size(); ir++) { | |
bias_energy += replicas[ir]->hills_energy->value(curr_bin); | std::vector<int> const curr_bin = values.size() ? |
| hills_energy->get_colvars_index(values) : |
| hills_energy->get_colvars_index(); |
| |
| if (hills_energy->index_ok(curr_bin)) { |
| for (ir = 0; ir < replicas.size(); ir++) { |
cvm::real const *f = &(replicas[ir]->hills_energy_gradients->value(curr_bin)); | cvm::real const *f = &(replicas[ir]->hills_energy_gradients->value(curr_bin)); |
for (size_t ic = 0; ic < colvars.size(); ic++) { | for (ic = 0; ic < num_variables(); ic++) { |
| // the gradients are stored, not the forces |
colvar_forces[ic].real_value += -1.0 * f[ic]; | colvar_forces[ic].real_value += -1.0 * f[ic]; |
} | } |
} | } |
| |
} else { | } else { |
| |
// off the grid: compute analytically only the hills at the grid's edges | // off the grid: compute analytically only the hills at the grid's edges |
| for (ir = 0; ir < replicas.size(); ir++) { |
calc_hills(hills_off_grid.begin(), hills_off_grid.end(), bias_energy); | for (ic = 0; ic < num_variables(); ic++) { |
for (size_t ic = 0; ic < colvars.size(); ic++) { | |
calc_hills_force(ic, hills_off_grid.begin(), hills_off_grid.end(), colvar_forces); | |
} | |
| |
if (comm == multiple_replicas) | |
for (size_t ir = 0; ir < replicas.size(); ir++) { | |
calc_hills(replicas[ir]->hills_off_grid.begin(), | |
replicas[ir]->hills_off_grid.end(), | |
bias_energy); | |
for (size_t ic = 0; ic < colvars.size(); ic++) { | |
calc_hills_force(ic, | calc_hills_force(ic, |
replicas[ir]->hills_off_grid.begin(), | replicas[ir]->hills_off_grid.begin(), |
replicas[ir]->hills_off_grid.end(), | replicas[ir]->hills_off_grid.end(), |
colvar_forces); | colvar_forces, |
} | values); |
} | } |
} | } |
} | } |
| |
// now include the hills that have not been binned yet (starting | // now include the hills that have not been binned yet (starting |
// from new_hills_begin) | // from new_hills_begin) |
| |
calc_hills(new_hills_begin, hills.end(), bias_energy); | if (cvm::debug()) { |
for (size_t ic = 0; ic < colvars.size(); ic++) { | |
calc_hills_force(ic, new_hills_begin, hills.end(), colvar_forces); | |
} | |
| |
if (cvm::debug()) | |
cvm::log("Hills energy = "+cvm::to_str(bias_energy)+ | |
", hills forces = "+cvm::to_str(colvar_forces)+".\n"); | |
| |
if (cvm::debug()) | |
cvm::log("Metadynamics bias \""+this->name+"\""+ | cvm::log("Metadynamics bias \""+this->name+"\""+ |
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ | ((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ |
": adding the forces from the other replicas.\n"); | ": adding the forces from the other replicas.\n"); |
| } |
| |
if (comm == multiple_replicas) | for (ir = 0; ir < replicas.size(); ir++) { |
for (size_t ir = 0; ir < replicas.size(); ir++) { | for (ic = 0; ic < num_variables(); ic++) { |
calc_hills(replicas[ir]->new_hills_begin, | |
replicas[ir]->hills.end(), | |
bias_energy); | |
for (size_t ic = 0; ic < colvars.size(); ic++) { | |
calc_hills_force(ic, | calc_hills_force(ic, |
replicas[ir]->new_hills_begin, | replicas[ir]->new_hills_begin, |
replicas[ir]->hills.end(), | replicas[ir]->hills.end(), |
colvar_forces); | colvar_forces, |
| values); |
| if (cvm::debug()) { |
| cvm::log("Hills forces = "+cvm::to_str(colvar_forces)+".\n"); |
| } |
} | } |
if (cvm::debug()) | |
cvm::log("Hills energy = "+cvm::to_str(bias_energy)+ | |
", hills forces = "+cvm::to_str(colvar_forces)+".\n"); | |
} | } |
| |
return COLVARS_OK; | return COLVARS_OK; |
} | } |
| |
| |
| |
void colvarbias_meta::calc_hills(colvarbias_meta::hill_iter h_first, | void colvarbias_meta::calc_hills(colvarbias_meta::hill_iter h_first, |
colvarbias_meta::hill_iter h_last, | colvarbias_meta::hill_iter h_last, |
cvm::real &energy, | cvm::real &energy, |
std::vector<colvarvalue> const &colvar_values) | std::vector<colvarvalue> const &colvar_values) |
{ | { |
std::vector<colvarvalue> curr_values(colvars.size()); | size_t i = 0; |
for (size_t i = 0; i < colvars.size(); i++) { | std::vector<colvarvalue> curr_values(num_variables()); |
curr_values[i].type(colvars[i]->value()); | for (i = 0; i < num_variables(); i++) { |
| curr_values[i].type(variables(i)->value()); |
} | } |
| |
if (colvar_values.size()) { | if (colvar_values.size()) { |
for (size_t i = 0; i < colvars.size(); i++) { | for (i = 0; i < num_variables(); i++) { |
curr_values[i] = colvar_values[i]; | curr_values[i] = colvar_values[i]; |
} | } |
} else { | } else { |
for (size_t i = 0; i < colvars.size(); i++) { | for (i = 0; i < num_variables(); i++) { |
curr_values[i] = colvars[i]->value(); | curr_values[i] = variables(i)->value(); |
} | } |
} | } |
| |
| |
| |
// compute the gaussian exponent | // compute the gaussian exponent |
cvm::real cv_sqdev = 0.0; | cvm::real cv_sqdev = 0.0; |
for (size_t i = 0; i < colvars.size(); i++) { | for (i = 0; i < num_variables(); i++) { |
colvarvalue const &x = curr_values[i]; | colvarvalue const &x = curr_values[i]; |
colvarvalue const ¢er = h->centers[i]; | colvarvalue const ¢er = h->centers[i]; |
cvm::real const half_width = 0.5 * h->widths[i]; | cvm::real const half_width = 0.5 * h->widths[i]; |
cv_sqdev += (colvars[i]->dist2(x, center)) / (half_width*half_width); | cv_sqdev += (variables(i)->dist2(x, center)) / (half_width*half_width); |
} | } |
| |
// compute the gaussian | // compute the gaussian |
| |
std::vector<colvarvalue> const &values) | std::vector<colvarvalue> const &values) |
{ | { |
// Retrieve the value of the colvar | // Retrieve the value of the colvar |
colvarvalue const x(values.size() ? values[i] : colvars[i]->value()); | colvarvalue const x(values.size() ? values[i] : variables(i)->value()); |
| |
// do the type check only once (all colvarvalues in the hills series | // do the type check only once (all colvarvalues in the hills series |
// were already saved with their types matching those in the | // were already saved with their types matching those in the |
// colvars) | // colvars) |
| |
hill_iter h; | hill_iter h; |
switch (colvars[i]->value().type()) { | switch (variables(i)->value().type()) { |
| |
case colvarvalue::type_scalar: | case colvarvalue::type_scalar: |
for (h = h_first; h != h_last; h++) { | for (h = h_first; h != h_last; h++) { |
| |
cvm::real const half_width = 0.5 * h->widths[i]; | cvm::real const half_width = 0.5 * h->widths[i]; |
forces[i].real_value += | forces[i].real_value += |
( h->weight() * h->value() * (0.5 / (half_width*half_width)) * | ( h->weight() * h->value() * (0.5 / (half_width*half_width)) * |
(colvars[i]->dist2_lgrad(x, center)).real_value ); | (variables(i)->dist2_lgrad(x, center)).real_value ); |
} | } |
break; | break; |
| |
| |
cvm::real const half_width = 0.5 * h->widths[i]; | cvm::real const half_width = 0.5 * h->widths[i]; |
forces[i].rvector_value += | forces[i].rvector_value += |
( h->weight() * h->value() * (0.5 / (half_width*half_width)) * | ( h->weight() * h->value() * (0.5 / (half_width*half_width)) * |
(colvars[i]->dist2_lgrad(x, center)).rvector_value ); | (variables(i)->dist2_lgrad(x, center)).rvector_value ); |
} | } |
break; | break; |
| |
| |
cvm::real const half_width = 0.5 * h->widths[i]; | cvm::real const half_width = 0.5 * h->widths[i]; |
forces[i].quaternion_value += | forces[i].quaternion_value += |
( h->weight() * h->value() * (0.5 / (half_width*half_width)) * | ( h->weight() * h->value() * (0.5 / (half_width*half_width)) * |
(colvars[i]->dist2_lgrad(x, center)).quaternion_value ); | (variables(i)->dist2_lgrad(x, center)).quaternion_value ); |
} | } |
break; | break; |
| |
| |
cvm::real const half_width = 0.5 * h->widths[i]; | cvm::real const half_width = 0.5 * h->widths[i]; |
forces[i].vector1d_value += | forces[i].vector1d_value += |
( h->weight() * h->value() * (0.5 / (half_width*half_width)) * | ( h->weight() * h->value() * (0.5 / (half_width*half_width)) * |
(colvars[i]->dist2_lgrad(x, center)).vector1d_value ); | (variables(i)->dist2_lgrad(x, center)).vector1d_value ); |
} | } |
break; | break; |
| |
| |
| |
// TODO: improve it by looping over a small subgrid instead of the whole grid | // TODO: improve it by looping over a small subgrid instead of the whole grid |
| |
std::vector<colvarvalue> colvar_values(colvars.size()); | std::vector<colvarvalue> colvar_values(num_variables()); |
std::vector<cvm::real> colvar_forces_scalar(colvars.size()); | std::vector<cvm::real> colvar_forces_scalar(num_variables()); |
| |
std::vector<int> he_ix = he->new_index(); | std::vector<int> he_ix = he->new_index(); |
std::vector<int> hg_ix = (hg != NULL) ? hg->new_index() : std::vector<int> (0); | std::vector<int> hg_ix = (hg != NULL) ? hg->new_index() : std::vector<int> (0); |
cvm::real hills_energy_here = 0.0; | cvm::real hills_energy_here = 0.0; |
std::vector<colvarvalue> hills_forces_here(colvars.size(), 0.0); | std::vector<colvarvalue> hills_forces_here(num_variables(), 0.0); |
| |
size_t count = 0; | size_t count = 0; |
size_t const print_frequency = ((hills.size() >= 1000000) ? 1 : (1000000/(hills.size()+1))); | size_t const print_frequency = ((hills.size() >= 1000000) ? 1 : (1000000/(hills.size()+1))); |
| |
(he->index_ok(he_ix)) && (hg->index_ok(hg_ix)); | (he->index_ok(he_ix)) && (hg->index_ok(hg_ix)); |
count++) { | count++) { |
size_t i; | size_t i; |
for (i = 0; i < colvars.size(); i++) { | for (i = 0; i < num_variables(); i++) { |
colvar_values[i] = hills_energy->bin_to_value_scalar(he_ix[i], i); | colvar_values[i] = hills_energy->bin_to_value_scalar(he_ix[i], i); |
} | } |
| |
| |
calc_hills(h_first, h_last, hills_energy_here, colvar_values); | calc_hills(h_first, h_last, hills_energy_here, colvar_values); |
he->acc_value(he_ix, hills_energy_here); | he->acc_value(he_ix, hills_energy_here); |
| |
for (i = 0; i < colvars.size(); i++) { | for (i = 0; i < num_variables(); i++) { |
hills_forces_here[i].reset(); | hills_forces_here[i].reset(); |
calc_hills_force(i, h_first, h_last, hills_forces_here, colvar_values); | calc_hills_force(i, h_first, h_last, hills_forces_here, colvar_values); |
colvar_forces_scalar[i] = hills_forces_here[i].real_value; | colvar_forces_scalar[i] = hills_forces_here[i].real_value; |
| |
| |
for ( ; (he->index_ok(he_ix)); ) { | for ( ; (he->index_ok(he_ix)); ) { |
| |
for (size_t i = 0; i < colvars.size(); i++) { | for (size_t i = 0; i < num_variables(); i++) { |
colvar_values[i] = hills_energy->bin_to_value_scalar(he_ix[i], i); | colvar_values[i] = hills_energy->bin_to_value_scalar(he_ix[i], i); |
} | } |
| |
| |
// ********************************************************************** | // ********************************************************************** |
| |
| |
| int colvarbias_meta::replica_share() |
| { |
| // sync with the other replicas (if needed) |
| if (comm == multiple_replicas) { |
| // reread the replicas registry |
| update_replicas_registry(); |
| // empty the output buffer |
| if (replica_hills_os.is_open()) |
| replica_hills_os.flush(); |
| read_replica_files(); |
| } |
| return COLVARS_OK; |
| } |
| |
| |
void colvarbias_meta::update_replicas_registry() | void colvarbias_meta::update_replicas_registry() |
{ | { |
if (cvm::debug()) | if (cvm::debug()) |
| |
} | } |
} | } |
| |
| |
if (cvm::debug()) | if (cvm::debug()) |
cvm::log("Metadynamics bias \""+this->name+"\": the list of replicas contains "+ | cvm::log("Metadynamics bias \""+this->name+"\": the list of replicas contains "+ |
cvm::to_str(replicas.size())+" elements.\n"); | cvm::to_str(replicas.size())+" elements.\n"); |
| |
| |
void colvarbias_meta::read_replica_files() | void colvarbias_meta::read_replica_files() |
{ | { |
for (size_t ir = 0; ir < replicas.size(); ir++) { | // Note: we start from the 2nd replica. |
| for (size_t ir = 1; ir < replicas.size(); ir++) { |
| |
if (! (replicas[ir])->replica_state_file_in_sync) { | if (! (replicas[ir])->replica_state_file_in_sync) { |
// if a new state file is being read, the hills file is also new | // if a new state file is being read, the hills file is also new |
| |
(replicas[ir])->replica_state_file+"\".\n"); | (replicas[ir])->replica_state_file+"\".\n"); |
| |
std::ifstream is((replicas[ir])->replica_state_file.c_str()); | std::ifstream is((replicas[ir])->replica_state_file.c_str()); |
if (! (replicas[ir])->read_restart(is)) { | if (! (replicas[ir])->read_state(is)) { |
cvm::log("Reading from file \""+(replicas[ir])->replica_state_file+ | cvm::log("Reading from file \""+(replicas[ir])->replica_state_file+ |
"\" failed or incomplete: will try again in "+ | "\" failed or incomplete: will try again in "+ |
cvm::to_str(replica_update_freq)+" steps.\n"); | cvm::to_str(replica_update_freq)+" steps.\n"); |
| |
} | } |
| |
| |
// ********************************************************************** | int colvarbias_meta::set_state_params(std::string const &state_conf) |
// input functions | |
// ********************************************************************** | |
| |
| |
std::istream & colvarbias_meta::read_restart(std::istream& is) | |
{ | { |
size_t const start_pos = is.tellg(); | std::string new_replica = ""; |
| if (colvarparse::get_keyval(state_conf, "replicaID", new_replica, |
if (comm == single_replica) { | |
// if using a multiple replicas scheme, output messages | |
// are printed before and after calling this function | |
cvm::log("Restarting metadynamics bias \""+this->name+"\""+ | |
".\n"); | |
} | |
std::string key, brace, conf; | |
if ( !(is >> key) || !(key == "metadynamics") || | |
!(is >> brace) || !(brace == "{") || | |
!(is >> colvarparse::read_block("configuration", conf)) ) { | |
| |
if (comm == single_replica) | |
cvm::log("Error: in reading restart configuration for metadynamics bias \""+ | |
this->name+"\""+ | |
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ | |
(replica_state_file_in_sync ? ("at position "+ | |
cvm::to_str(start_pos)+ | |
" in the state file") : "")+".\n"); | |
is.clear(); | |
is.seekg(start_pos, std::ios::beg); | |
is.setstate(std::ios::failbit); | |
return is; | |
} | |
| |
std::string name = ""; | |
if ( colvarparse::get_keyval(conf, "name", name, | |
std::string(""), colvarparse::parse_silent) && | std::string(""), colvarparse::parse_silent) && |
(name != this->name) ) | (new_replica != this->replica_id)) { |
cvm::fatal_error("Error: in the restart file, the " | cvm::error("Error: in the state file, the " |
"\"metadynamics\" block has a different name: different system?\n"); | "\"metadynamics\" block has a different replicaID: different system?\n", |
| INPUT_ERROR); |
if (name.size() == 0) { | return INPUT_ERROR; |
cvm::fatal_error("Error: \"metadynamics\" block within the restart file " | |
"has no identifiers.\n"); | |
} | } |
| |
if (comm != single_replica) { | return COLVARS_OK; |
std::string replica = ""; | |
if (colvarparse::get_keyval(conf, "replicaID", replica, | |
std::string(""), colvarparse::parse_silent) && | |
(replica != this->replica_id)) | |
cvm::fatal_error("Error: in the restart file, the " | |
"\"metadynamics\" block has a different replicaID: different system?\n"); | |
| |
colvarparse::get_keyval(conf, "step", state_file_step, | |
cvm::step_absolute(), colvarparse::parse_silent); | |
} | } |
| |
| |
| std::istream & colvarbias_meta::read_state_data(std::istream& is) |
| { |
bool grids_from_restart_file = use_grids; | bool grids_from_restart_file = use_grids; |
| |
if (use_grids) { | if (use_grids) { |
| |
} | } |
| |
size_t const hills_energy_pos = is.tellg(); | size_t const hills_energy_pos = is.tellg(); |
| std::string key; |
if (!(is >> key)) { | if (!(is >> key)) { |
if (hills_energy_backup != NULL) { | if (hills_energy_backup != NULL) { |
delete hills_energy; | delete hills_energy; |
| |
} | } |
} | } |
| |
is >> brace; | |
if (brace != "}") { | |
cvm::log("Incomplete restart information for metadynamics bias \""+ | |
this->name+"\""+ | |
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+ | |
": no closing brace at position "+ | |
cvm::to_str(is.tellg())+" in the file.\n"); | |
is.setstate(std::ios::failbit); | |
return is; | |
} | |
| |
if (cvm::debug()) | if (cvm::debug()) |
cvm::log("colvarbias_meta::read_restart() done\n"); | cvm::log("colvarbias_meta::read_restart() done\n"); |
| |
| |
cvm::real h_weight; | cvm::real h_weight; |
get_keyval(data, "weight", h_weight, hill_weight, parse_silent); | get_keyval(data, "weight", h_weight, hill_weight, parse_silent); |
| |
std::vector<colvarvalue> h_centers(colvars.size()); | std::vector<colvarvalue> h_centers(num_variables()); |
for (size_t i = 0; i < colvars.size(); i++) { | for (size_t i = 0; i < num_variables(); i++) { |
h_centers[i].type(colvars[i]->value()); | h_centers[i].type(variables(i)->value()); |
} | } |
{ | { |
// it is safer to read colvarvalue objects one at a time; | // it is safer to read colvarvalue objects one at a time; |
| |
std::string centers_input; | std::string centers_input; |
key_lookup(data, "centers", centers_input); | key_lookup(data, "centers", centers_input); |
std::istringstream centers_is(centers_input); | std::istringstream centers_is(centers_input); |
for (size_t i = 0; i < colvars.size(); i++) { | for (size_t i = 0; i < num_variables(); i++) { |
centers_is >> h_centers[i]; | centers_is >> h_centers[i]; |
} | } |
} | } |
| |
std::vector<cvm::real> h_widths(colvars.size()); | std::vector<cvm::real> h_widths(num_variables()); |
get_keyval(data, "widths", h_widths, | get_keyval(data, "widths", h_widths, |
std::vector<cvm::real> (colvars.size(), (std::sqrt(2.0 * PI) / 2.0)), | std::vector<cvm::real>(num_variables(), (std::sqrt(2.0 * PI) / 2.0)), |
parse_silent); | parse_silent); |
| |
std::string h_replica = ""; | std::string h_replica = ""; |
| |
} | } |
| |
| |
| |
| |
// ********************************************************************** | |
// output functions | |
// ********************************************************************** | |
| |
| |
int colvarbias_meta::setup_output() | int colvarbias_meta::setup_output() |
{ | { |
| output_prefix = cvm::output_prefix(); |
| if (cvm::num_biases_feature(colvardeps::f_cvb_calc_pmf) > 1) { |
| // if this is not the only free energy integrator, append |
| // this bias's name, to distinguish it from the output of the other |
| // biases producing a .pmf file |
| output_prefix += ("."+this->name); |
| } |
| |
if (comm == multiple_replicas) { | if (comm == multiple_replicas) { |
| |
| |
// those by another replica | // those by another replica |
replica_hills_file = | replica_hills_file = |
(std::string(pwd)+std::string(PATHSEP)+ | (std::string(pwd)+std::string(PATHSEP)+ |
cvm::output_prefix+".colvars."+this->name+"."+replica_id+".hills"); | cvm::output_prefix()+".colvars."+this->name+"."+replica_id+".hills"); |
replica_state_file = | replica_state_file = |
(std::string(pwd)+std::string(PATHSEP)+ | (std::string(pwd)+std::string(PATHSEP)+ |
cvm::output_prefix+".colvars."+this->name+"."+replica_id+".state"); | cvm::output_prefix()+".colvars."+this->name+"."+replica_id+".state"); |
delete[] pwd; | delete[] pwd; |
| |
// now register this replica | // now register this replica |
| |
} | } |
| |
if (b_hills_traj) { | if (b_hills_traj) { |
std::string const traj_file_name(cvm::output_prefix+ | std::string const traj_file_name(cvm::output_prefix()+ |
".colvars."+this->name+ | ".colvars."+this->name+ |
( (comm != single_replica) ? | ( (comm != single_replica) ? |
("."+replica_id) : | ("."+replica_id) : |
("") )+ | ("") )+ |
".hills.traj"); | ".hills.traj"); |
if (!hills_traj_os.is_open()) { | if (!hills_traj_os.is_open()) { |
| cvm::backup_file(traj_file_name.c_str()); |
hills_traj_os.open(traj_file_name.c_str()); | hills_traj_os.open(traj_file_name.c_str()); |
} | } |
if (!hills_traj_os.is_open()) | if (!hills_traj_os.is_open()) |
| |
} | } |
| |
| |
std::ostream & colvarbias_meta::write_restart(std::ostream& os) | std::string const colvarbias_meta::get_state_params() const |
{ | { |
os << "metadynamics {\n" | std::ostringstream os; |
<< " configuration {\n" | |
<< " step " << cvm::step_absolute() << "\n" | |
<< " name " << this->name << "\n"; | |
if (this->comm != single_replica) | if (this->comm != single_replica) |
os << " replicaID " << this->replica_id << "\n"; | os << " replicaID " << this->replica_id << "\n"; |
os << " }\n\n"; | return (colvarbias::get_state_params() + os.str()); |
| } |
| |
| |
| std::ostream & colvarbias_meta::write_state_data(std::ostream& os) |
| { |
if (use_grids) { | if (use_grids) { |
| |
// this is a very good time to project hills, if you haven't done | // this is a very good time to project hills, if you haven't done |
| |
} | } |
} | } |
| |
os << "}\n\n"; | return os; |
| } |
| |
| |
| int colvarbias_meta::write_state_to_replicas() |
| { |
if (comm != single_replica) { | if (comm != single_replica) { |
write_replica_state_file(); | write_replica_state_file(); |
// schedule to reread the state files of the other replicas (they | // schedule to reread the state files of the other replicas (they |
| |
(replicas[ir])->replica_state_file_in_sync = false; | (replicas[ir])->replica_state_file_in_sync = false; |
} | } |
} | } |
| return COLVARS_OK; |
| } |
| |
| |
| int colvarbias_meta::write_output_files() |
| { |
if (dump_fes) { | if (dump_fes) { |
write_pmf(); | write_pmf(); |
} | } |
| return COLVARS_OK; |
return os; | |
} | } |
| |
| |
| |
colvar_grid_scalar *pmf = new colvar_grid_scalar(*hills_energy); | colvar_grid_scalar *pmf = new colvar_grid_scalar(*hills_energy); |
pmf->setup(); | pmf->setup(); |
| |
std::string fes_file_name_prefix(cvm::output_prefix); | |
| |
if ((cvm::n_meta_biases > 1) || (cvm::n_abf_biases > 0)) { | |
// if this is not the only free energy integrator, append | |
// this bias's name, to distinguish it from the output of the other | |
// biases producing a .pmf file | |
// TODO: fix for ABF with updateBias == no | |
fes_file_name_prefix += ("."+this->name); | |
} | |
| |
if ((comm == single_replica) || (dump_replica_fes)) { | if ((comm == single_replica) || (dump_replica_fes)) { |
// output the PMF from this instance or replica | // output the PMF from this instance or replica |
pmf->reset(); | pmf->reset(); |
| |
pmf->multiply_constant(well_temper_scale); | pmf->multiply_constant(well_temper_scale); |
} | } |
{ | { |
std::string const fes_file_name(fes_file_name_prefix + | std::string const fes_file_name(this->output_prefix + |
((comm != single_replica) ? ".partial" : "") + | ((comm != single_replica) ? ".partial" : "") + |
(dump_fes_save ? | (dump_fes_save ? |
"."+cvm::to_str(cvm::step_absolute()) : "") + | "."+cvm::to_str(cvm::step_absolute()) : "") + |
| |
cvm::real const well_temper_scale = (bias_temperature + cvm::temperature()) / bias_temperature; | cvm::real const well_temper_scale = (bias_temperature + cvm::temperature()) / bias_temperature; |
pmf->multiply_constant(well_temper_scale); | pmf->multiply_constant(well_temper_scale); |
} | } |
std::string const fes_file_name(fes_file_name_prefix + | std::string const fes_file_name(this->output_prefix + |
(dump_fes_save ? | (dump_fes_save ? |
"."+cvm::to_str(cvm::step_absolute()) : "") + | "."+cvm::to_str(cvm::step_absolute()) : "") + |
".pmf"); | ".pmf"); |
| |
| |
| |
| |
void colvarbias_meta::write_replica_state_file() | int colvarbias_meta::write_replica_state_file() |
{ | { |
// write down also the restart for the other replicas: TODO: this | if (cvm::debug()) { |
// is duplicated code, that could be cleaned up later | cvm::log("Writing replica state file for bias \""+name+"\"\n"); |
cvm::backup_file(replica_state_file.c_str()); | |
cvm::ofstream rep_state_os(replica_state_file.c_str()); | |
if (!rep_state_os.is_open()) | |
cvm::fatal_error("Error: in opening file \""+ | |
replica_state_file+"\" for writing.\n"); | |
| |
rep_state_os.setf(std::ios::scientific, std::ios::floatfield); | |
rep_state_os << "\n" | |
<< "metadynamics {\n" | |
<< " configuration {\n" | |
<< " name " << this->name << "\n" | |
<< " step " << cvm::step_absolute() << "\n"; | |
if (this->comm != single_replica) { | |
rep_state_os << " replicaID " << this->replica_id << "\n"; | |
} | |
rep_state_os << " }\n\n"; | |
rep_state_os << " hills_energy\n"; | |
rep_state_os << std::setprecision(cvm::cv_prec) | |
<< std::setw(cvm::cv_width); | |
hills_energy->write_restart(rep_state_os); | |
rep_state_os << " hills_energy_gradients\n"; | |
rep_state_os << std::setprecision(cvm::cv_prec) | |
<< std::setw(cvm::cv_width); | |
hills_energy_gradients->write_restart(rep_state_os); | |
| |
if ( (!use_grids) || keep_hills ) { | |
// write all hills currently in memory | |
for (std::list<hill>::const_iterator h = this->hills.begin(); | |
h != this->hills.end(); | |
h++) { | |
rep_state_os << *h; | |
} | |
} else { | |
// write just those that are near the grid boundaries | |
for (std::list<hill>::const_iterator h = this->hills_off_grid.begin(); | |
h != this->hills_off_grid.end(); | |
h++) { | |
rep_state_os << *h; | |
} | } |
| // write down also the restart for the other replicas |
| cvm::backup_file(replica_state_file.c_str()); |
| std::ostream *rep_state_os = cvm::proxy->output_stream(replica_state_file); |
| if (rep_state_os == NULL) { |
| cvm::error("Error: in opening file \""+ |
| replica_state_file+"\" for writing.\n", FILE_ERROR); |
| return FILE_ERROR; |
} | } |
| |
rep_state_os << "}\n\n"; | rep_state_os->setf(std::ios::scientific, std::ios::floatfield); |
rep_state_os.close(); | |
| if (!write_state(*rep_state_os)) { |
| cvm::error("Error: in writing to file \""+ |
| replica_state_file+"\".\n", FILE_ERROR); |
| cvm::proxy->close_output_stream(replica_state_file); |
| return FILE_ERROR; |
| } |
| |
| cvm::proxy->close_output_stream(replica_state_file); |
| |
| // rep_state_os.setf(std::ios::scientific, std::ios::floatfield); |
| // rep_state_os << "\n" |
| // << "metadynamics {\n" |
| // << " configuration {\n" |
| // << " name " << this->name << "\n" |
| // << " step " << cvm::step_absolute() << "\n"; |
| // if (this->comm != single_replica) { |
| // rep_state_os << " replicaID " << this->replica_id << "\n"; |
| // } |
| // rep_state_os << " }\n\n"; |
| // rep_state_os << " hills_energy\n"; |
| // rep_state_os << std::setprecision(cvm::cv_prec) |
| // << std::setw(cvm::cv_width); |
| // hills_energy->write_restart(rep_state_os); |
| // rep_state_os << " hills_energy_gradients\n"; |
| // rep_state_os << std::setprecision(cvm::cv_prec) |
| // << std::setw(cvm::cv_width); |
| // hills_energy_gradients->write_restart(rep_state_os); |
| |
| // if ( (!use_grids) || keep_hills ) { |
| // // write all hills currently in memory |
| // for (std::list<hill>::const_iterator h = this->hills.begin(); |
| // h != this->hills.end(); |
| // h++) { |
| // rep_state_os << *h; |
| // } |
| // } else { |
| // // write just those that are near the grid boundaries |
| // for (std::list<hill>::const_iterator h = this->hills_off_grid.begin(); |
| // h != this->hills_off_grid.end(); |
| // h++) { |
| // rep_state_os << *h; |
| // } |
| // } |
| // rep_state_os << "}\n\n"; |
| // rep_state_os.close(); |
| |
// reopen the hills file | // reopen the hills file |
replica_hills_os.close(); | replica_hills_os.close(); |
| |
cvm::fatal_error("Error: in opening file \""+ | cvm::fatal_error("Error: in opening file \""+ |
replica_hills_file+"\" for writing.\n"); | replica_hills_file+"\" for writing.\n"); |
replica_hills_os.setf(std::ios::scientific, std::ios::floatfield); | replica_hills_os.setf(std::ios::scientific, std::ios::floatfield); |
| |
| return COLVARS_OK; |
} | } |
| |
| |
std::string colvarbias_meta::hill::output_traj() | std::string colvarbias_meta::hill::output_traj() |
{ | { |
std::ostringstream os; | std::ostringstream os; |