Update Colvars to version 2020-07-07
This update contains several fixes and small new features or usability improvements. Descriptions and authorship information can be accessed from the pull requests listed below. Skip the zero-step also when multiple run commands are executed in sequence (@giacomofiorin) https://github.com/Colvars/colvars/pull/357 Do not accumulate data at step 0 (@giacomofiorin) https://github.com/Colvars/colvars/pull/345 Support for symmetry permutations of atoms in RMSD (@jhenin) https://github.com/Colvars/colvars/pull/344 Detect new grid parameters (@jhenin) https://github.com/Colvars/colvars/pull/341 Only access the output streams in non-threaded regions (@giacomofiorin) https://github.com/Colvars/colvars/pull/338 Fix incomplete setting of default colvarsRestartFrequency (@giacomofiorin) https://github.com/Colvars/colvars/pull/334 Fix typo (@e-kwsm) https://github.com/Colvars/colvars/pull/333 Convert the input keyword to lowercase in read_state_data_key (@HanatoK) https://github.com/Colvars/colvars/pull/332 Implement reflecting b.c. for ext Lagrangian (@jhenin) https://github.com/Colvars/colvars/pull/329
This commit is contained in:
@ -20,11 +20,6 @@
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
#if defined(NAMD_TCL) || defined(VMDTCL)
|
||||
#define COLVARS_TCL
|
||||
#include <tcl.h>
|
||||
#endif
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarproxy.h"
|
||||
#include "colvarscript.h"
|
||||
@ -33,8 +28,9 @@
|
||||
|
||||
|
||||
colvarproxy_system::colvarproxy_system()
|
||||
: angstrom_value(0.)
|
||||
{
|
||||
angstrom_value = 0.0;
|
||||
total_force_requested = false;
|
||||
reset_pbc_lattice();
|
||||
}
|
||||
|
||||
@ -67,7 +63,7 @@ bool colvarproxy_system::total_forces_same_step() const
|
||||
|
||||
inline int round_to_integer(cvm::real x)
|
||||
{
|
||||
return cvm::floor(x+0.5);
|
||||
return int(cvm::floor(x+0.5));
|
||||
}
|
||||
|
||||
|
||||
@ -135,6 +131,14 @@ cvm::rvector colvarproxy_system::position_distance(cvm::atom_pos const &pos1,
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_system::get_molid(int &)
|
||||
{
|
||||
cvm::error("Error: only VMD allows the use of multiple \"molecules\", "
|
||||
"i.e. multiple molecular systems.", COLVARS_NOT_IMPLEMENTED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
colvarproxy_atoms::colvarproxy_atoms()
|
||||
{
|
||||
@ -505,144 +509,12 @@ int colvarproxy_script::run_colvar_gradient_callback(std::string const & /* name
|
||||
|
||||
|
||||
|
||||
colvarproxy_tcl::colvarproxy_tcl()
|
||||
colvarproxy_io::colvarproxy_io()
|
||||
{
|
||||
tcl_interp_ = NULL;
|
||||
input_buffer_ = NULL;
|
||||
}
|
||||
|
||||
|
||||
colvarproxy_tcl::~colvarproxy_tcl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void colvarproxy_tcl::init_tcl_pointers()
|
||||
{
|
||||
cvm::error("Error: Tcl support is currently unavailable "
|
||||
"outside NAMD or VMD.\n", COLVARS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
char const *colvarproxy_tcl::tcl_obj_to_str(unsigned char *obj)
|
||||
{
|
||||
#if defined(COLVARS_TCL)
|
||||
return Tcl_GetString(reinterpret_cast<Tcl_Obj *>(obj));
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_tcl::tcl_run_force_callback()
|
||||
{
|
||||
#if defined(COLVARS_TCL)
|
||||
Tcl_Interp *const tcl_interp = reinterpret_cast<Tcl_Interp *>(tcl_interp_);
|
||||
std::string cmd = std::string("calc_colvar_forces ")
|
||||
+ cvm::to_str(cvm::step_absolute());
|
||||
int err = Tcl_Eval(tcl_interp, cmd.c_str());
|
||||
if (err != TCL_OK) {
|
||||
cvm::log(std::string("Error while executing calc_colvar_forces:\n"));
|
||||
cvm::error(Tcl_GetStringResult(tcl_interp));
|
||||
return COLVARS_ERROR;
|
||||
}
|
||||
return cvm::get_error();
|
||||
#else
|
||||
return COLVARS_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_tcl::tcl_run_colvar_callback(
|
||||
std::string const & name,
|
||||
std::vector<const colvarvalue *> const & cvc_values,
|
||||
colvarvalue & value)
|
||||
{
|
||||
#if defined(COLVARS_TCL)
|
||||
|
||||
Tcl_Interp *const tcl_interp = reinterpret_cast<Tcl_Interp *>(tcl_interp_);
|
||||
size_t i;
|
||||
std::string cmd = std::string("calc_") + name;
|
||||
for (i = 0; i < cvc_values.size(); i++) {
|
||||
cmd += std::string(" {") + (*(cvc_values[i])).to_simple_string() +
|
||||
std::string("}");
|
||||
}
|
||||
int err = Tcl_Eval(tcl_interp, cmd.c_str());
|
||||
const char *result = Tcl_GetStringResult(tcl_interp);
|
||||
if (err != TCL_OK) {
|
||||
return cvm::error(std::string("Error while executing ")
|
||||
+ cmd + std::string(":\n") +
|
||||
std::string(Tcl_GetStringResult(tcl_interp)), COLVARS_ERROR);
|
||||
}
|
||||
std::istringstream is(result);
|
||||
if (value.from_simple_string(is.str()) != COLVARS_OK) {
|
||||
cvm::log("Error parsing colvar value from script:");
|
||||
cvm::error(result);
|
||||
return COLVARS_ERROR;
|
||||
}
|
||||
return cvm::get_error();
|
||||
|
||||
#else
|
||||
|
||||
return COLVARS_NOT_IMPLEMENTED;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_tcl::tcl_run_colvar_gradient_callback(
|
||||
std::string const & name,
|
||||
std::vector<const colvarvalue *> const & cvc_values,
|
||||
std::vector<cvm::matrix2d<cvm::real> > & gradient)
|
||||
{
|
||||
#if defined(COLVARS_TCL)
|
||||
|
||||
Tcl_Interp *const tcl_interp = reinterpret_cast<Tcl_Interp *>(tcl_interp_);
|
||||
size_t i;
|
||||
std::string cmd = std::string("calc_") + name + "_gradient";
|
||||
for (i = 0; i < cvc_values.size(); i++) {
|
||||
cmd += std::string(" {") + (*(cvc_values[i])).to_simple_string() +
|
||||
std::string("}");
|
||||
}
|
||||
int err = Tcl_Eval(tcl_interp, cmd.c_str());
|
||||
if (err != TCL_OK) {
|
||||
return cvm::error(std::string("Error while executing ")
|
||||
+ cmd + std::string(":\n") +
|
||||
std::string(Tcl_GetStringResult(tcl_interp)), COLVARS_ERROR);
|
||||
}
|
||||
Tcl_Obj **list;
|
||||
int n;
|
||||
Tcl_ListObjGetElements(tcl_interp, Tcl_GetObjResult(tcl_interp),
|
||||
&n, &list);
|
||||
if (n != int(gradient.size())) {
|
||||
cvm::error("Error parsing list of gradient values from script: found "
|
||||
+ cvm::to_str(n) + " values instead of " +
|
||||
cvm::to_str(gradient.size()));
|
||||
return COLVARS_ERROR;
|
||||
}
|
||||
for (i = 0; i < gradient.size(); i++) {
|
||||
std::istringstream is(Tcl_GetString(list[i]));
|
||||
if (gradient[i].from_simple_string(is.str()) != COLVARS_OK) {
|
||||
cvm::log("Gradient matrix size: " + cvm::to_str(gradient[i].size()));
|
||||
cvm::log("Gradient string: " + cvm::to_str(Tcl_GetString(list[i])));
|
||||
cvm::error("Error parsing gradient value from script", COLVARS_ERROR);
|
||||
return COLVARS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return cvm::get_error();
|
||||
|
||||
#else
|
||||
|
||||
return COLVARS_NOT_IMPLEMENTED;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
colvarproxy_io::colvarproxy_io() {}
|
||||
|
||||
|
||||
colvarproxy_io::~colvarproxy_io() {}
|
||||
|
||||
|
||||
@ -658,78 +530,6 @@ int colvarproxy_io::set_frame(long int)
|
||||
}
|
||||
|
||||
|
||||
std::ostream * colvarproxy_io::output_stream(std::string const &output_name,
|
||||
std::ios_base::openmode mode)
|
||||
{
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Using colvarproxy::output_stream()\n");
|
||||
}
|
||||
|
||||
std::ostream *os = get_output_stream(output_name);
|
||||
if (os != NULL) return os;
|
||||
|
||||
if (!(mode & (std::ios_base::app | std::ios_base::ate))) {
|
||||
backup_file(output_name);
|
||||
}
|
||||
std::ofstream *osf = new std::ofstream(output_name.c_str(), mode);
|
||||
if (!osf->is_open()) {
|
||||
cvm::error("Error: cannot write to file/channel \""+output_name+"\".\n",
|
||||
FILE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
output_stream_names.push_back(output_name);
|
||||
output_files.push_back(osf);
|
||||
return osf;
|
||||
}
|
||||
|
||||
|
||||
std::ostream *colvarproxy_io::get_output_stream(std::string const &output_name)
|
||||
{
|
||||
std::list<std::ostream *>::iterator osi = output_files.begin();
|
||||
std::list<std::string>::iterator osni = output_stream_names.begin();
|
||||
for ( ; osi != output_files.end(); osi++, osni++) {
|
||||
if (*osni == output_name) {
|
||||
return *osi;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int colvarproxy_io::flush_output_stream(std::ostream *os)
|
||||
{
|
||||
std::list<std::ostream *>::iterator osi = output_files.begin();
|
||||
std::list<std::string>::iterator osni = output_stream_names.begin();
|
||||
for ( ; osi != output_files.end(); osi++, osni++) {
|
||||
if (*osi == os) {
|
||||
((std::ofstream *) (*osi))->flush();
|
||||
return COLVARS_OK;
|
||||
}
|
||||
}
|
||||
return cvm::error("Error: trying to flush an output file/channel "
|
||||
"that wasn't open.\n", BUG_ERROR);
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_io::close_output_stream(std::string const &output_name)
|
||||
{
|
||||
std::list<std::ostream *>::iterator osi = output_files.begin();
|
||||
std::list<std::string>::iterator osni = output_stream_names.begin();
|
||||
for ( ; osi != output_files.end(); osi++, osni++) {
|
||||
if (*osni == output_name) {
|
||||
((std::ofstream *) (*osi))->close();
|
||||
delete *osi;
|
||||
output_files.erase(osi);
|
||||
output_stream_names.erase(osni);
|
||||
return COLVARS_OK;
|
||||
}
|
||||
}
|
||||
return cvm::error("Error: trying to close an output file/channel "
|
||||
"that wasn't open.\n", BUG_ERROR);
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_io::backup_file(char const * /* filename */)
|
||||
{
|
||||
// TODO implement this using rename_file()
|
||||
@ -796,11 +596,33 @@ colvarproxy::colvarproxy()
|
||||
{
|
||||
colvars = NULL;
|
||||
b_simulation_running = true;
|
||||
b_simulation_continuing = false;
|
||||
b_delete_requested = false;
|
||||
}
|
||||
|
||||
|
||||
colvarproxy::~colvarproxy() {}
|
||||
colvarproxy::~colvarproxy()
|
||||
{
|
||||
close_files();
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy::close_files()
|
||||
{
|
||||
if (smp_enabled() == COLVARS_OK && smp_thread_id() > 0) {
|
||||
// Nothing to do on non-master threads
|
||||
return COLVARS_OK;
|
||||
}
|
||||
std::list<std::string>::iterator osni = output_stream_names.begin();
|
||||
std::list<std::ostream *>::iterator osi = output_files.begin();
|
||||
for ( ; osi != output_files.end(); osi++, osni++) {
|
||||
((std::ofstream *) (*osi))->close();
|
||||
delete *osi;
|
||||
}
|
||||
output_files.clear();
|
||||
output_stream_names.clear();
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy::reset()
|
||||
@ -838,9 +660,37 @@ int colvarproxy::update_output()
|
||||
}
|
||||
|
||||
|
||||
size_t colvarproxy::restart_frequency()
|
||||
int colvarproxy::post_run()
|
||||
{
|
||||
return 0;
|
||||
int error_code = COLVARS_OK;
|
||||
if (colvars->output_prefix().size()) {
|
||||
error_code |= colvars->write_restart_file(cvm::output_prefix()+".colvars.state");
|
||||
error_code |= colvars->write_output_files();
|
||||
}
|
||||
error_code |= flush_output_streams();
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
void colvarproxy::add_error_msg(std::string const &message)
|
||||
{
|
||||
std::istringstream is(message);
|
||||
std::string line;
|
||||
while (std::getline(is, line)) {
|
||||
error_output += line+"\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void colvarproxy::clear_error_msgs()
|
||||
{
|
||||
error_output.clear();
|
||||
}
|
||||
|
||||
|
||||
std::string const & colvarproxy::get_error_msgs()
|
||||
{
|
||||
return error_output;
|
||||
}
|
||||
|
||||
|
||||
@ -852,3 +702,105 @@ int colvarproxy::get_version_from_string(char const *version_string)
|
||||
is >> newint;
|
||||
return newint;
|
||||
}
|
||||
|
||||
|
||||
void colvarproxy::smp_stream_error()
|
||||
{
|
||||
cvm::error("Error: trying to access an output stream from a "
|
||||
"multi-threaded region (bug). For a quick workaround, use "
|
||||
"\"smp off\" in the Colvars config.\n", BUG_ERROR);
|
||||
}
|
||||
|
||||
|
||||
std::ostream * colvarproxy::output_stream(std::string const &output_name,
|
||||
std::ios_base::openmode mode)
|
||||
{
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Using colvarproxy::output_stream()\n");
|
||||
}
|
||||
|
||||
std::ostream *os = get_output_stream(output_name);
|
||||
if (os != NULL) return os;
|
||||
|
||||
if (!(mode & (std::ios_base::app | std::ios_base::ate))) {
|
||||
backup_file(output_name);
|
||||
}
|
||||
std::ofstream *osf = new std::ofstream(output_name.c_str(), mode);
|
||||
if (!osf->is_open()) {
|
||||
cvm::error("Error: cannot write to file/channel \""+output_name+"\".\n",
|
||||
FILE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
output_stream_names.push_back(output_name);
|
||||
output_files.push_back(osf);
|
||||
return osf;
|
||||
}
|
||||
|
||||
|
||||
std::ostream *colvarproxy::get_output_stream(std::string const &output_name)
|
||||
{
|
||||
if (smp_enabled() == COLVARS_OK) {
|
||||
if (smp_thread_id() > 0) smp_stream_error();
|
||||
}
|
||||
std::list<std::ostream *>::iterator osi = output_files.begin();
|
||||
std::list<std::string>::iterator osni = output_stream_names.begin();
|
||||
for ( ; osi != output_files.end(); osi++, osni++) {
|
||||
if (*osni == output_name) {
|
||||
return *osi;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int colvarproxy::flush_output_stream(std::ostream *os)
|
||||
{
|
||||
if (smp_enabled() == COLVARS_OK) {
|
||||
if (smp_thread_id() > 0) smp_stream_error();
|
||||
}
|
||||
std::list<std::ostream *>::iterator osi = output_files.begin();
|
||||
std::list<std::string>::iterator osni = output_stream_names.begin();
|
||||
for ( ; osi != output_files.end(); osi++, osni++) {
|
||||
if (*osi == os) {
|
||||
((std::ofstream *) (*osi))->flush();
|
||||
return COLVARS_OK;
|
||||
}
|
||||
}
|
||||
return cvm::error("Error: trying to flush an output file/channel "
|
||||
"that wasn't open.\n", BUG_ERROR);
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy::flush_output_streams()
|
||||
{
|
||||
if (smp_enabled() == COLVARS_OK && smp_thread_id() > 0)
|
||||
return COLVARS_OK;
|
||||
|
||||
std::list<std::ostream *>::iterator osi = output_files.begin();
|
||||
for ( ; osi != output_files.end(); osi++) {
|
||||
((std::ofstream *) (*osi))->flush();
|
||||
}
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy::close_output_stream(std::string const &output_name)
|
||||
{
|
||||
if (smp_enabled() == COLVARS_OK) {
|
||||
if (smp_thread_id() > 0) smp_stream_error();
|
||||
}
|
||||
std::list<std::ostream *>::iterator osi = output_files.begin();
|
||||
std::list<std::string>::iterator osni = output_stream_names.begin();
|
||||
for ( ; osi != output_files.end(); osi++, osni++) {
|
||||
if (*osni == output_name) {
|
||||
((std::ofstream *) (*osi))->close();
|
||||
delete *osi;
|
||||
output_files.erase(osi);
|
||||
output_stream_names.erase(osni);
|
||||
return COLVARS_OK;
|
||||
}
|
||||
}
|
||||
return cvm::error("Error: trying to close an output file/channel "
|
||||
"that wasn't open.\n", BUG_ERROR);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user