22
22
#include " colvars_memstream.h"
23
23
24
24
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 *()>>();
29
27
30
28
std::map<std::string, std::string> colvar::global_cvc_desc_map =
31
29
std::map<std::string, std::string>();
@@ -37,6 +35,7 @@ colvar::colvar()
37
35
after_restart = false ;
38
36
kinetic_energy = 0.0 ;
39
37
potential_energy = 0.0 ;
38
+ period = 0.0 ;
40
39
41
40
#ifdef LEPTON
42
41
dev_null = 0.0 ;
@@ -139,7 +138,14 @@ int colvar::init(std::string const &conf)
139
138
140
139
// Sort array of cvcs based on their names
141
140
// 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
+ });
143
149
144
150
if (cvcs.size () > 1 ) {
145
151
cvm::log (" Sorted list of components for this scripted colvar:\n " );
@@ -194,9 +200,9 @@ int colvar::init(std::string const &conf)
194
200
195
201
if ((cvcs[i])->sup_np < 0 ) {
196
202
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 " );
200
206
}
201
207
}
202
208
}
@@ -303,7 +309,7 @@ int colvar::init(std::string const &conf)
303
309
error_code |= init_grid_parameters (conf);
304
310
305
311
// 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" ) {
307
313
enable (f_cv_external);
308
314
}
309
315
@@ -755,8 +761,8 @@ template <typename def_class_name>
755
761
void colvar::add_component_type (char const *def_description, char const *def_config_key)
756
762
{
757
763
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 ();
760
766
};
761
767
global_cvc_desc_map[def_config_key] = std::string (def_description);
762
768
}
@@ -767,48 +773,39 @@ int colvar::init_components_type(const std::string& conf, const char* def_config
767
773
size_t def_count = 0 ;
768
774
std::string def_conf = " " ;
769
775
size_t pos = 0 ;
776
+ int error_code = COLVARS_OK;
770
777
while ( this ->key_lookup (conf,
771
778
def_config_key,
772
779
&def_conf,
773
780
&pos) ) {
774
- if (!def_conf. size ()) continue ;
781
+
775
782
cvm::log (" Initializing "
776
783
" a new \" " +std::string (def_config_key)+" \" component" +
777
784
(cvm::debug () ? " , with configuration:\n " +def_conf
778
785
: " .\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 " ,
797
790
COLVARS_MEMORY_ERROR);
798
791
}
792
+ cvcs.push_back (std::shared_ptr<colvar::cvc>(cvcp));
799
793
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);
810
806
}
811
807
808
+ // Set default name if it doesn't have one
812
809
if ( ! cvcs.back ()->name .size ()) {
813
810
std::ostringstream s;
814
811
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
822
819
(cvm::debug () ? " , named \" " + cvcs.back ()->name + " \" " : " " ) + " .\n " );
823
820
}
824
821
825
- cvm::decrease_depth ();
826
-
827
822
def_conf = " " ;
828
823
if (cvm::debug ()) {
829
824
cvm::log (" Parsed " + cvm::to_str (cvcs.size ()) + " components at this time.\n " );
830
825
}
831
826
}
832
827
833
- return COLVARS_OK ;
828
+ return error_code ;
834
829
}
835
830
836
831
@@ -944,7 +939,7 @@ int colvar::init_components(std::string const &conf)
944
939
if (error_code == COLVARS_OK) {
945
940
// Store list of children cvcs for dependency checking purposes
946
941
for (i = 0 ; i < cvcs.size (); i++) {
947
- add_child (cvcs[i]);
942
+ add_child (cvcs[i]. get () );
948
943
}
949
944
// By default all CVCs are active at the start
950
945
n_active_cvcs = cvcs.size ();
@@ -1221,7 +1216,7 @@ int colvar::init_dependencies() {
1221
1216
1222
1217
// Initialize feature_states for each instance
1223
1218
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++) {
1225
1220
feature_states.push_back (feature_state (true , false ));
1226
1221
// Most features are available, so we set them so
1227
1222
// and list exceptions below
@@ -1284,14 +1279,10 @@ colvar::~colvar()
1284
1279
// for dependency purposes
1285
1280
remove_all_children ();
1286
1281
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
1293
1285
(*ci)->remove_all_children ();
1294
- delete *ci;
1295
1286
}
1296
1287
cvcs.clear ();
1297
1288
@@ -1513,6 +1504,7 @@ int colvar::collect_cvc_values()
1513
1504
cvm::to_str (x, cvm::cv_width, cvm::cv_prec)+" .\n " );
1514
1505
1515
1506
if (after_restart) {
1507
+ x_old = x_restart;
1516
1508
if (cvm::proxy->simulation_running ()) {
1517
1509
cvm::real const jump2 = dist2 (x, x_restart) / (width*width);
1518
1510
if (jump2 > 0.25 ) {
@@ -1707,12 +1699,13 @@ int colvar::calc_colvar_properties()
1707
1699
// Do the same if no simulation is running (eg. VMD postprocessing)
1708
1700
if ((cvm::step_relative () == 0 && !after_restart) || x_ext.type () == colvarvalue::type_notset || !cvm::proxy->simulation_running ()) {
1709
1701
x_ext = x;
1702
+ cvm::log (" Initializing extended coordinate to colvar value.\n " );
1710
1703
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 " );
1712
1705
x_ext = lower_boundary;
1713
1706
}
1714
1707
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 " );
1716
1709
x_ext = upper_boundary;
1717
1710
}
1718
1711
@@ -1722,8 +1715,18 @@ int colvar::calc_colvar_properties()
1722
1715
// Special case of a repeated timestep (eg. multiple NAMD "run" statements)
1723
1716
// revert values of the extended coordinate and velocity prior to latest integration
1724
1717
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
+ }
1727
1730
}
1728
1731
// report the restraint center as "value"
1729
1732
// These position and velocities come from integration at the _previous timestep_ in update_forces_energy()
@@ -1939,9 +1942,8 @@ int colvar::end_of_step()
1939
1942
if (cvm::debug ())
1940
1943
cvm::log (" End of step for colvar \" " +this ->name +" \" .\n " );
1941
1944
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;
1945
1947
1946
1948
if (is_enabled (f_cv_subtract_applied_force)) {
1947
1949
f_old = f;
0 commit comments