File: colvardeps.h

package info (click to toggle)
lammps 20220106.git7586adbb6a%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 348,064 kB
  • sloc: cpp: 831,421; python: 24,896; xml: 14,949; f90: 10,845; ansic: 7,967; sh: 4,226; perl: 4,064; fortran: 2,424; makefile: 1,501; objc: 238; lisp: 163; csh: 16; awk: 14; tcl: 6
file content (434 lines) | stat: -rw-r--r-- 16,788 bytes parent folder | download
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
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
// -*- 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
///   programmatically at initialization time.
///
/// The following diagram summarizes the dependency tree at the bias, colvar, and colvarcomp levels.
/// Isolated and atom group features are not shown to save space.
/// @image html deps_2019.svg
///
/// 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;

  /// 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);

  /// Describes a feature and its dependencies
  /// used in a static array within each subclass
  class feature {

  public:
    feature() : type(f_type_not_set) {}
    ~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_not_set(int id) { return features()[id]->type == f_type_not_set; }
  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() const = 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 accurate reference counting, do not add spurious calls to enable()
  /// \param dry_run Recursively test if a feature is available, without enabling it
  /// \param toplevel False if this is called as part of a chain of dependency resolution.
  /// This is used to diagnose failed dependencies by displaying the full stack:
  /// only the toplevel dependency will throw a fatal error.
  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,
    /// Accumulates data starting from step 0 of a simulation run
    f_cvb_step_zero_data,
    /// \brief will apply forces
    f_cvb_apply_force,
    /// \brief force this bias to act on actual value for extended-Lagrangian coordinates
    f_cvb_bypass_ext_lagrangian,
    /// \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 An extended variable that sets an external variable in the
    /// back-end (eg. an alchemical coupling parameter for lambda-dynamics)
    /// Can have a single component
    f_cv_external,
    /// \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 The lower boundary is not defined from user's choice
    f_cv_hard_lower_boundary,
    /// \brief The upper boundary is not defined from user's choice
    f_cv_hard_upper_boundary,
    /// \brief Reflecting lower boundary condition
    f_cv_reflecting_lower_boundary,
    /// \brief Reflecting upper boundary condition
    f_cv_reflecting_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 The colvar has only one component
    f_cv_single_cvc,
    /// \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 {
    /// Computation of this CVC is enabled
    f_cvc_active,
    /// This CVC computes a scalar value
    f_cvc_scalar,
    /// Values of this CVC lie in a periodic interval
    f_cvc_periodic,
    /// This CVC provides a default value for the colvar's width
    f_cvc_width,
    /// This CVC provides a default value for the colvar's lower boundary
    f_cvc_lower_boundary,
    /// This CVC provides a default value for the colvar's upper boundary
    f_cvc_upper_boundary,
    /// CVC calculates atom gradients
    f_cvc_gradient,
    /// CVC calculates and stores explicit atom gradients
    f_cvc_explicit_gradient,
    /// CVC calculates and stores inverse atom gradients (used for total force)
    f_cvc_inv_gradient,
    /// CVC calculates the Jacobian term of the total-force expression
    f_cvc_Jacobian,
    /// The total force for this CVC will be computed from one group only
    f_cvc_one_site_total_force,
    /// calc_gradients() will call debug_gradients() for every group needed
    f_cvc_debug_gradient,
    /// With PBCs, minimum-image convention will be used for distances
    /// (does not affect the periodicity of CVC values, e.g. angles)
    f_cvc_pbc_minimum_image,
    /// This CVC is a function of centers of mass
    f_cvc_com_based,
    /// This CVC can be computed in parallel
    f_cvc_scalable,
    /// Centers-of-mass used in this CVC can be computed in parallel
    f_cvc_scalable_com,
    /// Number of CVC features
    f_cvc_ntot
  };

  enum features_atomgroup {
    f_ag_active,
    f_ag_center,
    f_ag_center_origin,
    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_explicit_gradient,
    f_ag_fit_gradients,
    f_ag_atom_forces,
    f_ag_scalable,
    f_ag_scalable_com,
    f_ag_ntot
  };

  /// Initialize dependency tree for object of a derived class
  virtual int init_dependencies() = 0;

  /// Make feature f require feature g within the same object
  void require_feature_self(int f, int g);

  /// Make features f and g mutually exclusive within the same object
  void exclude_feature_self(int f, int g);

  /// Make feature f require feature g within children
  void require_feature_children(int f, int g);

  /// Make feature f require either g or h within the same object
  void require_feature_alt(int f, int g, int h);

  /// Make feature f require any of g, h, or i within the same object
  void require_feature_alt(int f, int g, int h, int i);

  /// Make feature f require any of g, h, i, or j within the same object
  void require_feature_alt(int f, int g, int h, int i, int j);

  /// \brief print all enabled features and those of children, for debugging
  void print_state();

  /// \brief Check that a feature is enabled, raising BUG_ERROR if not
  inline void check_enabled(int f, std::string const &reason) const
  {
    if (! is_enabled(f)) {
      cvm::error("Error: "+reason+" requires that the feature \""+
                 features()[f]->description+"\" is active.\n", BUG_ERROR);
    }
  }

};

#endif