1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
|
// -*- 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.
#ifndef COLVARDEPS_H
#define COLVARDEPS_H
#include "colvarmodule.h"
#include "colvarparse.h"
/// \brief Parent class for a member object of a bias, cv or cvc etc. containing features and
/// their dependencies, and handling dependency resolution
///
/// There are 3 kinds of features:
/// 1. Dynamic features are under the control of the dependency resolution
/// system. They may be enabled or disabled depending on dependencies.
/// 2. User features may be enabled based on user input (they may trigger a failure upon dependency resolution, though)
/// 3. Static features are static properties of the object, determined
/// programatically at initialization time.
///
/// In all classes, feature 0 is active. When an object is inactivated
/// all its children dependencies are dereferenced (free_children_deps)
/// While the object is inactive, no dependency solving is done on children
/// it is done when the object is activated back (restore_children_deps)
class colvardeps {
public:
colvardeps();
virtual ~colvardeps();
// Subclasses should initialize the following members:
std::string description; // reference to object name (cv, cvc etc.)
/// This contains the current state of each feature for each object
// since the feature class only contains static properties
struct feature_state {
feature_state(bool a, bool e)
: available(a), enabled(e), ref_count(0) {}
/// Feature may be enabled, subject to possible dependencies
bool available;
/// Currently enabled - this flag is subject to change dynamically
/// TODO consider implications for dependency solving: anyone who disables
/// it should trigger a refresh of parent objects
bool enabled; // see if this should be private depending on implementation
// bool enabledOnce; // this should trigger an update when object is evaluated
/// Number of features requiring this one as a dependency
/// When it falls to zero:
/// - a dynamic feature is disabled automatically
/// - other features may be disabled statically
int ref_count;
/// List of features that were enabled by this one
/// as part of an alternate requirement (for ref counting purposes)
/// This is necessary because we don't know which feature in the list
/// we enabled, otherwise
std::vector<int> alternate_refs;
};
protected:
/// Time step multiplier (for coarse-timestep biases & colvars)
/// Biases and colvars will only be calculated at those times
/// (f_cvb_awake and f_cv_awake); a
/// Biases use this to apply "impulse" biasing forces at the outer timestep
/// Unused by lower-level objects (cvcs and atom groups)
int time_step_factor;
private:
/// List of the states of all features
std::vector<feature_state> feature_states;
/// Enum of possible feature types
enum feature_type {
f_type_not_set,
f_type_dynamic,
f_type_user,
f_type_static
};
public:
/// \brief returns time_step_factor
inline int get_time_step_factor() const {return time_step_factor;}
/// Pair a numerical feature ID with a description and type
void init_feature(int feature_id, const char *description, feature_type type = f_type_not_set);
/// Describes a feature and its dependencies
/// used in a static array within each subclass
class feature {
public:
feature() {}
~feature() {}
std::string description; // Set by derived object initializer
// features that this feature requires in the same object
// NOTE: we have no safety mechanism against circular dependencies, however, they would have to be internal to an object (ie. requires_self or requires_alt)
std::vector<int> requires_self;
// Features that are incompatible, ie. required disabled
// if enabled, they will cause a dependency failure (they will not be disabled)
// To enforce these dependencies regardless of the order in which they
// are enabled, they are always set in a symmetric way, so whichever is enabled
// second will cause the dependency to fail
std::vector<int> requires_exclude;
// sets of features that are required in an alternate way
// when parent feature is enabled, if none are enabled, the first one listed that is available will be enabled
std::vector<std::vector<int> > requires_alt;
// features that this feature requires in children
std::vector<int> requires_children;
inline bool is_dynamic() { return type == f_type_dynamic; }
inline bool is_static() { return type == f_type_static; }
inline bool is_user() { return type == f_type_user; }
/// Type of this feature, from the enum feature_type
feature_type type;
};
inline bool is_dynamic(int id) { return features()[id]->type == f_type_dynamic; }
inline bool is_static(int id) { return features()[id]->type == f_type_static; }
inline bool is_user(int id) { return features()[id]->type == f_type_user; }
// Accessor to array of all features with deps, static in most derived classes
// Subclasses with dynamic dependency trees may override this
// with a non-static array
// Intermediate classes (colvarbias and colvarcomp, which are also base classes)
// implement this as virtual to allow overriding
virtual const std::vector<feature *>&features() = 0;
virtual std::vector<feature *>&modify_features() = 0;
void add_child(colvardeps *child);
void remove_child(colvardeps *child);
/// Used before deleting an object, if not handled by that object's destructor
/// (useful for cvcs because their children are member objects)
void remove_all_children();
private:
/// pointers to objects this object depends on
/// list should be maintained by any code that modifies the object
/// this could be secured by making lists of colvars / cvcs / atom groups private and modified through accessor functions
std::vector<colvardeps *> children;
/// pointers to objects that depend on this object
/// the size of this array is in effect a reference counter
std::vector<colvardeps *> parents;
public:
// Checks whether given feature is enabled
// Defaults to querying f_*_active
inline bool is_enabled(int f = f_cv_active) const {
return feature_states[f].enabled;
}
// Checks whether given feature is available
// Defaults to querying f_*_active
inline bool is_available(int f = f_cv_active) const {
return feature_states[f].available;
}
/// Set the feature's available flag, without checking
/// To be used for dynamic properties
/// dependencies will be checked by enable()
void provide(int feature_id, bool truefalse = true);
/// Enable or disable, depending on flag value
void set_enabled(int feature_id, bool truefalse = true);
protected:
/// Parse a keyword and enable a feature accordingly
bool get_keyval_feature(colvarparse *cvp,
std::string const &conf, char const *key,
int feature_id, bool const &def_value,
colvarparse::Parse_Mode const parse_mode = colvarparse::parse_normal);
public:
/// enable a feature and recursively solve its dependencies
/// for proper reference counting, one should not add
/// spurious calls to enable()
/// dry_run is set to true to recursively test if a feature is available, without enabling it
int enable(int f, bool dry_run = false, bool toplevel = true);
/// Disable a feature, decrease the reference count of its dependencies
/// and recursively disable them as applicable
int disable(int f);
/// disable all enabled features to free their dependencies
/// to be done when deleting the object
/// Cannot be in the base class destructor because it needs the derived class features()
void free_children_deps();
/// re-enable children features (to be used when object becomes active)
void restore_children_deps();
/// Decrement the reference count of a feature
/// disabling it if it's dynamic and count reaches zero
int decr_ref_count(int f);
/// Implements possible actions to be carried out
/// when a given feature is enabled
/// Base function does nothing, can be overloaded
virtual void do_feature_side_effects(int id) {}
// NOTE that all feature enums should start with f_*_active
enum features_biases {
/// \brief Bias is active
f_cvb_active,
/// \brief Bias is awake (active on its own accord) this timestep
f_cvb_awake,
/// \brief will apply forces
f_cvb_apply_force,
/// \brief requires total forces
f_cvb_get_total_force,
/// \brief whether this bias should record the accumulated work
f_cvb_output_acc_work,
/// \brief depends on simulation history
f_cvb_history_dependent,
/// \brief depends on time
f_cvb_time_dependent,
/// \brief requires scalar colvars
f_cvb_scalar_variables,
/// \brief whether this bias will compute a PMF
f_cvb_calc_pmf,
/// \brief whether this bias will compute TI samples
f_cvb_calc_ti_samples,
/// \brief whether this bias will write TI samples
f_cvb_write_ti_samples,
/// \brief whether this bias should write the TI PMF
f_cvb_write_ti_pmf,
f_cvb_ntot
};
enum features_colvar {
/// \brief Calculate colvar
f_cv_active,
/// \brief Colvar is awake (active on its own accord) this timestep
f_cv_awake,
/// \brief Gradients are calculated and temporarily stored, so
/// that external forces can be applied
f_cv_gradient,
/// \brief Collect atomic gradient data from all cvcs into vector
/// atomic_gradient
f_cv_collect_gradient,
/// \brief Calculate the velocity with finite differences
f_cv_fdiff_velocity,
/// \brief The total force is calculated, projecting the atomic
/// forces on the inverse gradient
f_cv_total_force,
/// \brief Calculate total force from atomic forces
f_cv_total_force_calc,
/// \brief Subtract the applied force from the total force
f_cv_subtract_applied_force,
/// \brief Estimate Jacobian derivative
f_cv_Jacobian,
/// \brief Do not report the Jacobian force as part of the total force
/// instead, apply a correction internally to cancel it
f_cv_hide_Jacobian,
/// \brief The variable has a harmonic restraint around a moving
/// center with fictitious mass; bias forces will be applied to
/// the center
f_cv_extended_Lagrangian,
/// \brief The extended system coordinate undergoes Langevin dynamics
f_cv_Langevin,
/// \brief Output the potential and kinetic energies
/// (for extended Lagrangian colvars only)
f_cv_output_energy,
/// \brief Output the value to the trajectory file (on by default)
f_cv_output_value,
/// \brief Output the velocity to the trajectory file
f_cv_output_velocity,
/// \brief Output the applied force to the trajectory file
f_cv_output_applied_force,
/// \brief Output the total force to the trajectory file
f_cv_output_total_force,
/// \brief A lower boundary is defined
f_cv_lower_boundary,
/// \brief An upper boundary is defined
f_cv_upper_boundary,
/// \brief Provide a discretization of the values of the colvar to
/// be used by the biases or in analysis (needs lower and upper
/// boundary)
f_cv_grid,
/// \brief Compute running average
f_cv_runave,
/// \brief Compute time correlation function
f_cv_corrfunc,
/// \brief Value and gradient computed by user script
f_cv_scripted,
/// \brief Value and gradient computed by user function through Lepton
f_cv_custom_function,
/// \brief Colvar is periodic
f_cv_periodic,
/// \brief is scalar
f_cv_scalar,
f_cv_linear,
f_cv_homogeneous,
/// \brief multiple timestep through time_step_factor
f_cv_multiple_ts,
/// \brief Number of colvar features
f_cv_ntot
};
enum features_cvc {
f_cvc_active,
f_cvc_scalar,
f_cvc_gradient,
/// \brief CVC doesn't calculate and store explicit atom gradients
f_cvc_implicit_gradient,
f_cvc_inv_gradient,
/// \brief If enabled, calc_gradients() will call debug_gradients() for every group needed
f_cvc_debug_gradient,
f_cvc_Jacobian,
f_cvc_pbc_minimum_image,
f_cvc_one_site_total_force,
f_cvc_com_based,
f_cvc_scalable,
f_cvc_scalable_com,
f_cvc_ntot
};
enum features_atomgroup {
f_ag_active,
f_ag_center,
f_ag_rotate,
f_ag_fitting_group,
/// Perform a standard minimum msd fit for given atoms
/// ie. not using refpositionsgroup
// f_ag_min_msd_fit,
/// \brief Does not have explicit atom gradients from parent CVC
f_ag_implicit_gradient,
f_ag_fit_gradients,
f_ag_atom_forces,
f_ag_scalable,
f_ag_scalable_com,
f_ag_ntot
};
void init_cvb_requires();
void init_cv_requires();
void init_cvc_requires();
void init_ag_requires();
/// \brief print all enabled features and those of children, for debugging
void print_state();
};
#endif
|