Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F90843276
colvardeps.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Nov 5, 06:49
Size
17 KB
Mime Type
text/x-c
Expires
Thu, Nov 7, 06:49 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
22142721
Attached To
rLAMMPS lammps
colvardeps.cpp
View Options
#include "colvardeps.h"
colvardeps
::~
colvardeps
()
{
size_t
i
;
for
(
i
=
0
;
i
<
feature_states
.
size
();
i
++
)
{
if
(
feature_states
[
i
]
!=
NULL
)
delete
feature_states
[
i
];
}
// Do not delete features if it's static
// for (i=0; i<features.size(); i++) {
// if (features[i] != NULL) delete features[i];
// }
remove_all_children
();
// Protest if we are deleting an object while a parent object may still depend on it
// Another possible strategy is to have the child unlist itself from the parent's children
if
(
parents
.
size
())
{
cvm
::
log
(
"Warning: destroying "
+
description
+
" before its parents objects:"
);
for
(
i
=
0
;
i
<
parents
.
size
();
i
++
)
{
cvm
::
log
(
parents
[
i
]
->
description
);
}
}
}
void
colvardeps
::
provide
(
int
feature_id
)
{
feature_states
[
feature_id
]
->
available
=
true
;
}
bool
colvardeps
::
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
)
{
bool
value
;
bool
const
found
=
cvp
->
get_keyval
(
conf
,
key
,
value
,
def_value
,
parse_mode
);
if
(
value
)
enable
(
feature_id
);
return
found
;
}
int
colvardeps
::
enable
(
int
feature_id
,
bool
dry_run
/* default: false */
,
// dry_run: fail silently, do not enable if available
// flag is passed recursively to deps of this feature
bool
toplevel
/* default: true */
)
// 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
res
;
size_t
i
,
j
;
bool
ok
;
feature
*
f
=
features
()[
feature_id
];
feature_state
*
fs
=
feature_states
[
feature_id
];
if
(
cvm
::
debug
())
{
cvm
::
log
(
"DEPS: "
+
description
+
(
dry_run
?
" testing "
:
" requiring "
)
+
"
\"
"
+
f
->
description
+
"
\"
"
);
}
if
(
fs
->
enabled
)
{
// Do not try to solve deps if already enabled
return
COLVARS_OK
;
}
if
(
!
fs
->
available
)
{
if
(
!
dry_run
)
{
if
(
toplevel
)
{
cvm
::
error
(
"Error: Feature unavailable:
\"
"
+
f
->
description
+
"
\"
in "
+
description
+
"."
);
}
else
{
cvm
::
log
(
"Feature unavailable:
\"
"
+
f
->
description
+
"
\"
in "
+
description
);
}
}
return
COLVARS_ERROR
;
}
// 1) enforce exclusions
for
(
i
=
0
;
i
<
f
->
requires_exclude
.
size
();
i
++
)
{
feature
*
g
=
features
()[
f
->
requires_exclude
[
i
]];
if
(
cvm
::
debug
())
cvm
::
log
(
f
->
description
+
" requires exclude "
+
g
->
description
);
if
(
is_enabled
(
f
->
requires_exclude
[
i
]))
{
if
(
!
dry_run
)
{
cvm
::
log
(
"Features
\"
"
+
f
->
description
+
"
\"
is incompatible with
\"
"
+
g
->
description
+
"
\"
in "
+
description
);
if
(
toplevel
)
{
cvm
::
error
(
"Error: Failed dependency in "
+
description
+
"."
);
}
}
return
COLVARS_ERROR
;
}
}
// 2) solve internal deps (self)
for
(
i
=
0
;
i
<
f
->
requires_self
.
size
();
i
++
)
{
if
(
cvm
::
debug
())
cvm
::
log
(
f
->
description
+
" requires self "
+
features
()[
f
->
requires_self
[
i
]]
->
description
);
res
=
enable
(
f
->
requires_self
[
i
],
dry_run
,
false
);
if
(
res
!=
COLVARS_OK
)
{
if
(
!
dry_run
)
{
cvm
::
log
(
"...required by
\"
"
+
f
->
description
+
"
\"
in "
+
description
);
if
(
toplevel
)
{
cvm
::
error
(
"Error: Failed dependency in "
+
description
+
"."
);
}
}
return
res
;
}
}
// 3) solve internal alternate deps
for
(
i
=
0
;
i
<
f
->
requires_alt
.
size
();
i
++
)
{
// test if one is available; if yes, enable and exit w/ success
ok
=
false
;
for
(
j
=
0
;
j
<
f
->
requires_alt
[
i
].
size
();
j
++
)
{
int
g
=
f
->
requires_alt
[
i
][
j
];
if
(
cvm
::
debug
())
cvm
::
log
(
f
->
description
+
" requires alt "
+
features
()[
g
]
->
description
);
res
=
enable
(
g
,
true
,
false
);
// see if available
if
(
res
==
COLVARS_OK
)
{
ok
=
true
;
if
(
!
dry_run
)
enable
(
g
,
false
,
false
);
// Require again, for real
break
;
}
}
if
(
!
ok
)
{
if
(
!
dry_run
)
{
cvm
::
log
(
"No dependency satisfied among alternates:"
);
cvm
::
log
(
"-----------------------------------------"
);
for
(
j
=
0
;
j
<
f
->
requires_alt
[
i
].
size
();
j
++
)
{
int
g
=
f
->
requires_alt
[
i
][
j
];
cvm
::
log
(
cvm
::
to_str
(
j
+
1
)
+
". "
+
features
()[
g
]
->
description
);
cvm
::
increase_depth
();
enable
(
g
,
false
,
false
);
// Just for printing error output
cvm
::
decrease_depth
();
}
cvm
::
log
(
"-----------------------------------------"
);
cvm
::
log
(
"for
\"
"
+
f
->
description
+
"
\"
in "
+
description
);
if
(
toplevel
)
{
cvm
::
error
(
"Error: Failed dependency in "
+
description
+
"."
);
}
}
return
COLVARS_ERROR
;
}
}
// 4) solve deps in children
for
(
i
=
0
;
i
<
f
->
requires_children
.
size
();
i
++
)
{
int
g
=
f
->
requires_children
[
i
];
for
(
j
=
0
;
j
<
children
.
size
();
j
++
)
{
cvm
::
increase_depth
();
res
=
children
[
j
]
->
enable
(
g
,
dry_run
,
false
);
cvm
::
decrease_depth
();
if
(
res
!=
COLVARS_OK
)
{
if
(
!
dry_run
)
{
cvm
::
log
(
"...required by
\"
"
+
f
->
description
+
"
\"
in "
+
description
);
}
if
(
toplevel
)
{
cvm
::
error
(
"Error: Failed dependency in "
+
description
+
"."
);
}
return
res
;
}
}
// If we've just touched the features of child objects, refresh them
if
(
!
dry_run
&&
f
->
requires_children
.
size
()
!=
0
)
{
for
(
j
=
0
;
j
<
children
.
size
();
j
++
)
{
children
[
j
]
->
refresh_deps
();
}
}
}
// Actually enable feature only once everything checks out
if
(
!
dry_run
)
fs
->
enabled
=
true
;
return
COLVARS_OK
;
}
// disable() {
//
// // we need refs to parents to walk up the deps tree!
// // or refresh
// }
// Shorthand macros for describing dependencies
#define f_description(f, d) features()[f]->description = d
#define f_req_self(f, g) features()[f]->requires_self.push_back(g)
// This macro ensures that exclusions are symmetric
#define f_req_exclude(f, g) features()[f]->requires_exclude.push_back(g); \
features()[g]->requires_exclude.push_back(f)
#define f_req_children(f, g) features()[f]->requires_children.push_back(g)
#define f_req_alt2(f, g, h) features()[f]->requires_alt.push_back(std::vector<int>(2));\
features()[f]->requires_alt.back()[0] = g; \
features()[f]->requires_alt.back()[1] = h
#define f_req_alt3(f, g, h, i) features()[f]->requires_alt.push_back(std::vector<int>(3));\
features()[f]->requires_alt.back()[0] = g; \
features()[f]->requires_alt.back()[1] = h; \
features()[f]->requires_alt.back()[2] = i
void
colvardeps
::
init_cvb_requires
()
{
int
i
;
if
(
features
().
size
()
==
0
)
{
for
(
i
=
0
;
i
<
f_cvb_ntot
;
i
++
)
{
features
().
push_back
(
new
feature
);
}
}
f_description
(
f_cvb_active
,
"active"
);
f_req_children
(
f_cvb_active
,
f_cv_active
);
f_description
(
f_cvb_apply_force
,
"apply force"
);
f_req_children
(
f_cvb_apply_force
,
f_cv_gradient
);
f_description
(
f_cvb_get_total_force
,
"obtain total force"
);
f_req_children
(
f_cvb_get_total_force
,
f_cv_total_force
);
f_description
(
f_cvb_history_dependent
,
"history-dependent"
);
// Initialize feature_states for each instance
feature_states
.
reserve
(
f_cvb_ntot
);
for
(
i
=
0
;
i
<
f_cvb_ntot
;
i
++
)
{
feature_states
.
push_back
(
new
feature_state
(
true
,
false
));
// Most features are available, so we set them so
// and list exceptions below
}
// some biases are not history-dependent
feature_states
[
f_cvb_history_dependent
]
->
available
=
false
;
}
void
colvardeps
::
init_cv_requires
()
{
size_t
i
;
if
(
features
().
size
()
==
0
)
{
for
(
i
=
0
;
i
<
f_cv_ntot
;
i
++
)
{
features
().
push_back
(
new
feature
);
}
f_description
(
f_cv_active
,
"active"
);
f_req_children
(
f_cv_active
,
f_cvc_active
);
// Colvars must be either a linear combination, or scalar (and polynomial) or scripted
f_req_alt3
(
f_cv_active
,
f_cv_scalar
,
f_cv_linear
,
f_cv_scripted
);
f_description
(
f_cv_gradient
,
"gradient"
);
f_req_children
(
f_cv_gradient
,
f_cvc_gradient
);
f_description
(
f_cv_collect_gradient
,
"collect gradient"
);
f_req_self
(
f_cv_collect_gradient
,
f_cv_gradient
);
f_req_self
(
f_cv_collect_gradient
,
f_cv_scalar
);
f_description
(
f_cv_fdiff_velocity
,
"fdiff_velocity"
);
// System force: either trivial (spring force); through extended Lagrangian, or calculated explicitly
f_description
(
f_cv_total_force
,
"total force"
);
f_req_alt2
(
f_cv_total_force
,
f_cv_extended_Lagrangian
,
f_cv_total_force_calc
);
// Deps for explicit total force calculation
f_description
(
f_cv_total_force_calc
,
"total force calculation"
);
f_req_self
(
f_cv_total_force_calc
,
f_cv_scalar
);
f_req_self
(
f_cv_total_force_calc
,
f_cv_linear
);
f_req_children
(
f_cv_total_force_calc
,
f_cvc_inv_gradient
);
f_req_self
(
f_cv_total_force_calc
,
f_cv_Jacobian
);
f_description
(
f_cv_Jacobian
,
"Jacobian derivative"
);
f_req_self
(
f_cv_Jacobian
,
f_cv_scalar
);
f_req_self
(
f_cv_Jacobian
,
f_cv_linear
);
f_req_children
(
f_cv_Jacobian
,
f_cvc_Jacobian
);
f_description
(
f_cv_hide_Jacobian
,
"hide Jacobian force"
);
f_req_self
(
f_cv_hide_Jacobian
,
f_cv_Jacobian
);
// can only hide if calculated
f_description
(
f_cv_extended_Lagrangian
,
"extended Lagrangian"
);
f_description
(
f_cv_Langevin
,
"Langevin dynamics"
);
f_req_self
(
f_cv_Langevin
,
f_cv_extended_Lagrangian
);
f_description
(
f_cv_linear
,
"linear"
);
f_description
(
f_cv_scalar
,
"scalar"
);
f_description
(
f_cv_output_energy
,
"output energy"
);
f_description
(
f_cv_output_value
,
"output value"
);
f_description
(
f_cv_output_velocity
,
"output velocity"
);
f_req_self
(
f_cv_output_velocity
,
f_cv_fdiff_velocity
);
f_description
(
f_cv_output_applied_force
,
"output applied force"
);
f_description
(
f_cv_output_total_force
,
"output total force"
);
f_req_self
(
f_cv_output_total_force
,
f_cv_total_force
);
f_description
(
f_cv_lower_boundary
,
"lower boundary"
);
f_req_self
(
f_cv_lower_boundary
,
f_cv_scalar
);
f_description
(
f_cv_upper_boundary
,
"upper boundary"
);
f_req_self
(
f_cv_upper_boundary
,
f_cv_scalar
);
f_description
(
f_cv_grid
,
"grid"
);
f_req_self
(
f_cv_grid
,
f_cv_lower_boundary
);
f_req_self
(
f_cv_grid
,
f_cv_upper_boundary
);
f_description
(
f_cv_lower_wall
,
"lower wall"
);
f_req_self
(
f_cv_lower_wall
,
f_cv_lower_boundary
);
f_req_self
(
f_cv_lower_wall
,
f_cv_gradient
);
f_description
(
f_cv_upper_wall
,
"upper wall"
);
f_req_self
(
f_cv_upper_wall
,
f_cv_upper_boundary
);
f_req_self
(
f_cv_upper_wall
,
f_cv_gradient
);
f_description
(
f_cv_runave
,
"running average"
);
f_description
(
f_cv_corrfunc
,
"correlation function"
);
// The features below are set programmatically
f_description
(
f_cv_scripted
,
"scripted"
);
f_description
(
f_cv_periodic
,
"periodic"
);
f_description
(
f_cv_scalar
,
"scalar"
);
f_description
(
f_cv_linear
,
"linear"
);
f_description
(
f_cv_homogeneous
,
"homogeneous"
);
}
// Initialize feature_states for each instance
feature_states
.
reserve
(
f_cv_ntot
);
for
(
i
=
0
;
i
<
f_cv_ntot
;
i
++
)
{
feature_states
.
push_back
(
new
feature_state
(
true
,
false
));
// Most features are available, so we set them so
// and list exceptions below
}
// properties that may NOT be enabled as a dependency
int
unavailable_deps
[]
=
{
f_cv_lower_boundary
,
f_cv_upper_boundary
,
f_cv_extended_Lagrangian
,
f_cv_Langevin
,
f_cv_scripted
,
f_cv_periodic
,
f_cv_scalar
,
f_cv_linear
,
f_cv_homogeneous
};
for
(
i
=
0
;
i
<
sizeof
(
unavailable_deps
)
/
sizeof
(
unavailable_deps
[
0
]);
i
++
)
{
feature_states
[
unavailable_deps
[
i
]]
->
available
=
false
;
}
}
void
colvardeps
::
init_cvc_requires
()
{
size_t
i
;
// Initialize static array once and for all
if
(
features
().
size
()
==
0
)
{
for
(
i
=
0
;
i
<
colvardeps
::
f_cvc_ntot
;
i
++
)
{
features
().
push_back
(
new
feature
);
}
f_description
(
f_cvc_active
,
"active"
);
// The dependency below may become useful if we use dynamic atom groups
// f_req_children(f_cvc_active, f_ag_active);
f_description
(
f_cvc_scalar
,
"scalar"
);
f_description
(
f_cvc_gradient
,
"gradient"
);
f_description
(
f_cvc_inv_gradient
,
"inverse gradient"
);
f_req_self
(
f_cvc_inv_gradient
,
f_cvc_gradient
);
f_description
(
f_cvc_debug_gradient
,
"debug gradient"
);
f_req_self
(
f_cvc_debug_gradient
,
f_cvc_gradient
);
f_description
(
f_cvc_Jacobian
,
"Jacobian derivative"
);
f_req_self
(
f_cvc_Jacobian
,
f_cvc_inv_gradient
);
f_description
(
f_cvc_com_based
,
"depends on group centers of mass"
);
f_description
(
f_cvc_scalable
,
"scalable calculation"
);
f_req_self
(
f_cvc_scalable
,
f_cvc_scalable_com
);
f_description
(
f_cvc_scalable_com
,
"scalable calculation of centers of mass"
);
f_req_self
(
f_cvc_scalable_com
,
f_cvc_com_based
);
// TODO only enable this when f_ag_scalable can be turned on for a pre-initialized group
// f_req_children(f_cvc_scalable, f_ag_scalable);
// f_req_children(f_cvc_scalable_com, f_ag_scalable_com);
}
// Initialize feature_states for each instance
// default as unavailable, not enabled
feature_states
.
reserve
(
f_cvc_ntot
);
for
(
i
=
0
;
i
<
colvardeps
::
f_cvc_ntot
;
i
++
)
{
feature_states
.
push_back
(
new
feature_state
(
false
,
false
));
}
// Features that are implemented by all cvcs by default
// Each cvc specifies what other features are available
feature_states
[
f_cvc_active
]
->
available
=
true
;
feature_states
[
f_cvc_gradient
]
->
available
=
true
;
feature_states
[
f_cvc_scalable_com
]
->
available
=
(
cvm
::
proxy
->
scalable_group_coms
()
==
COLVARS_OK
);
feature_states
[
f_cvc_scalable
]
->
available
=
feature_states
[
f_cvc_scalable_com
]
->
available
;
}
void
colvardeps
::
init_ag_requires
()
{
size_t
i
;
// Initialize static array once and for all
if
(
features
().
size
()
==
0
)
{
for
(
i
=
0
;
i
<
f_ag_ntot
;
i
++
)
{
features
().
push_back
(
new
feature
);
}
f_description
(
f_ag_active
,
"active"
);
f_description
(
f_ag_center
,
"translational fit"
);
f_description
(
f_ag_rotate
,
"rotational fit"
);
f_description
(
f_ag_fitting_group
,
"reference positions group"
);
f_description
(
f_ag_fit_gradient_group
,
"fit gradient for main group"
);
f_description
(
f_ag_fit_gradient_ref
,
"fit gradient for reference group"
);
f_description
(
f_ag_atom_forces
,
"atomic forces"
);
// parallel calculation implies that we have at least a scalable center of mass,
// but f_ag_scalable is kept as a separate feature to deal with future dependencies
f_description
(
f_ag_scalable
,
"scalable group calculation"
);
f_description
(
f_ag_scalable_com
,
"scalable group center of mass calculation"
);
f_req_self
(
f_ag_scalable
,
f_ag_scalable_com
);
// f_description(f_ag_min_msd_fit, "minimum MSD fit")
// f_req_self(f_ag_min_msd_fit, f_ag_center)
// f_req_self(f_ag_min_msd_fit, f_ag_rotate)
// f_req_exclude(f_ag_min_msd_fit, f_ag_fitting_group)
}
// Initialize feature_states for each instance
// default as unavailable, not enabled
feature_states
.
reserve
(
f_ag_ntot
);
for
(
i
=
0
;
i
<
colvardeps
::
f_ag_ntot
;
i
++
)
{
feature_states
.
push_back
(
new
feature_state
(
false
,
false
));
}
// Features that are implemented (or not) by all atom groups
feature_states
[
f_ag_active
]
->
available
=
true
;
feature_states
[
f_ag_scalable_com
]
->
available
=
(
cvm
::
proxy
->
scalable_group_coms
()
==
COLVARS_OK
);
feature_states
[
f_ag_scalable
]
->
available
=
feature_states
[
f_ag_scalable_com
]
->
available
;
}
void
colvardeps
::
print_state
()
{
size_t
i
;
cvm
::
log
(
"Enabled features of "
+
description
);
for
(
i
=
0
;
i
<
feature_states
.
size
();
i
++
)
{
if
(
feature_states
[
i
]
->
enabled
)
cvm
::
log
(
"- "
+
features
()[
i
]
->
description
);
}
for
(
i
=
0
;
i
<
children
.
size
();
i
++
)
{
cvm
::
log
(
"* child "
+
cvm
::
to_str
(
i
+
1
));
cvm
::
increase_depth
();
children
[
i
]
->
print_state
();
cvm
::
decrease_depth
();
}
}
void
colvardeps
::
add_child
(
colvardeps
*
child
)
{
children
.
push_back
(
child
);
child
->
parents
.
push_back
((
colvardeps
*
)
this
);
}
void
colvardeps
::
remove_child
(
colvardeps
*
child
)
{
int
i
;
bool
found
=
false
;
for
(
i
=
children
.
size
()
-
1
;
i
>=
0
;
--
i
)
{
if
(
children
[
i
]
==
child
)
{
children
.
erase
(
children
.
begin
()
+
i
);
found
=
true
;
break
;
}
}
if
(
!
found
)
{
cvm
::
error
(
"Trying to remove missing child reference from "
+
description
+
"
\n
"
);
}
found
=
false
;
for
(
i
=
child
->
parents
.
size
()
-
1
;
i
>=
0
;
--
i
)
{
if
(
child
->
parents
[
i
]
==
this
)
{
child
->
parents
.
erase
(
child
->
parents
.
begin
()
+
i
);
found
=
true
;
break
;
}
}
if
(
!
found
)
{
cvm
::
error
(
"Trying to remove missing parent reference from "
+
child
->
description
+
"
\n
"
);
}
}
void
colvardeps
::
remove_all_children
()
{
size_t
i
;
int
j
;
bool
found
;
for
(
i
=
0
;
i
<
children
.
size
();
++
i
)
{
found
=
false
;
for
(
j
=
children
[
i
]
->
parents
.
size
()
-
1
;
j
>=
0
;
--
j
)
{
if
(
children
[
i
]
->
parents
[
j
]
==
this
)
{
children
[
i
]
->
parents
.
erase
(
children
[
i
]
->
parents
.
begin
()
+
j
);
found
=
true
;
break
;
}
}
if
(
!
found
)
{
cvm
::
error
(
"Trying to remove missing parent reference from "
+
children
[
i
]
->
description
+
"
\n
"
);
}
}
children
.
clear
();
}
Event Timeline
Log In to Comment