Skip to content

Commit 7eeb580

Browse files
committed
Add Colvars module version 2024-03-12
1 parent 2489a59 commit 7eeb580

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+9654
-2664
lines changed

CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,8 @@ include(gmxManageLmfit)
676676

677677
include(gmxManageMuparser)
678678

679+
include(gmxManageLepton)
680+
679681
include(gmxManageColvars)
680682

681683
##################################################

CMakeLists.txt.orig

+1,044
Large diffs are not rendered by default.

cmake/gmxManageLepton.cmake

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Add Lepton library, which is developed and distributed as part of OpenMM:
2+
# https://github.com/openmm/openmm
3+
4+
gmx_option_multichoice(GMX_USE_LEPTON
5+
"Build the Lepton library interfaced with GROMACS"
6+
INTERNAL
7+
INTERNAL NONE)
8+
mark_as_advanced(GMX_USE_LEPTON)
9+
10+
function(gmx_manage_lepton)
11+
if(GMX_USE_LEPTON STREQUAL "INTERNAL")
12+
13+
set(LEPTON_DIR "${CMAKE_SOURCE_DIR}/src/external/lepton")
14+
15+
file(GLOB LEPTON_SOURCES ${LEPTON_DIR}/src/*.cpp)
16+
add_library(lepton_objlib OBJECT ${LEPTON_SOURCES})
17+
target_include_directories(lepton_objlib PRIVATE ${LEPTON_DIR}/include)
18+
# TODO support building as shared library
19+
target_compile_options(lepton_objlib PRIVATE -DLEPTON_BUILDING_STATIC_LIBRARY)
20+
set_target_properties(lepton_objlib PROPERTIES POSITION_INDEPENDENT_CODE ON)
21+
22+
add_library(lepton INTERFACE)
23+
target_sources(lepton INTERFACE $<TARGET_OBJECTS:lepton_objlib>)
24+
target_include_directories(lepton SYSTEM INTERFACE $<BUILD_INTERFACE:${LEPTON_DIR}>)
25+
26+
# Set flags so that Colvars can leverage Lepton functionality
27+
# TODO handle the case when Lepton is built without Colvars?
28+
target_include_directories(colvars_objlib PRIVATE ${LEPTON_DIR}/include)
29+
target_compile_options(colvars_objlib PRIVATE -DLEPTON -DLEPTON_USE_STATIC_LIBRARIES)
30+
31+
else()
32+
33+
# Dummy target
34+
add_library(lepton INTERFACE)
35+
endif()
36+
endfunction()

src/external/colvars/colvar.cpp

+61-59
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,8 @@
2222
#include "colvars_memstream.h"
2323

2424

25-
26-
std::map<std::string, std::function<colvar::cvc *(const std::string &conf)>>
27-
colvar::global_cvc_map =
28-
std::map<std::string, std::function<colvar::cvc *(const std::string &conf)>>();
25+
std::map<std::string, std::function<colvar::cvc *()>> colvar::global_cvc_map =
26+
std::map<std::string, std::function<colvar::cvc *()>>();
2927

3028
std::map<std::string, std::string> colvar::global_cvc_desc_map =
3129
std::map<std::string, std::string>();
@@ -37,6 +35,7 @@ colvar::colvar()
3735
after_restart = false;
3836
kinetic_energy = 0.0;
3937
potential_energy = 0.0;
38+
period = 0.0;
4039

4140
#ifdef LEPTON
4241
dev_null = 0.0;
@@ -139,7 +138,14 @@ int colvar::init(std::string const &conf)
139138

140139
// Sort array of cvcs based on their names
141140
// Note: default CVC names are in input order for same type of CVC
142-
std::sort(cvcs.begin(), cvcs.end(), colvar::compare_cvc);
141+
std::sort(cvcs.begin(), cvcs.end(),
142+
[](std::shared_ptr<colvar::cvc> const &cvc1,
143+
std::shared_ptr<colvar::cvc> const &cvc2) -> bool {
144+
if (cvc1 && cvc2) {
145+
return cvc1->name < cvc2->name;
146+
}
147+
return false;
148+
});
143149

144150
if(cvcs.size() > 1) {
145151
cvm::log("Sorted list of components for this scripted colvar:\n");
@@ -194,9 +200,9 @@ int colvar::init(std::string const &conf)
194200

195201
if ((cvcs[i])->sup_np < 0) {
196202
cvm::log("Warning: you chose a negative exponent in the combination; "
197-
"if you apply forces, the simulation may become unstable "
198-
"when the component \""+
199-
(cvcs[i])->function_type+"\" approaches zero.\n");
203+
"if you apply forces, the simulation may become unstable "
204+
"when the component \""+
205+
(cvcs[i])->function_type()+"\" approaches zero.\n");
200206
}
201207
}
202208
}
@@ -303,7 +309,7 @@ int colvar::init(std::string const &conf)
303309
error_code |= init_grid_parameters(conf);
304310

305311
// Detect if we have a single component that is an alchemical lambda
306-
if (is_enabled(f_cv_single_cvc) && cvcs[0]->function_type == "alchLambda") {
312+
if (is_enabled(f_cv_single_cvc) && cvcs[0]->function_type() == "alchLambda") {
307313
enable(f_cv_external);
308314
}
309315

@@ -755,8 +761,8 @@ template <typename def_class_name>
755761
void colvar::add_component_type(char const *def_description, char const *def_config_key)
756762
{
757763
if (global_cvc_map.count(def_config_key) == 0) {
758-
global_cvc_map[def_config_key] = [](const std::string &cvc_conf) {
759-
return new def_class_name(cvc_conf);
764+
global_cvc_map[def_config_key] = []() {
765+
return new def_class_name();
760766
};
761767
global_cvc_desc_map[def_config_key] = std::string(def_description);
762768
}
@@ -767,48 +773,39 @@ int colvar::init_components_type(const std::string& conf, const char* def_config
767773
size_t def_count = 0;
768774
std::string def_conf = "";
769775
size_t pos = 0;
776+
int error_code = COLVARS_OK;
770777
while ( this->key_lookup(conf,
771778
def_config_key,
772779
&def_conf,
773780
&pos) ) {
774-
if (!def_conf.size()) continue;
781+
775782
cvm::log("Initializing "
776783
"a new \""+std::string(def_config_key)+"\" component"+
777784
(cvm::debug() ? ", with configuration:\n"+def_conf
778785
: ".\n"));
779-
cvc *cvcp = global_cvc_map[def_config_key](def_conf);
780-
cvm::increase_depth();
781-
if (cvcp) {
782-
int error_code = cvcp->init_code;
783-
cvcs.push_back(cvcp);
784-
error_code |= cvcp->set_function_type(def_config_key);
785-
if (error_code == COLVARS_OK) {
786-
error_code |= cvcp->check_keywords(def_conf, def_config_key);
787-
}
788-
if (error_code != COLVARS_OK) {
789-
cvm::decrease_depth();
790-
return cvm::error("Error: in setting up component \"" + std::string(def_config_key) +
791-
"\".\n",
792-
COLVARS_INPUT_ERROR);
793-
}
794-
} else {
795-
cvm::decrease_depth();
796-
return cvm::error("Error: in allocating component \"" + std::string(def_config_key) + "\".\n",
786+
cvc *cvcp = global_cvc_map[def_config_key]();
787+
if (!cvcp) {
788+
return cvm::error("Error: in creating object of type \"" + std::string(def_config_key) +
789+
"\".\n",
797790
COLVARS_MEMORY_ERROR);
798791
}
792+
cvcs.push_back(std::shared_ptr<colvar::cvc>(cvcp));
799793

800-
if ((cvcp->period != 0.0) || (cvcp->wrap_center != 0.0)) {
801-
if (!cvcp->is_enabled(f_cvc_periodic)) {
802-
cvm::decrease_depth();
803-
return cvm::error("Error: invalid use of period and/or "
804-
"wrapAround in a \"" +
805-
std::string(def_config_key) + "\" component.\n" +
806-
"Period: " + cvm::to_str(cvcp->period) +
807-
" wrapAround: " + cvm::to_str(cvcp->wrap_center),
808-
COLVARS_INPUT_ERROR);
809-
}
794+
cvm::increase_depth();
795+
int error_code_this = cvcp->init(def_conf);
796+
if (error_code_this == COLVARS_OK) {
797+
// Checking for invalid keywords only if the parsing was successful, otherwise any
798+
// early-returns due to errors would raise false positives
799+
error_code_this |= cvcp->check_keywords(def_conf, def_config_key);
800+
}
801+
cvm::decrease_depth();
802+
if (error_code_this != COLVARS_OK) {
803+
error_code |=
804+
cvm::error("Error: in setting up component \"" + std::string(def_config_key) + "\".\n",
805+
COLVARS_INPUT_ERROR);
810806
}
811807

808+
// Set default name if it doesn't have one
812809
if ( ! cvcs.back()->name.size()) {
813810
std::ostringstream s;
814811
s << def_config_key << std::setfill('0') << std::setw(4) << ++def_count;
@@ -822,15 +819,13 @@ int colvar::init_components_type(const std::string& conf, const char* def_config
822819
(cvm::debug() ? ", named \"" + cvcs.back()->name + "\"" : "") + ".\n");
823820
}
824821

825-
cvm::decrease_depth();
826-
827822
def_conf = "";
828823
if (cvm::debug()) {
829824
cvm::log("Parsed " + cvm::to_str(cvcs.size()) + " components at this time.\n");
830825
}
831826
}
832827

833-
return COLVARS_OK;
828+
return error_code;
834829
}
835830

836831

@@ -944,7 +939,7 @@ int colvar::init_components(std::string const &conf)
944939
if (error_code == COLVARS_OK) {
945940
// Store list of children cvcs for dependency checking purposes
946941
for (i = 0; i < cvcs.size(); i++) {
947-
add_child(cvcs[i]);
942+
add_child(cvcs[i].get());
948943
}
949944
// By default all CVCs are active at the start
950945
n_active_cvcs = cvcs.size();
@@ -1221,7 +1216,7 @@ int colvar::init_dependencies() {
12211216

12221217
// Initialize feature_states for each instance
12231218
feature_states.reserve(f_cv_ntot);
1224-
for (i = 0; i < f_cv_ntot; i++) {
1219+
for (i = feature_states.size(); i < f_cv_ntot; i++) {
12251220
feature_states.push_back(feature_state(true, false));
12261221
// Most features are available, so we set them so
12271222
// and list exceptions below
@@ -1284,14 +1279,10 @@ colvar::~colvar()
12841279
// for dependency purposes
12851280
remove_all_children();
12861281

1287-
for (std::vector<cvc *>::reverse_iterator ci = cvcs.rbegin();
1288-
ci != cvcs.rend();
1289-
++ci) {
1290-
// clear all children of this cvc (i.e. its atom groups)
1291-
// because the cvc base class destructor can't do it early enough
1292-
// and we don't want to have each cvc derived class do it separately
1282+
for (auto ci = cvcs.rbegin(); ci != cvcs.rend(); ++ci) {
1283+
// Clear all children of this cvc (i.e. its atom groups), because the cvc base class destructor
1284+
// can't do it early enough and we don't want to have each cvc derived class do it separately
12931285
(*ci)->remove_all_children();
1294-
delete *ci;
12951286
}
12961287
cvcs.clear();
12971288

@@ -1513,6 +1504,7 @@ int colvar::collect_cvc_values()
15131504
cvm::to_str(x, cvm::cv_width, cvm::cv_prec)+".\n");
15141505

15151506
if (after_restart) {
1507+
x_old = x_restart;
15161508
if (cvm::proxy->simulation_running()) {
15171509
cvm::real const jump2 = dist2(x, x_restart) / (width*width);
15181510
if (jump2 > 0.25) {
@@ -1707,12 +1699,13 @@ int colvar::calc_colvar_properties()
17071699
// Do the same if no simulation is running (eg. VMD postprocessing)
17081700
if ((cvm::step_relative() == 0 && !after_restart) || x_ext.type() == colvarvalue::type_notset || !cvm::proxy->simulation_running()) {
17091701
x_ext = x;
1702+
cvm::log("Initializing extended coordinate to colvar value.\n");
17101703
if (is_enabled(f_cv_reflecting_lower_boundary) && x_ext < lower_boundary) {
1711-
cvm::log("Warning: initializing extended coordinate to reflective lower boundary, as colvar value is below.");
1704+
cvm::log("Warning: initializing extended coordinate to reflective lower boundary, as colvar value is below.\n");
17121705
x_ext = lower_boundary;
17131706
}
17141707
if (is_enabled(f_cv_reflecting_upper_boundary) && x_ext > upper_boundary) {
1715-
cvm::log("Warning: initializing extended coordinate to reflective upper boundary, as colvar value is above.");
1708+
cvm::log("Warning: initializing extended coordinate to reflective upper boundary, as colvar value is above.\n");
17161709
x_ext = upper_boundary;
17171710
}
17181711

@@ -1722,8 +1715,18 @@ int colvar::calc_colvar_properties()
17221715
// Special case of a repeated timestep (eg. multiple NAMD "run" statements)
17231716
// revert values of the extended coordinate and velocity prior to latest integration
17241717
if (cvm::proxy->simulation_running() && cvm::step_relative() == prev_timestep) {
1725-
x_ext = prev_x_ext;
1726-
v_ext = prev_v_ext;
1718+
// Detect jumps due to discrete changes in coordinates (eg. in replica exchange schemes)
1719+
cvm::real const jump2 = dist2(x, x_old) / (width*width);
1720+
if (jump2 > 0.25) {
1721+
cvm::log("Detected discrete jump in colvar value from "
1722+
+ cvm::to_str(x_old) + " to " + cvm::to_str(x) + ".\n");
1723+
cvm::log("Reinitializing extended coordinate to colvar value.\n");
1724+
x_ext = x;
1725+
} else {
1726+
cvm::log("Reinitializing extended coordinate to last value.\n");
1727+
x_ext = prev_x_ext;
1728+
v_ext = prev_v_ext;
1729+
}
17271730
}
17281731
// report the restraint center as "value"
17291732
// These position and velocities come from integration at the _previous timestep_ in update_forces_energy()
@@ -1939,9 +1942,8 @@ int colvar::end_of_step()
19391942
if (cvm::debug())
19401943
cvm::log("End of step for colvar \""+this->name+"\".\n");
19411944

1942-
if (is_enabled(f_cv_fdiff_velocity)) {
1943-
x_old = x;
1944-
}
1945+
// Used for fdiff_velocity and for detecting jumps for extended Lagrangian colvars
1946+
x_old = x;
19451947

19461948
if (is_enabled(f_cv_subtract_applied_force)) {
19471949
f_old = f;

src/external/colvars/colvar.h

+5-7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <list>
1515
#include <iosfwd>
1616
#include <map>
17+
#include <memory>
1718

1819
#include "colvarmodule.h"
1920
#include "colvarvalue.h"
@@ -617,7 +618,6 @@ class colvar : public colvarparse, public colvardeps {
617618
class dihedPC;
618619
class alch_lambda;
619620
class alch_Flambda;
620-
class componentDisabled;
621621
class CartesianBasedPath;
622622
class aspath;
623623
class azpath;
@@ -645,8 +645,7 @@ class colvar : public colvarparse, public colvardeps {
645645
class map_total;
646646

647647
/// A global mapping of cvc names to the cvc constructors
648-
static const std::map<std::string, std::function<colvar::cvc *(const std::string &subcv_conf)>> &
649-
get_global_cvc_map()
648+
static const std::map<std::string, std::function<colvar::cvc *()>> &get_global_cvc_map()
650649
{
651650
return global_cvc_map;
652651
}
@@ -656,8 +655,8 @@ class colvar : public colvarparse, public colvardeps {
656655

657656
protected:
658657

659-
/// \brief Array of \link colvar::cvc \endlink objects
660-
std::vector<cvc *> cvcs;
658+
/// Array of components objects
659+
std::vector<std::shared_ptr<colvar::cvc>> cvcs;
661660

662661
/// \brief Flags to enable or disable cvcs at next colvar evaluation
663662
std::vector<bool> cvc_flags;
@@ -689,8 +688,7 @@ class colvar : public colvarparse, public colvardeps {
689688
#endif
690689

691690
/// A global mapping of cvc names to the cvc constructors
692-
static std::map<std::string, std::function<colvar::cvc *(const std::string &conf)>>
693-
global_cvc_map;
691+
static std::map<std::string, std::function<colvar::cvc *()>> global_cvc_map;
694692

695693
/// A global mapping of cvc names to the corresponding descriptions
696694
static std::map<std::string, std::string> global_cvc_desc_map;

src/external/colvars/colvaratoms.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ int cvm::atom_group::init_dependencies() {
286286
// Initialize feature_states for each instance
287287
// default as unavailable, not enabled
288288
feature_states.reserve(f_ag_ntot);
289-
for (i = 0; i < colvardeps::f_ag_ntot; i++) {
289+
for (i = feature_states.size(); i < colvardeps::f_ag_ntot; i++) {
290290
feature_states.push_back(feature_state(false, false));
291291
}
292292

@@ -532,8 +532,8 @@ int cvm::atom_group::parse(std::string const &group_conf)
532532
cvm::error("Error: atomsColValue, if provided, must be non-zero.\n", COLVARS_INPUT_ERROR);
533533
}
534534

535-
// NOTE: calls to add_atom() and/or add_atom_id() are in the proxy-implemented function
536-
error_code |= cvm::load_atoms(atoms_file_name.c_str(), *this, atoms_col, atoms_col_value);
535+
error_code |= cvm::main()->proxy->load_atoms_pdb(atoms_file_name.c_str(), *this, atoms_col,
536+
atoms_col_value);
537537
}
538538
}
539539

0 commit comments

Comments
 (0)