Update Colvars library to version 2024-06-04
This commit is contained in:
Binary file not shown.
@ -25,6 +25,7 @@ COLVARS_INCFLAGS = -DCOLVARS_LAMMPS $(COLVARS_DEBUG_INCFLAGS) $(COLVARS_PYTHON_I
|
||||
COLVARS_SRCS = \
|
||||
colvaratoms.cpp \
|
||||
colvarbias_abf.cpp \
|
||||
colvarbias_abmd.cpp \
|
||||
colvarbias_alb.cpp \
|
||||
colvarbias.cpp \
|
||||
colvarbias_histogram.cpp \
|
||||
@ -59,6 +60,7 @@ COLVARS_SRCS = \
|
||||
colvarscript_commands.cpp \
|
||||
colvarscript_commands_bias.cpp \
|
||||
colvarscript_commands_colvar.cpp \
|
||||
colvars_memstream.cpp \
|
||||
colvartypes.cpp \
|
||||
colvarvalue.cpp \
|
||||
colvar_neuralnetworkcompute.cpp
|
||||
|
||||
@ -1,201 +1,230 @@
|
||||
|
||||
$(COLVARS_OBJ_DIR)colvaratoms.o: colvaratoms.cpp colvarmodule.h \
|
||||
colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \
|
||||
$(COLVARS_OBJ_DIR)colvaratoms.o: colvaratoms.cpp colvardeps.h \
|
||||
colvarmodule.h colvars_version.h colvarparse.h colvarvalue.h \
|
||||
colvartypes.h ../../src/math_eigen_impl.h colvarparams.h colvarproxy.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvarparse.h colvarparams.h colvaratoms.h \
|
||||
colvardeps.h
|
||||
colvarproxy_volmaps.h colvaratoms.h colvar_rotation_derivative.h
|
||||
$(COLVARS_OBJ_DIR)colvarbias_abf.o: colvarbias_abf.cpp colvarmodule.h \
|
||||
colvars_version.h colvar.h colvarvalue.h colvartypes.h colvarparse.h \
|
||||
colvarparams.h colvardeps.h colvarbias_abf.h colvarproxy.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvarbias.h colvargrid.h colvar_UIestimator.h
|
||||
colvars_version.h colvar.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarparse.h colvarparams.h colvardeps.h \
|
||||
colvarbias_abf.h colvarproxy.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvarbias.h colvargrid.h \
|
||||
colvar_UIestimator.h colvars_memstream.h
|
||||
$(COLVARS_OBJ_DIR)colvarbias_abmd.o: colvarbias_abmd.cpp \
|
||||
colvarbias_abmd.h colvarbias_restraint.h colvarbias.h colvar.h \
|
||||
colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarparse.h colvarparams.h colvardeps.h \
|
||||
colvarproxy.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h
|
||||
$(COLVARS_OBJ_DIR)colvarbias_alb.o: colvarbias_alb.cpp colvarmodule.h \
|
||||
colvars_version.h colvarbias.h colvar.h colvarvalue.h colvartypes.h \
|
||||
colvarparse.h colvarparams.h colvardeps.h colvarbias_alb.h
|
||||
colvars_version.h colvarproxy.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvarbias.h colvar.h \
|
||||
colvarvalue.h colvarparse.h colvarparams.h colvardeps.h colvarbias_alb.h
|
||||
$(COLVARS_OBJ_DIR)colvarbias.o: colvarbias.cpp colvarmodule.h \
|
||||
colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvarbias.h colvar.h colvarparse.h colvarparams.h \
|
||||
colvardeps.h colvargrid.h
|
||||
colvars_version.h colvarproxy.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvarvalue.h colvarbias.h \
|
||||
colvar.h colvarparse.h colvarparams.h colvardeps.h colvargrid.h \
|
||||
colvars_memstream.h
|
||||
$(COLVARS_OBJ_DIR)colvarbias_histogram.o: colvarbias_histogram.cpp \
|
||||
colvarmodule.h colvars_version.h colvarproxy.h colvartypes.h \
|
||||
colvarvalue.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvar.h colvarparse.h colvarparams.h colvardeps.h \
|
||||
colvarbias_histogram.h colvarbias.h colvargrid.h
|
||||
../../src/math_eigen_impl.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvar.h colvarvalue.h \
|
||||
colvarparse.h colvarparams.h colvardeps.h colvarbias_histogram.h \
|
||||
colvarbias.h colvargrid.h colvars_memstream.h
|
||||
$(COLVARS_OBJ_DIR)colvarbias_histogram_reweight_amd.o: \
|
||||
colvarbias_histogram_reweight_amd.cpp \
|
||||
colvarbias_histogram_reweight_amd.h colvarbias_histogram.h colvarbias.h \
|
||||
colvar.h colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \
|
||||
colvarparse.h colvarparams.h colvardeps.h colvargrid.h colvarproxy.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h
|
||||
../../src/math_eigen_impl.h colvarparse.h colvarparams.h colvardeps.h \
|
||||
colvargrid.h colvarproxy.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvars_memstream.h
|
||||
$(COLVARS_OBJ_DIR)colvarbias_meta.o: colvarbias_meta.cpp colvarmodule.h \
|
||||
colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvar.h colvarparse.h colvarparams.h colvardeps.h \
|
||||
colvarbias_meta.h colvarbias.h colvargrid.h
|
||||
colvars_version.h colvarproxy.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvar.h colvarvalue.h \
|
||||
colvarparse.h colvarparams.h colvardeps.h colvarbias_meta.h colvarbias.h \
|
||||
colvargrid.h colvars_memstream.h
|
||||
$(COLVARS_OBJ_DIR)colvarbias_restraint.o: colvarbias_restraint.cpp \
|
||||
colvarmodule.h colvars_version.h colvarproxy.h colvartypes.h \
|
||||
colvarvalue.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvarbias_restraint.h colvarbias.h colvar.h \
|
||||
colvarparse.h colvarparams.h colvardeps.h
|
||||
../../src/math_eigen_impl.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvarvalue.h \
|
||||
colvarbias_restraint.h colvarbias.h colvar.h colvarparse.h \
|
||||
colvarparams.h colvardeps.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_alchlambda.o: colvarcomp_alchlambda.cpp \
|
||||
colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \
|
||||
colvarparse.h colvarparams.h colvar.h colvardeps.h colvarcomp.h \
|
||||
colvaratoms.h colvarproxy.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvar_arithmeticpath.h \
|
||||
../../src/math_eigen_impl.h colvar.h colvarparse.h colvarparams.h \
|
||||
colvardeps.h colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_angles.o: colvarcomp_angles.cpp \
|
||||
colvarmodule.h colvars_version.h colvar.h colvarvalue.h colvartypes.h \
|
||||
colvarparse.h colvarparams.h colvardeps.h colvarcomp.h colvaratoms.h \
|
||||
colvarproxy.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_apath.o: colvarcomp_apath.cpp colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h colvarparse.h \
|
||||
colvarparams.h colvar.h colvardeps.h colvarcomp.h colvaratoms.h \
|
||||
colvarproxy.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_coordnums.o: colvarcomp_coordnums.cpp \
|
||||
colvarmodule.h colvars_version.h colvarparse.h colvarvalue.h \
|
||||
colvartypes.h colvarparams.h colvaratoms.h colvarproxy.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvardeps.h colvar.h colvarcomp.h \
|
||||
colvar_arithmeticpath.h colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp.o: colvarcomp.cpp colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h colvar.h colvarparse.h \
|
||||
colvarparams.h colvardeps.h colvarcomp.h colvaratoms.h colvarproxy.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_distances.o: colvarcomp_distances.cpp \
|
||||
colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \
|
||||
colvarparse.h colvarparams.h colvar.h colvardeps.h colvarcomp.h \
|
||||
colvaratoms.h colvarproxy.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvar_arithmeticpath.h \
|
||||
../../src/math_eigen_impl.h colvarparse.h colvarparams.h colvardeps.h \
|
||||
colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_gpath.o: colvarcomp_gpath.cpp colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h colvarparse.h \
|
||||
colvarparams.h colvar.h colvardeps.h colvarcomp.h colvaratoms.h \
|
||||
colvarproxy.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_neuralnetwork.o: \
|
||||
colvarcomp_neuralnetwork.cpp colvarmodule.h colvars_version.h \
|
||||
colvarvalue.h colvartypes.h colvarparse.h colvarparams.h colvar.h \
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_apath.o: colvarcomp_apath.cpp colvarvalue.h \
|
||||
colvarmodule.h colvars_version.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvar.h colvarparse.h colvarparams.h \
|
||||
colvardeps.h colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvar_arithmeticpath.h colvar_geometricpath.h \
|
||||
colvar_geometricpath.h colvar_arithmeticpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_coordnums.o: colvarcomp_coordnums.cpp \
|
||||
colvarmodule.h colvars_version.h colvaratoms.h colvarproxy.h \
|
||||
colvartypes.h ../../src/math_eigen_impl.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvarparse.h colvarvalue.h colvarparams.h colvardeps.h colvar.h \
|
||||
colvarcomp.h colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp.o: colvarcomp.cpp colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvar.h colvarparse.h colvarparams.h \
|
||||
colvardeps.h colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_distances.o: colvarcomp_distances.cpp \
|
||||
colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvar.h colvarparse.h colvarparams.h \
|
||||
colvardeps.h colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvar_geometricpath.h colvar_rotation_derivative.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_gpath.o: colvarcomp_gpath.cpp colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvar.h colvarparse.h colvarparams.h \
|
||||
colvardeps.h colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_neuralnetwork.o: \
|
||||
colvarcomp_neuralnetwork.cpp colvarmodule.h colvars_version.h \
|
||||
colvarvalue.h colvartypes.h ../../src/math_eigen_impl.h colvar.h \
|
||||
colvarparse.h colvarparams.h colvardeps.h colvarcomp.h colvaratoms.h \
|
||||
colvarproxy.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvar_geometricpath.h \
|
||||
colvar_neuralnetworkcompute.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_combination.o: colvarcomp_combination.cpp \
|
||||
colvarcomp.h colvarmodule.h colvars_version.h colvar.h colvarvalue.h \
|
||||
colvartypes.h colvarparse.h colvarparams.h colvardeps.h colvaratoms.h \
|
||||
colvarproxy.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h
|
||||
colvarcomp.h colvarmodule.h colvars_version.h colvaratoms.h \
|
||||
colvarproxy.h colvartypes.h ../../src/math_eigen_impl.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvarparse.h colvarvalue.h colvarparams.h colvardeps.h colvar.h \
|
||||
colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_protein.o: colvarcomp_protein.cpp \
|
||||
colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \
|
||||
colvarparse.h colvarparams.h colvar.h colvardeps.h colvarcomp.h \
|
||||
colvaratoms.h colvarproxy.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvar_arithmeticpath.h \
|
||||
../../src/math_eigen_impl.h colvar.h colvarparse.h colvarparams.h \
|
||||
colvardeps.h colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_rotations.o: colvarcomp_rotations.cpp \
|
||||
colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \
|
||||
colvarparse.h colvarparams.h colvar.h colvardeps.h colvarcomp.h \
|
||||
colvaratoms.h colvarproxy.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvar_arithmeticpath.h \
|
||||
colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_volmaps.o: colvarcomp_volmaps.cpp \
|
||||
colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \
|
||||
colvarparse.h colvarparams.h colvar.h colvardeps.h colvarcomp.h \
|
||||
colvaratoms.h colvarproxy.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvar_arithmeticpath.h \
|
||||
colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvar.o: colvar.cpp colvarmodule.h colvars_version.h \
|
||||
colvarvalue.h colvartypes.h colvarparse.h colvarparams.h colvar.h \
|
||||
../../src/math_eigen_impl.h colvar.h colvarparse.h colvarparams.h \
|
||||
colvardeps.h colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvar_arithmeticpath.h colvar_geometricpath.h colvarscript.h \
|
||||
colvarbias.h colvarscript_commands.h colvarscript_commands_colvar.h \
|
||||
colvarscript_commands_bias.h
|
||||
colvar_geometricpath.h colvar_rotation_derivative.h
|
||||
$(COLVARS_OBJ_DIR)colvarcomp_volmaps.o: colvarcomp_volmaps.cpp \
|
||||
colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvar.h colvarparse.h colvarparams.h \
|
||||
colvardeps.h colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvar_geometricpath.h
|
||||
$(COLVARS_OBJ_DIR)colvar.o: colvar.cpp colvarmodule.h colvars_version.h \
|
||||
colvarvalue.h colvartypes.h ../../src/math_eigen_impl.h colvarparse.h \
|
||||
colvarparams.h colvarcomp.h colvaratoms.h colvarproxy.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvardeps.h colvar.h colvar_geometricpath.h colvarbias.h \
|
||||
colvars_memstream.h
|
||||
$(COLVARS_OBJ_DIR)colvardeps.o: colvardeps.cpp colvarmodule.h \
|
||||
colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvardeps.h colvarparse.h colvarparams.h
|
||||
colvars_version.h colvarproxy.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvardeps.h colvarparse.h \
|
||||
colvarvalue.h colvarparams.h
|
||||
$(COLVARS_OBJ_DIR)colvargrid.o: colvargrid.cpp colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h colvarparse.h \
|
||||
colvarparams.h colvar.h colvardeps.h colvarcomp.h colvaratoms.h \
|
||||
colvarproxy.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvar_arithmeticpath.h colvar_geometricpath.h \
|
||||
colvargrid.h colvargrid_def.h
|
||||
colvars_version.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarparse.h colvarparams.h colvar.h \
|
||||
colvardeps.h colvargrid.h colvargrid_def.h colvarproxy.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvars_memstream.h
|
||||
$(COLVARS_OBJ_DIR)colvarmodule.o: colvarmodule.cpp colvarmodule.h \
|
||||
colvars_version.h colvarparse.h colvarvalue.h colvartypes.h \
|
||||
colvarparams.h colvarproxy.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvar.h colvardeps.h \
|
||||
colvarbias.h colvarbias_abf.h colvargrid.h colvar_UIestimator.h \
|
||||
colvarbias_alb.h colvarbias_histogram.h \
|
||||
colvarbias_histogram_reweight_amd.h colvarbias_meta.h \
|
||||
colvarbias_restraint.h colvarscript.h colvarscript_commands.h \
|
||||
colvarscript_commands_colvar.h colvarscript_commands_bias.h \
|
||||
colvaratoms.h colvarcomp.h colvar_arithmeticpath.h \
|
||||
colvar_geometricpath.h colvarmodule_refs.h
|
||||
$(COLVARS_OBJ_DIR)colvarparams.o: colvarparams.cpp colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h colvarparams.h
|
||||
$(COLVARS_OBJ_DIR)colvarparse.o: colvarparse.cpp colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h colvarparse.h \
|
||||
colvarparams.h
|
||||
$(COLVARS_OBJ_DIR)colvarproxy.o: colvarproxy.cpp colvarmodule.h \
|
||||
colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \
|
||||
../../src/math_eigen_impl.h colvarparams.h colvarproxy.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvarscript.h colvarbias.h colvar.h colvarparse.h \
|
||||
colvarparams.h colvardeps.h colvarscript_commands.h \
|
||||
colvarscript_commands_colvar.h colvarscript_commands_bias.h \
|
||||
colvaratoms.h colvarmodule_utils.h
|
||||
colvarproxy_volmaps.h colvar.h colvardeps.h colvarbias.h \
|
||||
colvarbias_abf.h colvargrid.h colvar_UIestimator.h colvarbias_abmd.h \
|
||||
colvarbias_restraint.h colvarbias_alb.h colvarbias_histogram.h \
|
||||
colvarbias_histogram_reweight_amd.h colvarbias_meta.h colvarscript.h \
|
||||
colvarscript_commands.h colvarscript_commands_colvar.h \
|
||||
colvarscript_commands_bias.h colvaratoms.h colvarcomp.h \
|
||||
colvar_geometricpath.h colvars_memstream.h colvarmodule_refs.h
|
||||
$(COLVARS_OBJ_DIR)colvarparams.o: colvarparams.cpp colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarparams.h
|
||||
$(COLVARS_OBJ_DIR)colvarparse.o: colvarparse.cpp colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarparse.h colvarparams.h \
|
||||
colvars_memstream.h
|
||||
$(COLVARS_OBJ_DIR)colvarproxy.o: colvarproxy.cpp colvarmodule.h \
|
||||
colvars_version.h colvarproxy.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvar.h colvarvalue.h \
|
||||
colvarparse.h colvarparams.h colvardeps.h colvarbias.h colvarscript.h \
|
||||
colvarscript_commands.h colvarscript_commands_colvar.h \
|
||||
colvarscript_commands_bias.h colvarmodule_utils.h
|
||||
$(COLVARS_OBJ_DIR)colvarproxy_io.o: colvarproxy_io.cpp colvarmodule.h \
|
||||
colvars_version.h colvarproxy_io.h
|
||||
$(COLVARS_OBJ_DIR)colvarproxy_replicas.o: colvarproxy_replicas.cpp \
|
||||
colvarmodule.h colvars_version.h colvarproxy.h colvartypes.h \
|
||||
colvarvalue.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h
|
||||
../../src/math_eigen_impl.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h
|
||||
$(COLVARS_OBJ_DIR)colvarproxy_system.o: colvarproxy_system.cpp \
|
||||
colvarmodule.h colvars_version.h colvartypes.h colvarproxy_system.h
|
||||
colvarmodule.h colvars_version.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarproxy_system.h
|
||||
$(COLVARS_OBJ_DIR)colvarproxy_tcl.o: colvarproxy_tcl.cpp colvarmodule.h \
|
||||
colvars_version.h colvarproxy.h colvartypes.h colvarvalue.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvaratoms.h colvarparse.h colvarparams.h \
|
||||
colvardeps.h
|
||||
colvars_version.h colvarproxy.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvaratoms.h colvarparse.h \
|
||||
colvarvalue.h colvarparams.h colvardeps.h
|
||||
$(COLVARS_OBJ_DIR)colvarproxy_volmaps.o: colvarproxy_volmaps.cpp \
|
||||
colvarmodule.h colvars_version.h colvarproxy_volmaps.h \
|
||||
colvarmodule_utils.h
|
||||
$(COLVARS_OBJ_DIR)colvarscript.o: colvarscript.cpp colvarproxy.h \
|
||||
colvarmodule.h colvars_version.h colvartypes.h colvarvalue.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvardeps.h colvarparse.h colvarparams.h \
|
||||
colvarscript.h colvarbias.h colvar.h colvarscript_commands.h \
|
||||
colvarmodule.h colvars_version.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvardeps.h colvarparse.h \
|
||||
colvarvalue.h colvarparams.h colvarscript.h colvarscript_commands.h \
|
||||
colvarscript_commands_colvar.h colvarscript_commands_bias.h
|
||||
$(COLVARS_OBJ_DIR)colvarscript_commands.o: colvarscript_commands.cpp \
|
||||
colvarproxy.h colvarmodule.h colvars_version.h colvartypes.h \
|
||||
colvarvalue.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvardeps.h colvarparse.h colvarparams.h \
|
||||
colvarscript.h colvarbias.h colvar.h colvarscript_commands.h \
|
||||
colvarscript_commands_colvar.h colvarscript_commands_bias.h
|
||||
colvar.h colvarmodule.h colvars_version.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarparse.h colvarparams.h colvardeps.h \
|
||||
colvarbias.h colvarproxy.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvarscript.h \
|
||||
colvarscript_commands.h colvarscript_commands_colvar.h \
|
||||
colvarscript_commands_bias.h
|
||||
$(COLVARS_OBJ_DIR)colvarscript_commands_bias.o: \
|
||||
colvarscript_commands_bias.cpp colvarproxy.h colvarmodule.h \
|
||||
colvars_version.h colvartypes.h colvarvalue.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvardeps.h colvarparse.h colvarparams.h colvarscript.h colvarbias.h \
|
||||
colvar.h colvarscript_commands.h colvarscript_commands_colvar.h \
|
||||
colvarscript_commands_bias.h
|
||||
colvars_version.h colvartypes.h ../../src/math_eigen_impl.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvarbias.h colvar.h colvarvalue.h colvarparse.h \
|
||||
colvarparams.h colvardeps.h colvarscript.h colvarscript_commands.h \
|
||||
colvarscript_commands_colvar.h colvarscript_commands_bias.h
|
||||
$(COLVARS_OBJ_DIR)colvarscript_commands_colvar.o: \
|
||||
colvarscript_commands_colvar.cpp colvarproxy.h colvarmodule.h \
|
||||
colvars_version.h colvartypes.h colvarvalue.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h \
|
||||
colvardeps.h colvarparse.h colvarparams.h colvarscript.h colvarbias.h \
|
||||
colvar.h colvarscript_commands.h colvarscript_commands_colvar.h \
|
||||
colvarscript_commands_bias.h
|
||||
colvarscript_commands_colvar.cpp colvar.h colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarparse.h colvarparams.h colvardeps.h \
|
||||
colvarproxy.h colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h colvarscript.h colvarscript_commands.h \
|
||||
colvarscript_commands_colvar.h colvarscript_commands_bias.h
|
||||
$(COLVARS_OBJ_DIR)colvars_memstream.o: colvars_memstream.cpp \
|
||||
colvarmodule.h colvars_version.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvarvalue.h colvars_memstream.h
|
||||
$(COLVARS_OBJ_DIR)colvartypes.o: colvartypes.cpp colvarmodule.h \
|
||||
colvars_version.h colvartypes.h colvarparse.h colvarvalue.h \
|
||||
colvarparams.h ../../src/math_eigen_impl.h
|
||||
colvars_version.h colvartypes.h ../../src/math_eigen_impl.h \
|
||||
colvaratoms.h colvarproxy.h colvarproxy_io.h colvarproxy_system.h \
|
||||
colvarproxy_tcl.h colvarproxy_volmaps.h colvarparse.h colvarvalue.h \
|
||||
colvarparams.h colvardeps.h colvar_rotation_derivative.h
|
||||
$(COLVARS_OBJ_DIR)colvarvalue.o: colvarvalue.cpp colvarmodule.h \
|
||||
colvars_version.h colvarvalue.h colvartypes.h
|
||||
colvars_version.h colvarvalue.h colvartypes.h \
|
||||
../../src/math_eigen_impl.h colvars_memstream.h
|
||||
$(COLVARS_OBJ_DIR)colvar_neuralnetworkcompute.o: \
|
||||
colvar_neuralnetworkcompute.cpp colvar_neuralnetworkcompute.h \
|
||||
colvarparse.h colvarmodule.h colvars_version.h colvarvalue.h \
|
||||
colvartypes.h colvarparams.h colvarproxy.h colvarproxy_io.h \
|
||||
colvarproxy_system.h colvarproxy_tcl.h colvarproxy_volmaps.h
|
||||
colvartypes.h ../../src/math_eigen_impl.h colvarparams.h colvarproxy.h \
|
||||
colvarproxy_io.h colvarproxy_system.h colvarproxy_tcl.h \
|
||||
colvarproxy_volmaps.h
|
||||
|
||||
@ -16,13 +16,18 @@
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarcomp.h"
|
||||
#include "colvarscript.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarbias.h"
|
||||
#include "colvars_memstream.h"
|
||||
|
||||
|
||||
std::map<std::string, std::function<colvar::cvc *()>> colvar::global_cvc_map =
|
||||
std::map<std::string, std::function<colvar::cvc *()>>();
|
||||
|
||||
std::map<std::string, std::string> colvar::global_cvc_desc_map =
|
||||
std::map<std::string, std::string>();
|
||||
|
||||
#if (__cplusplus >= 201103L)
|
||||
std::map<std::string, std::function<colvar::cvc* (const std::string& subcv_conf)>> colvar::global_cvc_map = std::map<std::string, std::function<colvar::cvc* (const std::string& subcv_conf)>>();
|
||||
#endif
|
||||
|
||||
colvar::colvar()
|
||||
{
|
||||
@ -36,6 +41,8 @@ colvar::colvar()
|
||||
dev_null = 0.0;
|
||||
#endif
|
||||
|
||||
matching_state = false;
|
||||
|
||||
expand_boundaries = false;
|
||||
|
||||
description = "uninitialized colvar";
|
||||
@ -131,7 +138,14 @@ int colvar::init(std::string const &conf)
|
||||
|
||||
// Sort array of cvcs based on their names
|
||||
// Note: default CVC names are in input order for same type of CVC
|
||||
std::sort(cvcs.begin(), cvcs.end(), colvar::compare_cvc);
|
||||
std::sort(cvcs.begin(), cvcs.end(),
|
||||
[](std::shared_ptr<colvar::cvc> const &cvc1,
|
||||
std::shared_ptr<colvar::cvc> const &cvc2) -> bool {
|
||||
if (cvc1 && cvc2) {
|
||||
return cvc1->name < cvc2->name;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if(cvcs.size() > 1) {
|
||||
cvm::log("Sorted list of components for this scripted colvar:\n");
|
||||
@ -188,7 +202,7 @@ int colvar::init(std::string const &conf)
|
||||
cvm::log("Warning: you chose a negative exponent in the combination; "
|
||||
"if you apply forces, the simulation may become unstable "
|
||||
"when the component \""+
|
||||
(cvcs[i])->function_type+"\" approaches zero.\n");
|
||||
(cvcs[i])->function_type()+"\" approaches zero.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -295,7 +309,7 @@ int colvar::init(std::string const &conf)
|
||||
error_code |= init_grid_parameters(conf);
|
||||
|
||||
// Detect if we have a single component that is an alchemical lambda
|
||||
if (is_enabled(f_cv_single_cvc) && cvcs[0]->function_type == "alchLambda") {
|
||||
if (is_enabled(f_cv_single_cvc) && cvcs[0]->function_type() == "alchLambda") {
|
||||
enable(f_cv_external);
|
||||
}
|
||||
|
||||
@ -468,13 +482,6 @@ int colvar::init_custom_function(std::string const &conf)
|
||||
size_t pos = 0;
|
||||
if (key_lookup(conf, "customFunction", &expr, &pos)) {
|
||||
std::string msg("Error: customFunction requires the Lepton library.");
|
||||
#if (__cplusplus < 201103L)
|
||||
// NOTE: this is not ideal; testing for the Lepton library's version would
|
||||
// be more accurate, but also less portable
|
||||
msg +=
|
||||
std::string(" Note also that recent versions of Lepton require C++11: "
|
||||
"please see https://colvars.github.io/README-c++11.html.");
|
||||
#endif
|
||||
return cvm::error(msg, COLVARS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
@ -697,9 +704,14 @@ int colvar::init_extended_Lagrangian(std::string const &conf)
|
||||
}
|
||||
if (ext_gamma != 0.0) {
|
||||
enable(f_cv_Langevin);
|
||||
cvm::main()->cite_feature("BAOA integrator");
|
||||
ext_gamma *= 1.0e-3; // correct as long as input is required in ps-1 and cvm::dt() is in fs
|
||||
// Adjust Langevin sigma for slow time step if time_step_factor != 1
|
||||
ext_sigma = cvm::sqrt(2.0 * proxy->boltzmann() * temp * ext_gamma * ext_mass / (cvm::dt() * cvm::real(time_step_factor)));
|
||||
// Eq. (6a) in https://doi.org/10.1021/acs.jctc.2c00585
|
||||
ext_sigma = cvm::sqrt((1.0 - cvm::exp(-2.0 * ext_gamma * cvm::dt() * cvm::real(time_step_factor)))
|
||||
* ext_mass * proxy->boltzmann() * temp);
|
||||
} else {
|
||||
ext_sigma = 0.0;
|
||||
}
|
||||
|
||||
get_keyval_feature(this, conf, "reflectingLowerBoundary", f_cv_reflecting_lower_boundary, false);
|
||||
@ -744,75 +756,56 @@ int colvar::init_output_flags(std::string const &conf)
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
#if (__cplusplus >= 201103L)
|
||||
// C++11
|
||||
template<typename def_class_name> int colvar::init_components_type(std::string const &,
|
||||
char const * /* def_desc */,
|
||||
char const *def_config_key) {
|
||||
// global_cvc_map is only supported in the C++11 case
|
||||
global_cvc_map[def_config_key] = [](const std::string& cvc_conf){return new def_class_name(cvc_conf);};
|
||||
// TODO: maybe it is better to do more check to avoid duplication in the map?
|
||||
return COLVARS_OK;
|
||||
|
||||
template <typename def_class_name>
|
||||
void colvar::add_component_type(char const *def_description, char const *def_config_key)
|
||||
{
|
||||
if (global_cvc_map.count(def_config_key) == 0) {
|
||||
global_cvc_map[def_config_key] = []() {
|
||||
return new def_class_name();
|
||||
};
|
||||
global_cvc_desc_map[def_config_key] = std::string(def_description);
|
||||
}
|
||||
}
|
||||
|
||||
int colvar::init_components_type_from_global_map(const std::string& conf,
|
||||
const char* def_config_key) {
|
||||
#else
|
||||
template<typename def_class_name> int colvar::init_components_type(std::string const & conf,
|
||||
char const * /* def_desc */,
|
||||
char const *def_config_key) {
|
||||
#endif
|
||||
|
||||
int colvar::init_components_type(const std::string& conf, const char* def_config_key) {
|
||||
size_t def_count = 0;
|
||||
std::string def_conf = "";
|
||||
size_t pos = 0;
|
||||
int error_code = COLVARS_OK;
|
||||
while ( this->key_lookup(conf,
|
||||
def_config_key,
|
||||
&def_conf,
|
||||
&pos) ) {
|
||||
if (!def_conf.size()) continue;
|
||||
|
||||
cvm::log("Initializing "
|
||||
"a new \""+std::string(def_config_key)+"\" component"+
|
||||
(cvm::debug() ? ", with configuration:\n"+def_conf
|
||||
: ".\n"));
|
||||
cvm::increase_depth();
|
||||
// only the following line is different from init_components_type
|
||||
// in the non-C++11 case
|
||||
#if (__cplusplus >= 201103L)
|
||||
cvc *cvcp = global_cvc_map.at(def_config_key)(def_conf);
|
||||
#else
|
||||
cvc *cvcp = new def_class_name(def_conf);
|
||||
#endif
|
||||
if (cvcp != NULL) {
|
||||
cvcs.push_back(cvcp);
|
||||
cvcp->check_keywords(def_conf, def_config_key);
|
||||
cvcp->set_function_type(def_config_key);
|
||||
if (cvm::get_error()) {
|
||||
cvm::error("Error: in setting up component \""+
|
||||
std::string(def_config_key)+"\".\n", COLVARS_INPUT_ERROR);
|
||||
return COLVARS_INPUT_ERROR;
|
||||
}
|
||||
cvm::decrease_depth();
|
||||
} else {
|
||||
cvm::decrease_depth();
|
||||
cvm::error("Error: in allocating component \""+
|
||||
std::string(def_config_key)+"\".\n",
|
||||
cvc *cvcp = global_cvc_map[def_config_key]();
|
||||
if (!cvcp) {
|
||||
return cvm::error("Error: in creating object of type \"" + std::string(def_config_key) +
|
||||
"\".\n",
|
||||
COLVARS_MEMORY_ERROR);
|
||||
return COLVARS_MEMORY_ERROR;
|
||||
}
|
||||
cvcs.push_back(std::shared_ptr<colvar::cvc>(cvcp));
|
||||
|
||||
if ( (cvcp->period != 0.0) || (cvcp->wrap_center != 0.0) ) {
|
||||
if (! cvcp->is_enabled(f_cvc_periodic)) {
|
||||
cvm::error("Error: invalid use of period and/or "
|
||||
"wrapAround in a \""+
|
||||
std::string(def_config_key)+
|
||||
"\" component.\n"+
|
||||
"Period: "+cvm::to_str(cvcp->period) +
|
||||
" wrapAround: "+cvm::to_str(cvcp->wrap_center),
|
||||
cvm::increase_depth();
|
||||
int error_code_this = cvcp->init(def_conf);
|
||||
if (error_code_this == COLVARS_OK) {
|
||||
// Checking for invalid keywords only if the parsing was successful, otherwise any
|
||||
// early-returns due to errors would raise false positives
|
||||
error_code_this |= cvcp->check_keywords(def_conf, def_config_key);
|
||||
}
|
||||
cvm::decrease_depth();
|
||||
if (error_code_this != COLVARS_OK) {
|
||||
error_code |=
|
||||
cvm::error("Error: in setting up component \"" + std::string(def_config_key) + "\".\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return COLVARS_INPUT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Set default name if it doesn't have one
|
||||
if ( ! cvcs.back()->name.size()) {
|
||||
std::ostringstream s;
|
||||
s << def_config_key << std::setfill('0') << std::setw(4) << ++def_count;
|
||||
@ -822,135 +815,138 @@ template<typename def_class_name> int colvar::init_components_type(std::string c
|
||||
|
||||
cvcs.back()->setup();
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Done initializing a \""+
|
||||
std::string(def_config_key)+
|
||||
"\" component"+
|
||||
(cvm::debug() ?
|
||||
", named \""+cvcs.back()->name+"\""
|
||||
: "")+".\n");
|
||||
cvm::log("Done initializing a \"" + std::string(def_config_key) + "\" component" +
|
||||
(cvm::debug() ? ", named \"" + cvcs.back()->name + "\"" : "") + ".\n");
|
||||
}
|
||||
|
||||
def_conf = "";
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Parsed "+cvm::to_str(cvcs.size())+
|
||||
" components at this time.\n");
|
||||
cvm::log("Parsed " + cvm::to_str(cvcs.size()) + " components at this time.\n");
|
||||
}
|
||||
}
|
||||
|
||||
return COLVARS_OK;
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
void colvar::define_component_types()
|
||||
{
|
||||
colvarproxy *proxy = cvm::main()->proxy;
|
||||
|
||||
add_component_type<distance>("distance", "distance");
|
||||
add_component_type<distance_vec>("distance vector", "distanceVec");
|
||||
add_component_type<cartesian>("Cartesian coordinates", "cartesian");
|
||||
add_component_type<distance_dir>("distance vector direction", "distanceDir");
|
||||
add_component_type<distance_z>("distance projection on an axis", "distanceZ");
|
||||
add_component_type<distance_xy>("distance projection on a plane", "distanceXY");
|
||||
add_component_type<polar_theta>("spherical polar angle theta", "polarTheta");
|
||||
add_component_type<polar_phi>("spherical azimuthal angle phi", "polarPhi");
|
||||
add_component_type<distance_inv>("average distance weighted by inverse power", "distanceInv");
|
||||
add_component_type<distance_pairs>("N1xN2-long vector of pairwise distances", "distancePairs");
|
||||
add_component_type<dipole_magnitude>("dipole magnitude", "dipoleMagnitude");
|
||||
add_component_type<coordnum>("coordination number", "coordNum");
|
||||
add_component_type<selfcoordnum>("self-coordination number", "selfCoordNum");
|
||||
add_component_type<groupcoordnum>("group-coordination number", "groupCoord");
|
||||
add_component_type<angle>("angle", "angle");
|
||||
add_component_type<dipole_angle>("dipole angle", "dipoleAngle");
|
||||
add_component_type<dihedral>("dihedral", "dihedral");
|
||||
add_component_type<h_bond>("hydrogen bond", "hBond");
|
||||
|
||||
if (proxy->check_atom_name_selections_available() == COLVARS_OK) {
|
||||
add_component_type<alpha_angles>("alpha helix", "alpha");
|
||||
add_component_type<dihedPC>("dihedral principal component", "dihedralPC");
|
||||
}
|
||||
|
||||
add_component_type<orientation>("orientation", "orientation");
|
||||
add_component_type<orientation_angle>("orientation angle", "orientationAngle");
|
||||
add_component_type<orientation_proj>("orientation projection", "orientationProj");
|
||||
add_component_type<tilt>("tilt", "tilt");
|
||||
add_component_type<spin_angle>("spin angle", "spinAngle");
|
||||
add_component_type<rmsd>("RMSD", "rmsd");
|
||||
add_component_type<gyration>("radius of gyration", "gyration");
|
||||
add_component_type<inertia>("moment of inertia", "inertia");
|
||||
add_component_type<inertia_z>("moment of inertia around an axis", "inertiaZ");
|
||||
add_component_type<eigenvector>("eigenvector", "eigenvector");
|
||||
add_component_type<alch_lambda>("alchemical coupling parameter", "alchLambda");
|
||||
add_component_type<alch_Flambda>("force on alchemical coupling parameter", "alchFLambda");
|
||||
add_component_type<aspath>("arithmetic path collective variables (s)", "aspath");
|
||||
add_component_type<azpath>("arithmetic path collective variables (z)", "azpath");
|
||||
add_component_type<gspath>("geometrical path collective variables (s)", "gspath");
|
||||
add_component_type<gzpath>("geometrical path collective variables (z)", "gzpath");
|
||||
add_component_type<linearCombination>("linear combination of other collective variables", "linearCombination");
|
||||
add_component_type<gspathCV>("geometrical path collective variables (s) for other CVs", "gspathCV");
|
||||
add_component_type<gzpathCV>("geometrical path collective variables (z) for other CVs", "gzpathCV");
|
||||
add_component_type<aspathCV>("arithmetic path collective variables (s) for other CVs", "aspathCV");
|
||||
add_component_type<azpathCV>("arithmetic path collective variables (s) for other CVs", "azpathCV");
|
||||
add_component_type<euler_phi>("euler phi angle of the optimal orientation", "eulerPhi");
|
||||
add_component_type<euler_psi>("euler psi angle of the optimal orientation", "eulerPsi");
|
||||
add_component_type<euler_theta>("euler theta angle of the optimal orientation", "eulerTheta");
|
||||
|
||||
#ifdef LEPTON
|
||||
add_component_type<customColvar>("CV with support of the Lepton custom function", "customColvar");
|
||||
#endif
|
||||
|
||||
add_component_type<neuralNetwork>("neural network CV for other CVs", "neuralNetwork");
|
||||
|
||||
if (proxy->check_volmaps_available() == COLVARS_OK) {
|
||||
add_component_type<map_total>("total value of atomic map", "mapTotal");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int colvar::init_components(std::string const &conf)
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
size_t i = 0, j = 0;
|
||||
|
||||
// in the non-C++11 case, the components are initialized directly by init_components_type;
|
||||
// in the C++11 case, the components are stored in the global_cvc_map at first
|
||||
// by init_components_type, and then the map is iterated to initialize all components.
|
||||
error_code |= init_components_type<distance>(conf, "distance", "distance");
|
||||
error_code |= init_components_type<distance_vec>(conf, "distance vector", "distanceVec");
|
||||
error_code |= init_components_type<cartesian>(conf, "Cartesian coordinates", "cartesian");
|
||||
error_code |= init_components_type<distance_dir>(conf, "distance vector "
|
||||
"direction", "distanceDir");
|
||||
error_code |= init_components_type<distance_z>(conf, "distance projection "
|
||||
"on an axis", "distanceZ");
|
||||
error_code |= init_components_type<distance_xy>(conf, "distance projection "
|
||||
"on a plane", "distanceXY");
|
||||
error_code |= init_components_type<polar_theta>(conf, "spherical polar angle theta",
|
||||
"polarTheta");
|
||||
error_code |= init_components_type<polar_phi>(conf, "spherical azimuthal angle phi",
|
||||
"polarPhi");
|
||||
error_code |= init_components_type<distance_inv>(conf, "average distance "
|
||||
"weighted by inverse power", "distanceInv");
|
||||
error_code |= init_components_type<distance_pairs>(conf, "N1xN2-long vector "
|
||||
"of pairwise distances", "distancePairs");
|
||||
error_code |= init_components_type<dipole_magnitude>(conf, "dipole magnitude",
|
||||
"dipoleMagnitude");
|
||||
error_code |= init_components_type<coordnum>(conf, "coordination "
|
||||
"number", "coordNum");
|
||||
error_code |= init_components_type<selfcoordnum>(conf, "self-coordination "
|
||||
"number", "selfCoordNum");
|
||||
error_code |= init_components_type<groupcoordnum>(conf, "group-coordination "
|
||||
"number", "groupCoord");
|
||||
error_code |= init_components_type<angle>(conf, "angle", "angle");
|
||||
error_code |= init_components_type<dipole_angle>(conf, "dipole angle", "dipoleAngle");
|
||||
error_code |= init_components_type<dihedral>(conf, "dihedral", "dihedral");
|
||||
error_code |= init_components_type<h_bond>(conf, "hydrogen bond", "hBond");
|
||||
error_code |= init_components_type<alpha_angles>(conf, "alpha helix", "alpha");
|
||||
error_code |= init_components_type<dihedPC>(conf, "dihedral "
|
||||
"principal component", "dihedralPC");
|
||||
error_code |= init_components_type<orientation>(conf, "orientation", "orientation");
|
||||
error_code |= init_components_type<orientation_angle>(conf, "orientation "
|
||||
"angle", "orientationAngle");
|
||||
error_code |= init_components_type<orientation_proj>(conf, "orientation "
|
||||
"projection", "orientationProj");
|
||||
error_code |= init_components_type<tilt>(conf, "tilt", "tilt");
|
||||
error_code |= init_components_type<spin_angle>(conf, "spin angle", "spinAngle");
|
||||
error_code |= init_components_type<rmsd>(conf, "RMSD", "rmsd");
|
||||
error_code |= init_components_type<gyration>(conf, "radius of "
|
||||
"gyration", "gyration");
|
||||
error_code |= init_components_type<inertia>(conf, "moment of "
|
||||
"inertia", "inertia");
|
||||
error_code |= init_components_type<inertia_z>(conf, "moment of inertia around an axis", "inertiaZ");
|
||||
error_code |= init_components_type<eigenvector>(conf, "eigenvector", "eigenvector");
|
||||
error_code |= init_components_type<alch_lambda>(conf, "alchemical coupling parameter", "alchLambda");
|
||||
error_code |= init_components_type<alch_Flambda>(conf, "force on alchemical coupling parameter", "alchFLambda");
|
||||
error_code |= init_components_type<gspath>(conf, "geometrical path collective variables (s)", "gspath");
|
||||
error_code |= init_components_type<gzpath>(conf, "geometrical path collective variables (z)", "gzpath");
|
||||
error_code |= init_components_type<linearCombination>(conf, "linear combination of other collective variables", "linearCombination");
|
||||
error_code |= init_components_type<gspathCV>(conf, "geometrical path collective variables (s) for other CVs", "gspathCV");
|
||||
error_code |= init_components_type<gzpathCV>(conf, "geometrical path collective variables (z) for other CVs", "gzpathCV");
|
||||
error_code |= init_components_type<aspathCV>(conf, "arithmetic path collective variables (s) for other CVs", "aspathCV");
|
||||
error_code |= init_components_type<azpathCV>(conf, "arithmetic path collective variables (s) for other CVs", "azpathCV");
|
||||
error_code |= init_components_type<euler_phi>(conf, "euler phi angle of the optimal orientation", "eulerPhi");
|
||||
error_code |= init_components_type<euler_psi>(conf, "euler psi angle of the optimal orientation", "eulerPsi");
|
||||
error_code |= init_components_type<euler_theta>(conf, "euler theta angle of the optimal orientation", "eulerTheta");
|
||||
#ifdef LEPTON
|
||||
error_code |= init_components_type<customColvar>(conf, "CV with support of the lepton custom function", "customColvar");
|
||||
#endif
|
||||
error_code |= init_components_type<neuralNetwork>(conf, "neural network CV for other CVs", "NeuralNetwork");
|
||||
if (global_cvc_map.empty()) {
|
||||
define_component_types();
|
||||
}
|
||||
|
||||
error_code |= init_components_type<map_total>(conf, "total value of atomic map", "mapTotal");
|
||||
#if (__cplusplus >= 201103L)
|
||||
// iterate over all available CVC in the map
|
||||
for (auto it = global_cvc_map.begin(); it != global_cvc_map.end(); ++it) {
|
||||
error_code |= init_components_type_from_global_map(conf, it->first.c_str());
|
||||
error_code |= init_components_type(conf, it->first.c_str());
|
||||
// TODO: is it better to check the error code here?
|
||||
if (error_code != COLVARS_OK) {
|
||||
cvm::log("Failed to initialize " + it->first + " with the following configuration:\n");
|
||||
cvm::log(conf);
|
||||
// TODO: should it stop here?
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!cvcs.size() || (error_code != COLVARS_OK)) {
|
||||
cvm::error("Error: no valid components were provided "
|
||||
"for this collective variable.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return COLVARS_INPUT_ERROR;
|
||||
|
||||
if (!cvcs.size()) {
|
||||
std::string msg("Error: no valid components were provided for this collective variable.\n");
|
||||
msg += "Currently available component types are: \n";
|
||||
for (auto it = global_cvc_desc_map.begin(); it != global_cvc_desc_map.end(); ++it) {
|
||||
msg += " " + it->first + " -- " + it->second + "\n";
|
||||
}
|
||||
msg += "\nPlease note that some of the above types may still be unavailable, irrespective of this error.\n";
|
||||
error_code |= cvm::error(msg, COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
// Check for uniqueness of CVC names (esp. if user-provided)
|
||||
for (i = 0; i < cvcs.size(); i++) {
|
||||
for (j = i+1; j < cvcs.size(); j++) {
|
||||
for (j = i + 1; j < cvcs.size(); j++) {
|
||||
if (cvcs[i]->name == cvcs[j]->name) {
|
||||
cvm::error("Components " + cvm::to_str(i) + " and " + cvm::to_str(j) +\
|
||||
" cannot have the same name \"" + cvcs[i]->name+ "\".\n", COLVARS_INPUT_ERROR);
|
||||
return COLVARS_INPUT_ERROR;
|
||||
error_code |= cvm::error("Components " + cvm::to_str(i) + " and " + cvm::to_str(j) +
|
||||
" cannot have the same name \"" + cvcs[i]->name + "\".\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n_active_cvcs = cvcs.size();
|
||||
|
||||
if (error_code == COLVARS_OK) {
|
||||
// Store list of children cvcs for dependency checking purposes
|
||||
for (i = 0; i < cvcs.size(); i++) {
|
||||
add_child(cvcs[i]);
|
||||
add_child(cvcs[i].get());
|
||||
}
|
||||
// By default all CVCs are active at the start
|
||||
n_active_cvcs = cvcs.size();
|
||||
cvm::log("All components initialized.\n");
|
||||
}
|
||||
|
||||
cvm::log("All components initialized.\n");
|
||||
|
||||
return COLVARS_OK;
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
@ -1220,7 +1216,7 @@ int colvar::init_dependencies() {
|
||||
|
||||
// Initialize feature_states for each instance
|
||||
feature_states.reserve(f_cv_ntot);
|
||||
for (i = 0; i < f_cv_ntot; i++) {
|
||||
for (i = feature_states.size(); i < f_cv_ntot; i++) {
|
||||
feature_states.push_back(feature_state(true, false));
|
||||
// Most features are available, so we set them so
|
||||
// and list exceptions below
|
||||
@ -1283,14 +1279,10 @@ colvar::~colvar()
|
||||
// for dependency purposes
|
||||
remove_all_children();
|
||||
|
||||
for (std::vector<cvc *>::reverse_iterator ci = cvcs.rbegin();
|
||||
ci != cvcs.rend();
|
||||
++ci) {
|
||||
// clear all children of this cvc (i.e. its atom groups)
|
||||
// because the cvc base class destructor can't do it early enough
|
||||
// and we don't want to have each cvc derived class do it separately
|
||||
for (auto ci = cvcs.rbegin(); ci != cvcs.rend(); ++ci) {
|
||||
// Clear all children of this cvc (i.e. its atom groups), because the cvc base class destructor
|
||||
// can't do it early enough and we don't want to have each cvc derived class do it separately
|
||||
(*ci)->remove_all_children();
|
||||
delete *ci;
|
||||
}
|
||||
cvcs.clear();
|
||||
|
||||
@ -1512,6 +1504,7 @@ int colvar::collect_cvc_values()
|
||||
cvm::to_str(x, cvm::cv_width, cvm::cv_prec)+".\n");
|
||||
|
||||
if (after_restart) {
|
||||
x_old = x_restart;
|
||||
if (cvm::proxy->simulation_running()) {
|
||||
cvm::real const jump2 = dist2(x, x_restart) / (width*width);
|
||||
if (jump2 > 0.25) {
|
||||
@ -1555,12 +1548,12 @@ int colvar::calc_cvc_gradients(int first_cvc, size_t num_cvcs)
|
||||
(cvcs[i])->debug_gradients();
|
||||
}
|
||||
|
||||
cvm::decrease_depth();
|
||||
|
||||
if (cvm::debug())
|
||||
cvm::log("Done calculating gradients of colvar \""+this->name+"\".\n");
|
||||
}
|
||||
|
||||
cvm::decrease_depth();
|
||||
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
@ -1706,12 +1699,13 @@ int colvar::calc_colvar_properties()
|
||||
// Do the same if no simulation is running (eg. VMD postprocessing)
|
||||
if ((cvm::step_relative() == 0 && !after_restart) || x_ext.type() == colvarvalue::type_notset || !cvm::proxy->simulation_running()) {
|
||||
x_ext = x;
|
||||
cvm::log("Initializing extended coordinate to colvar value.\n");
|
||||
if (is_enabled(f_cv_reflecting_lower_boundary) && x_ext < lower_boundary) {
|
||||
cvm::log("Warning: initializing extended coordinate to reflective lower boundary, as colvar value is below.");
|
||||
cvm::log("Warning: initializing extended coordinate to reflective lower boundary, as colvar value is below.\n");
|
||||
x_ext = lower_boundary;
|
||||
}
|
||||
if (is_enabled(f_cv_reflecting_upper_boundary) && x_ext > upper_boundary) {
|
||||
cvm::log("Warning: initializing extended coordinate to reflective upper boundary, as colvar value is above.");
|
||||
cvm::log("Warning: initializing extended coordinate to reflective upper boundary, as colvar value is above.\n");
|
||||
x_ext = upper_boundary;
|
||||
}
|
||||
|
||||
@ -1721,9 +1715,19 @@ int colvar::calc_colvar_properties()
|
||||
// Special case of a repeated timestep (eg. multiple NAMD "run" statements)
|
||||
// revert values of the extended coordinate and velocity prior to latest integration
|
||||
if (cvm::proxy->simulation_running() && cvm::step_relative() == prev_timestep) {
|
||||
// Detect jumps due to discrete changes in coordinates (eg. in replica exchange schemes)
|
||||
cvm::real const jump2 = dist2(x, x_old) / (width*width);
|
||||
if (jump2 > 0.25) {
|
||||
cvm::log("Detected discrete jump in colvar value from "
|
||||
+ cvm::to_str(x_old) + " to " + cvm::to_str(x) + ".\n");
|
||||
cvm::log("Reinitializing extended coordinate to colvar value.\n");
|
||||
x_ext = x;
|
||||
} else {
|
||||
cvm::log("Reinitializing extended coordinate to last value.\n");
|
||||
x_ext = prev_x_ext;
|
||||
v_ext = prev_v_ext;
|
||||
}
|
||||
}
|
||||
// report the restraint center as "value"
|
||||
// These position and velocities come from integration at the _previous timestep_ in update_forces_energy()
|
||||
// But we report values at the beginning of the timestep (value at t=0 on the first timestep)
|
||||
@ -1830,9 +1834,11 @@ void colvar::update_extended_Lagrangian()
|
||||
f += fb_actual;
|
||||
}
|
||||
|
||||
// fr: bias force on extended variable (without harmonic spring), for output in trajectory
|
||||
fr = f;
|
||||
// External force has been scaled for a 1-timestep impulse, scale it back because we will
|
||||
// integrate it with the colvar's own timestep factor
|
||||
|
||||
// External force has been scaled for an inner-timestep impulse (for the back-end integrator)
|
||||
// here we scale it back because this integrator uses only the outer (long) timestep
|
||||
f_ext = f / cvm::real(time_step_factor);
|
||||
|
||||
colvarvalue f_system(fr.type()); // force exterted by the system on the extended DOF
|
||||
@ -1845,15 +1851,14 @@ void colvar::update_extended_Lagrangian()
|
||||
} else {
|
||||
// the total force is applied to the fictitious mass, while the
|
||||
// atoms only feel the harmonic force + wall force
|
||||
// fr: bias force on extended variable (without harmonic spring), for output in trajectory
|
||||
// f_ext: total force on extended variable (including harmonic spring)
|
||||
// f: - initially, external biasing force
|
||||
// - after this code block, colvar force to be applied to atomic coordinates
|
||||
// ie. spring force (fb_actual will be added just below)
|
||||
f_system = (-0.5 * ext_force_k) * this->dist2_lgrad(x_ext, x);
|
||||
f = -1.0 * f_system;
|
||||
// Coupling force is a slow force, to be applied to atomic coords impulse-style
|
||||
// over a single MD timestep
|
||||
// Coupling force will be applied to atomic coords impulse-style
|
||||
// over an inner timestep of the back-end integrator
|
||||
f *= cvm::real(time_step_factor);
|
||||
}
|
||||
f_ext += f_system;
|
||||
@ -1873,34 +1878,57 @@ void colvar::update_extended_Lagrangian()
|
||||
prev_x_ext = x_ext;
|
||||
prev_v_ext = v_ext;
|
||||
|
||||
// leapfrog: starting from x_i, f_i, v_(i-1/2)
|
||||
v_ext += (0.5 * dt) * f_ext / ext_mass;
|
||||
// Because of leapfrog, kinetic energy at time i is approximate
|
||||
// BAOA (GSD) integrator as formulated in https://doi.org/10.1021/acs.jctc.2c00585
|
||||
// starting from x_t, f_t, v_(t-1/2)
|
||||
// Variation: the velocity step is split in two to estimate the kinetic energy at time t
|
||||
// so this is more of a "BBAOA" scheme: a rearranged BAOAB where the second B is deferred
|
||||
// to the next time step for implementation reasons (waiting for the force calculation)
|
||||
|
||||
// [B] Eq. (10a) split into two half-steps
|
||||
// would reduce to leapfrog when gamma = 0 if this was the reported velocity
|
||||
v_ext += 0.5 * dt * f_ext / ext_mass;
|
||||
|
||||
// Kinetic energy at t
|
||||
kinetic_energy = 0.5 * ext_mass * v_ext * v_ext;
|
||||
|
||||
// Potential energy at t
|
||||
potential_energy = 0.5 * ext_force_k * this->dist2(x_ext, x);
|
||||
// leap to v_(i+1/2)
|
||||
|
||||
// Total energy will lag behind position by one timestep
|
||||
// (current kinetic energy is not accessible before the next force calculation)
|
||||
|
||||
v_ext += 0.5 * dt * f_ext / ext_mass;
|
||||
// Final v_ext lags behind x_ext by half a timestep
|
||||
|
||||
// [A] Half step in position (10b)
|
||||
x_ext += dt * v_ext / 2.0;
|
||||
|
||||
// [O] leap to v_(i+1/2) (10c)
|
||||
if (is_enabled(f_cv_Langevin)) {
|
||||
v_ext -= dt * ext_gamma * v_ext;
|
||||
colvarvalue rnd(x);
|
||||
rnd.set_random();
|
||||
v_ext += dt * ext_sigma * rnd / ext_mass;
|
||||
// ext_sigma has been computed at init time according to (10c)
|
||||
v_ext = cvm::exp(- 1.0 * dt * ext_gamma) * v_ext + ext_sigma * rnd / ext_mass;
|
||||
}
|
||||
v_ext += (0.5 * dt) * f_ext / ext_mass;
|
||||
x_ext += dt * v_ext;
|
||||
// [A] Second half step in position (10d)
|
||||
x_ext += dt * v_ext / 2.0;
|
||||
|
||||
cvm::real delta = 0; // Length of overshoot past either reflecting boundary
|
||||
if ((is_enabled(f_cv_reflecting_lower_boundary) && (delta = x_ext - lower_boundary) < 0) ||
|
||||
(is_enabled(f_cv_reflecting_upper_boundary) && (delta = x_ext - upper_boundary) > 0)) {
|
||||
// Reflect arrival position
|
||||
x_ext -= 2.0 * delta;
|
||||
v_ext *= -1.0;
|
||||
if ((is_enabled(f_cv_reflecting_lower_boundary) && (delta = x_ext - lower_boundary) < 0) ||
|
||||
(is_enabled(f_cv_reflecting_upper_boundary) && (delta = x_ext - upper_boundary) > 0)) {
|
||||
// Bounce happened on average at t+1/2 -> reflect velocity at t+1/2
|
||||
v_ext = -0.5 * (prev_v_ext + v_ext);
|
||||
if ((is_enabled(f_cv_reflecting_lower_boundary) && (x_ext - lower_boundary) < 0.0) ||
|
||||
(is_enabled(f_cv_reflecting_upper_boundary) && (x_ext - upper_boundary) > 0.0)) {
|
||||
cvm::error("Error: extended coordinate value " + cvm::to_str(x_ext) + " is still outside boundaries after reflection.\n");
|
||||
}
|
||||
}
|
||||
|
||||
x_ext.apply_constraints();
|
||||
this->wrap(x_ext);
|
||||
|
||||
if (is_enabled(f_cv_external)) {
|
||||
// Colvar value is constrained to the extended value
|
||||
x = x_ext;
|
||||
@ -1914,9 +1942,8 @@ int colvar::end_of_step()
|
||||
if (cvm::debug())
|
||||
cvm::log("End of step for colvar \""+this->name+"\".\n");
|
||||
|
||||
if (is_enabled(f_cv_fdiff_velocity)) {
|
||||
// Used for fdiff_velocity and for detecting jumps for extended Lagrangian colvars
|
||||
x_old = x;
|
||||
}
|
||||
|
||||
if (is_enabled(f_cv_subtract_applied_force)) {
|
||||
f_old = f;
|
||||
@ -2256,44 +2283,65 @@ void colvar::wrap(colvarvalue &x_unwrapped) const
|
||||
|
||||
std::istream & colvar::read_state(std::istream &is)
|
||||
{
|
||||
std::streampos const start_pos = is.tellg();
|
||||
auto const start_pos = is.tellg();
|
||||
|
||||
std::string conf;
|
||||
if ( !(is >> colvarparse::read_block("colvar", &conf)) ) {
|
||||
if ( !(is >> colvarparse::read_block("colvar", &conf)) ||
|
||||
(check_matching_state(conf) != COLVARS_OK) ) {
|
||||
// this is not a colvar block
|
||||
is.clear();
|
||||
is.seekg(start_pos, std::ios::beg);
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
return is;
|
||||
}
|
||||
|
||||
{
|
||||
std::string check_name = "";
|
||||
get_keyval(conf, "name", check_name,
|
||||
std::string(""), colvarparse::parse_silent);
|
||||
if (check_name.size() == 0) {
|
||||
cvm::error("Error: Collective variable in the "
|
||||
"restart file without any identifier.\n", COLVARS_INPUT_ERROR);
|
||||
is.clear();
|
||||
is.seekg(start_pos, std::ios::beg);
|
||||
is.setstate(std::ios::failbit);
|
||||
if (!matching_state) {
|
||||
// No errors reading, but this state is not for this colvar; rewind
|
||||
is.seekg(start_pos);
|
||||
return is;
|
||||
}
|
||||
|
||||
if (set_state_params(conf) != COLVARS_OK) {
|
||||
is.clear();
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
int colvar::check_matching_state(std::string const &conf)
|
||||
{
|
||||
std::string check_name = "";
|
||||
get_keyval(conf, "name", check_name, std::string(""), colvarparse::parse_silent);
|
||||
|
||||
if (check_name.size() == 0) {
|
||||
return cvm::error("Error: Collective variable in the "
|
||||
"state file without any identifier.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if (check_name != name) {
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Ignoring state of colvar \""+check_name+
|
||||
"\": this colvar is named \""+name+"\".\n");
|
||||
}
|
||||
is.seekg(start_pos, std::ios::beg);
|
||||
return is;
|
||||
}
|
||||
matching_state = false;
|
||||
} else {
|
||||
matching_state = true;
|
||||
}
|
||||
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
int colvar::set_state_params(std::string const &conf)
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
if ( !(get_keyval(conf, "x", x, x, colvarparse::parse_silent)) ) {
|
||||
cvm::log("Error: restart file does not contain "
|
||||
error_code |= cvm::error("Error: restart file does not contain "
|
||||
"the value of the colvar \""+
|
||||
name+"\" .\n");
|
||||
name+"\" .\n", COLVARS_INPUT_ERROR);
|
||||
} else {
|
||||
cvm::log("Restarting collective variable \""+name+"\" from value: "+
|
||||
cvm::to_str(x)+"\n");
|
||||
@ -2306,9 +2354,10 @@ std::istream & colvar::read_state(std::istream &is)
|
||||
colvarvalue(x.type()), colvarparse::parse_silent)) ||
|
||||
!(get_keyval(conf, "extended_v", v_ext,
|
||||
colvarvalue(x.type()), colvarparse::parse_silent)) ) {
|
||||
cvm::log("Error: restart file does not contain "
|
||||
error_code |= cvm::error("Error: restart file does not contain "
|
||||
"\"extended_x\" or \"extended_v\" for the colvar \""+
|
||||
name+"\", but you requested \"extendedLagrangian\".\n");
|
||||
name+"\", but you requested \"extendedLagrangian\".\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
x_reported = x_ext;
|
||||
} else {
|
||||
@ -2319,9 +2368,10 @@ std::istream & colvar::read_state(std::istream &is)
|
||||
|
||||
if ( !(get_keyval(conf, "v", v_fdiff,
|
||||
colvarvalue(x.type()), colvarparse::parse_silent)) ) {
|
||||
cvm::log("Error: restart file does not contain "
|
||||
error_code |= cvm::error("Error: restart file does not contain "
|
||||
"the velocity for the colvar \""+
|
||||
name+"\", but you requested \"outputVelocity\".\n");
|
||||
name+"\", but you requested \"outputVelocity\".\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if (is_enabled(f_cv_extended_Lagrangian)) {
|
||||
@ -2331,6 +2381,41 @@ std::istream & colvar::read_state(std::istream &is)
|
||||
}
|
||||
}
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream &colvar::read_state(cvm::memory_stream &is)
|
||||
{
|
||||
auto const start_pos = is.tellg();
|
||||
std::string key, data;
|
||||
if (is >> key) {
|
||||
if (key == "colvar") {
|
||||
// Read a formatted config string, then read the state parameters from it
|
||||
if (is >> data) {
|
||||
if (set_state_params(data) == COLVARS_OK) {
|
||||
return is;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto const error_pos = is.tellg();
|
||||
|
||||
is.clear();
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
|
||||
std::string error_msg("Error: in reading state data for colvar \"" + name + " at position " +
|
||||
cvm::to_str(error_pos) + " in unformatted stream.\n");
|
||||
if (key.size() && key != "colvar") {
|
||||
error_msg += "; the keyword read was \"" + key + "\", but \"colvar\" was expected";
|
||||
}
|
||||
if (data.size()) {
|
||||
error_msg += "; the configuration string read was not recognized";
|
||||
}
|
||||
error_msg += ".\n";
|
||||
cvm::error(error_msg, COLVARS_INPUT_ERROR);
|
||||
return is;
|
||||
}
|
||||
|
||||
@ -2345,7 +2430,7 @@ std::istream & colvar::read_traj(std::istream &is)
|
||||
cvm::log("Error: in reading the value of colvar \""+
|
||||
this->name+"\" from trajectory.\n");
|
||||
is.clear();
|
||||
is.seekg(start_pos, std::ios::beg);
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
return is;
|
||||
}
|
||||
@ -2385,10 +2470,23 @@ std::istream & colvar::read_traj(std::istream &is)
|
||||
|
||||
// ******************** OUTPUT FUNCTIONS ********************
|
||||
|
||||
std::ostream & colvar::write_state(std::ostream &os) {
|
||||
std::ostream & colvar::write_state(std::ostream &os) const
|
||||
{
|
||||
os << "colvar {\n" << get_state_params() << "}\n\n";
|
||||
|
||||
os << "colvar {\n"
|
||||
<< " name " << name << "\n"
|
||||
if (runave_outfile.size() > 0) {
|
||||
cvm::main()->proxy->flush_output_stream(runave_outfile);
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
std::string const colvar::get_state_params() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
||||
os << " name " << name << "\n"
|
||||
<< " x "
|
||||
<< std::setprecision(cvm::cv_prec)
|
||||
<< std::setw(cvm::cv_width)
|
||||
@ -2412,7 +2510,13 @@ std::ostream & colvar::write_state(std::ostream &os) {
|
||||
<< v_reported << "\n";
|
||||
}
|
||||
|
||||
os << "}\n\n";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream & colvar::write_state(cvm::memory_stream &os) const
|
||||
{
|
||||
os << std::string("colvar") << get_state_params();
|
||||
|
||||
if (runave_outfile.size() > 0) {
|
||||
cvm::main()->proxy->flush_output_stream(runave_outfile);
|
||||
@ -2875,14 +2979,11 @@ int colvar::calc_runave()
|
||||
runave_variance *= 1.0 / cvm::real(runave_length-1);
|
||||
|
||||
if (runave_outfile.size() > 0) {
|
||||
std::ostream &runave_os = proxy->output_stream(runave_outfile);
|
||||
runave_os << std::setw(cvm::it_width) << cvm::step_relative()
|
||||
<< " "
|
||||
<< std::setprecision(cvm::cv_prec)
|
||||
<< std::setw(cvm::cv_width)
|
||||
<< runave << " "
|
||||
<< std::setprecision(cvm::cv_prec)
|
||||
<< std::setw(cvm::cv_width)
|
||||
std::ostream &runave_os =
|
||||
proxy->output_stream(runave_outfile, "running average output file");
|
||||
runave_os << std::setw(cvm::it_width) << cvm::step_relative() << " "
|
||||
<< std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width) << runave << " "
|
||||
<< std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
|
||||
<< cvm::sqrt(runave_variance) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,12 +10,11 @@
|
||||
#ifndef COLVAR_H
|
||||
#define COLVAR_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if (__cplusplus >= 201103L)
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#endif
|
||||
#include <list>
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
@ -91,7 +90,7 @@ public:
|
||||
/// calculations, \link colvarbias_abf \endlink, it is used to
|
||||
/// calculate the grid spacing in the direction of this collective
|
||||
/// variable.
|
||||
cvm::real width;
|
||||
cvm::real width = 1.0;
|
||||
|
||||
/// \brief Implementation of the feature list for colvar
|
||||
static std::vector<feature *> cv_features;
|
||||
@ -184,13 +183,13 @@ protected:
|
||||
/// Previous velocity of the restraint center
|
||||
colvarvalue prev_v_ext;
|
||||
/// Mass of the restraint center
|
||||
cvm::real ext_mass;
|
||||
cvm::real ext_mass = 0.0;
|
||||
/// Restraint force constant
|
||||
cvm::real ext_force_k;
|
||||
cvm::real ext_force_k = 0.0;
|
||||
/// Friction coefficient for Langevin extended dynamics
|
||||
cvm::real ext_gamma;
|
||||
cvm::real ext_gamma = 0.0;
|
||||
/// Amplitude of Gaussian white noise for Langevin extended dynamics
|
||||
cvm::real ext_sigma;
|
||||
cvm::real ext_sigma = 0.0;
|
||||
|
||||
/// \brief Applied force on extended DOF, for output (unscaled if using MTS)
|
||||
colvarvalue fr;
|
||||
@ -224,14 +223,14 @@ public:
|
||||
colvarvalue ft;
|
||||
|
||||
/// Period, if this variable is periodic
|
||||
cvm::real period;
|
||||
cvm::real period = 0.0;
|
||||
|
||||
/// Center of wrapping, if this variable is periodic
|
||||
cvm::real wrap_center;
|
||||
cvm::real wrap_center = 0.0;
|
||||
|
||||
/// \brief Expand the boundaries of multiples of width, to keep the
|
||||
/// value always within range
|
||||
bool expand_boundaries;
|
||||
bool expand_boundaries = false;
|
||||
|
||||
/// \brief Location of the lower boundary
|
||||
colvarvalue lower_boundary;
|
||||
@ -252,6 +251,9 @@ public:
|
||||
/// Main init function
|
||||
int init(std::string const &conf);
|
||||
|
||||
/// Populate the map of available CVC types
|
||||
void define_component_types();
|
||||
|
||||
/// Parse the CVC configuration and allocate their data
|
||||
int init_components(std::string const &conf);
|
||||
|
||||
@ -271,17 +273,13 @@ public:
|
||||
virtual int init_dependencies();
|
||||
|
||||
private:
|
||||
/// Parse the CVC configuration for all components of a certain type
|
||||
template<typename def_class_name> int init_components_type(std::string const & conf,
|
||||
char const *def_desc,
|
||||
char const *def_config_key);
|
||||
#if (__cplusplus >= 201103L)
|
||||
/// For the C++11 case, the names of all available components are
|
||||
/// registered in the global map at first, and then the CVC configuration
|
||||
/// is parsed by this function
|
||||
int init_components_type_from_global_map(const std::string& conf,
|
||||
const char* def_config_key);
|
||||
#endif
|
||||
|
||||
/// Declare an available CVC type and its description, register them in the global map
|
||||
template <typename def_class_name>
|
||||
void add_component_type(char const *description, char const *config_key);
|
||||
|
||||
/// Initialize any CVC objects matching the given key
|
||||
int init_components_type(const std::string &conf, const char *config_key);
|
||||
|
||||
public:
|
||||
|
||||
@ -387,10 +385,10 @@ public:
|
||||
protected:
|
||||
|
||||
/// \brief Number of CVC objects with an active flag
|
||||
size_t n_active_cvcs;
|
||||
size_t n_active_cvcs = 0;
|
||||
|
||||
/// Sum of square coefficients for active cvcs
|
||||
cvm::real active_cvc_square_norm;
|
||||
cvm::real active_cvc_square_norm = 0.0;
|
||||
|
||||
/// Update the sum of square coefficients for active cvcs
|
||||
void update_active_cvc_square_norm();
|
||||
@ -460,16 +458,35 @@ public:
|
||||
/// Write a label to the trajectory file (comment line)
|
||||
std::ostream & write_traj_label(std::ostream &os);
|
||||
|
||||
/// Read the collective variable from a restart file
|
||||
/// Read the colvar's state from a formatted input stream
|
||||
std::istream & read_state(std::istream &is);
|
||||
/// Write the collective variable to a restart file
|
||||
std::ostream & write_state(std::ostream &os);
|
||||
|
||||
/// Read the colvar's state from an unformatted input stream
|
||||
cvm::memory_stream & read_state(cvm::memory_stream &is);
|
||||
|
||||
/// Check the name of the bias vs. the given string, set the matching_state flag accordingly
|
||||
int check_matching_state(std::string const &state_conf);
|
||||
|
||||
/// Read the values of colvar mutable data from a string (used by both versions of read_state())
|
||||
int set_state_params(std::string const &state_conf);
|
||||
|
||||
/// Write the state information of this colvar in a block of text, suitable for later parsing
|
||||
std::string const get_state_params() const;
|
||||
|
||||
/// Write the colvar's state to a formatted output stream
|
||||
std::ostream & write_state(std::ostream &os) const;
|
||||
|
||||
/// Write the colvar's state to an unformatted output stream
|
||||
cvm::memory_stream & write_state(cvm::memory_stream &os) const;
|
||||
|
||||
/// Write output files (if defined, e.g. in analysis mode)
|
||||
int write_output_files();
|
||||
|
||||
protected:
|
||||
|
||||
/// Flag used to tell if the state string being read is for this colvar
|
||||
bool matching_state;
|
||||
|
||||
/// Previous value (to calculate velocities during analysis)
|
||||
colvarvalue x_old;
|
||||
|
||||
@ -554,15 +571,15 @@ protected:
|
||||
/// Current value of the running average
|
||||
colvarvalue runave;
|
||||
/// Current value of the square deviation from the running average
|
||||
cvm::real runave_variance;
|
||||
cvm::real runave_variance = 0.0;
|
||||
|
||||
/// Calculate the running average and its standard deviation
|
||||
int calc_runave();
|
||||
|
||||
/// If extended Lagrangian active: colvar kinetic energy
|
||||
cvm::real kinetic_energy;
|
||||
cvm::real kinetic_energy = 0.0;
|
||||
/// If extended Lagrangian active: colvar harmonic potential
|
||||
cvm::real potential_energy;
|
||||
cvm::real potential_energy = 0.0;
|
||||
|
||||
public:
|
||||
|
||||
@ -601,8 +618,9 @@ public:
|
||||
class dihedPC;
|
||||
class alch_lambda;
|
||||
class alch_Flambda;
|
||||
class componentDisabled;
|
||||
class CartesianBasedPath;
|
||||
class aspath;
|
||||
class azpath;
|
||||
class gspath;
|
||||
class gzpath;
|
||||
class linearCombination;
|
||||
@ -626,21 +644,19 @@ public:
|
||||
// components that do not handle any atoms directly
|
||||
class map_total;
|
||||
|
||||
/// getter of the global cvc map
|
||||
#if (__cplusplus >= 201103L)
|
||||
/// A global mapping of cvc names to the cvc constructors
|
||||
static const std::map<std::string, std::function<colvar::cvc* (const std::string& subcv_conf)>>& get_global_cvc_map() {
|
||||
static const std::map<std::string, std::function<colvar::cvc *()>> &get_global_cvc_map()
|
||||
{
|
||||
return global_cvc_map;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \brief function for sorting cvcs by their names
|
||||
static bool compare_cvc(const colvar::cvc* const i, const colvar::cvc* const j);
|
||||
|
||||
protected:
|
||||
|
||||
/// \brief Array of \link colvar::cvc \endlink objects
|
||||
std::vector<cvc *> cvcs;
|
||||
/// Array of components objects
|
||||
std::vector<std::shared_ptr<colvar::cvc>> cvcs;
|
||||
|
||||
/// \brief Flags to enable or disable cvcs at next colvar evaluation
|
||||
std::vector<bool> cvc_flags;
|
||||
@ -671,10 +687,11 @@ protected:
|
||||
double dev_null;
|
||||
#endif
|
||||
|
||||
#if (__cplusplus >= 201103L)
|
||||
/// A global mapping of cvc names to the cvc constructors
|
||||
static std::map<std::string, std::function<colvar::cvc* (const std::string& subcv_conf)>> global_cvc_map;
|
||||
#endif
|
||||
static std::map<std::string, std::function<colvar::cvc *()>> global_cvc_map;
|
||||
|
||||
/// A global mapping of cvc names to the corresponding descriptions
|
||||
static std::map<std::string, std::string> global_cvc_desc_map;
|
||||
|
||||
/// Volmap numeric IDs, one for each CVC (-1 if not available)
|
||||
std::vector<int> volmap_ids_;
|
||||
@ -762,4 +779,3 @@ inline void colvar::reset_bias_force() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,126 +7,84 @@
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
namespace ArithmeticPathCV {
|
||||
|
||||
using std::vector;
|
||||
|
||||
enum path_sz {S, Z};
|
||||
|
||||
template <typename element_type, typename scalar_type, path_sz path_type>
|
||||
template <typename scalar_type>
|
||||
class ArithmeticPathBase {
|
||||
public:
|
||||
ArithmeticPathBase() {}
|
||||
virtual ~ArithmeticPathBase() {}
|
||||
virtual void initialize(size_t p_num_elements, size_t p_total_frames, double p_lambda, const vector<element_type>& p_element, const vector<double>& p_weights);
|
||||
virtual void updateDistanceToReferenceFrames() = 0;
|
||||
virtual void computeValue();
|
||||
virtual void computeDerivatives();
|
||||
virtual void compute();
|
||||
virtual void reComputeLambda(const vector<scalar_type>& rmsd_between_refs);
|
||||
~ArithmeticPathBase() {}
|
||||
void initialize(size_t p_num_elements, size_t p_total_frames, scalar_type p_lambda, const vector<scalar_type>& p_weights);
|
||||
void reComputeLambda(const vector<scalar_type>& rmsd_between_refs);
|
||||
template <typename element_type>
|
||||
void computeValue(const vector<vector<element_type>>& frame_element_distances, scalar_type *s = nullptr, scalar_type *z = nullptr);
|
||||
// can only be called after computeValue() for element-wise derivatives and store derivatives of i-th frame to dsdx and dzdx
|
||||
template <typename element_type>
|
||||
void computeDerivatives(const vector<vector<element_type>>& frame_element_distances, vector<vector<element_type>> *dsdx = nullptr, vector<vector<element_type>> *dzdx = nullptr);
|
||||
protected:
|
||||
scalar_type lambda;
|
||||
vector<scalar_type> weights;
|
||||
vector<scalar_type> squared_weights;
|
||||
size_t num_elements;
|
||||
size_t total_frames;
|
||||
vector< vector<element_type> > frame_element_distances;
|
||||
scalar_type s;
|
||||
scalar_type z;
|
||||
vector<element_type> dsdx;
|
||||
vector<element_type> dzdx;
|
||||
private:
|
||||
// intermediate variables
|
||||
vector<scalar_type> s_numerator_frame;
|
||||
vector<scalar_type> s_denominator_frame;
|
||||
scalar_type numerator_s;
|
||||
scalar_type denominator_s;
|
||||
vector<scalar_type> exponents;
|
||||
scalar_type max_exponent;
|
||||
scalar_type saved_exponent_sum;
|
||||
scalar_type normalization_factor;
|
||||
scalar_type saved_s;
|
||||
};
|
||||
|
||||
template <typename element_type, typename scalar_type, path_sz path_type>
|
||||
void ArithmeticPathBase<element_type, scalar_type, path_type>::initialize(size_t p_num_elements, size_t p_total_frames, double p_lambda, const vector<element_type>& p_element, const vector<double>& p_weights) {
|
||||
template <typename scalar_type>
|
||||
void ArithmeticPathBase<scalar_type>::initialize(size_t p_num_elements, size_t p_total_frames, scalar_type p_lambda, const vector<scalar_type>& p_weights) {
|
||||
lambda = p_lambda;
|
||||
weights = p_weights;
|
||||
for (size_t i = 0; i < p_weights.size(); ++i) squared_weights.push_back(p_weights[i] * p_weights[i]);
|
||||
num_elements = p_num_elements;
|
||||
total_frames = p_total_frames;
|
||||
frame_element_distances.resize(total_frames, p_element);
|
||||
for (size_t i_frame = 0; i_frame < frame_element_distances.size(); ++i_frame) {
|
||||
for (size_t j_elem = 0; j_elem < num_elements; ++j_elem) {
|
||||
frame_element_distances[i_frame][j_elem].reset();
|
||||
}
|
||||
}
|
||||
s = scalar_type(0);
|
||||
z = scalar_type(0);
|
||||
dsdx = p_element;
|
||||
dzdx = p_element;
|
||||
s_numerator_frame.resize(total_frames, scalar_type(0));
|
||||
s_denominator_frame.resize(total_frames, scalar_type(0));
|
||||
numerator_s = scalar_type(0);
|
||||
denominator_s = scalar_type(0);
|
||||
exponents.resize(total_frames);
|
||||
normalization_factor = 1.0 / static_cast<scalar_type>(total_frames - 1);
|
||||
saved_s = scalar_type();
|
||||
saved_exponent_sum = scalar_type();
|
||||
max_exponent = scalar_type();
|
||||
}
|
||||
|
||||
template <typename element_type, typename scalar_type, path_sz path_type>
|
||||
void ArithmeticPathBase<element_type, scalar_type, path_type>::computeValue() {
|
||||
updateDistanceToReferenceFrames();
|
||||
numerator_s = scalar_type(0);
|
||||
denominator_s = scalar_type(0);
|
||||
for (size_t i_frame = 0; i_frame < frame_element_distances.size(); ++i_frame) {
|
||||
scalar_type exponent_tmp = scalar_type(0);
|
||||
template <typename scalar_type>
|
||||
template <typename element_type>
|
||||
void ArithmeticPathBase<scalar_type>::computeValue(
|
||||
const vector<vector<element_type>>& frame_element_distances,
|
||||
scalar_type *s, scalar_type *z)
|
||||
{
|
||||
for (size_t i_frame = 0; i_frame < total_frames; ++i_frame) {
|
||||
scalar_type exponent_tmp = scalar_type();
|
||||
for (size_t j_elem = 0; j_elem < num_elements; ++j_elem) {
|
||||
exponent_tmp += weights[j_elem] * frame_element_distances[i_frame][j_elem] * weights[j_elem] * frame_element_distances[i_frame][j_elem];
|
||||
exponent_tmp += squared_weights[j_elem] * frame_element_distances[i_frame][j_elem] * frame_element_distances[i_frame][j_elem];
|
||||
}
|
||||
exponent_tmp = exponent_tmp * -1.0 * lambda;
|
||||
// prevent underflow if the argument of cvm::exp is less than -708.4
|
||||
if (exponent_tmp > -708.4) {
|
||||
exponent_tmp = cvm::exp(exponent_tmp);
|
||||
} else {
|
||||
exponent_tmp = 0;
|
||||
exponents[i_frame] = exponent_tmp * -1.0 * lambda;
|
||||
if (i_frame == 0 || exponents[i_frame] > max_exponent) max_exponent = exponents[i_frame];
|
||||
}
|
||||
numerator_s += static_cast<scalar_type>(i_frame) * exponent_tmp;
|
||||
denominator_s += exponent_tmp;
|
||||
s_numerator_frame[i_frame] = static_cast<scalar_type>(i_frame) * exponent_tmp;
|
||||
s_denominator_frame[i_frame] = exponent_tmp;
|
||||
scalar_type log_sum_exp_0 = scalar_type();
|
||||
scalar_type log_sum_exp_1 = scalar_type();
|
||||
for (size_t i_frame = 0; i_frame < total_frames; ++i_frame) {
|
||||
exponents[i_frame] = cvm::exp(exponents[i_frame] - max_exponent);
|
||||
log_sum_exp_0 += exponents[i_frame];
|
||||
log_sum_exp_1 += i_frame * exponents[i_frame];
|
||||
}
|
||||
s = numerator_s / denominator_s * normalization_factor;
|
||||
z = -1.0 / lambda * cvm::logn(denominator_s);
|
||||
}
|
||||
|
||||
template <typename element_type, typename scalar_type, path_sz path_type>
|
||||
void ArithmeticPathBase<element_type, scalar_type, path_type>::compute() {
|
||||
computeValue();
|
||||
computeDerivatives();
|
||||
}
|
||||
|
||||
template <typename element_type, typename scalar_type, path_sz path_type>
|
||||
void ArithmeticPathBase<element_type, scalar_type, path_type>::computeDerivatives() {
|
||||
for (size_t j_elem = 0; j_elem < num_elements; ++j_elem) {
|
||||
element_type dsdxj_numerator_part1(dsdx[j_elem]);
|
||||
element_type dsdxj_numerator_part2(dsdx[j_elem]);
|
||||
element_type dzdxj_numerator(dsdx[j_elem]);
|
||||
dsdxj_numerator_part1.reset();
|
||||
dsdxj_numerator_part2.reset();
|
||||
dzdxj_numerator.reset();
|
||||
for (size_t i_frame = 0; i_frame < frame_element_distances.size(); ++i_frame) {
|
||||
element_type derivative_tmp = -2.0 * lambda * weights[j_elem] * weights[j_elem] * frame_element_distances[i_frame][j_elem];
|
||||
dsdxj_numerator_part1 += s_numerator_frame[i_frame] * derivative_tmp;
|
||||
dsdxj_numerator_part2 += s_denominator_frame[i_frame] * derivative_tmp;
|
||||
dzdxj_numerator += s_denominator_frame[i_frame] * derivative_tmp;
|
||||
saved_exponent_sum = log_sum_exp_0;
|
||||
log_sum_exp_0 = max_exponent + cvm::logn(log_sum_exp_0);
|
||||
log_sum_exp_1 = max_exponent + cvm::logn(log_sum_exp_1);
|
||||
saved_s = normalization_factor * cvm::exp(log_sum_exp_1 - log_sum_exp_0);
|
||||
if (s != nullptr) {
|
||||
*s = saved_s;
|
||||
}
|
||||
dsdxj_numerator_part1 *= denominator_s;
|
||||
dsdxj_numerator_part2 *= numerator_s;
|
||||
if ((dsdxj_numerator_part1 - dsdxj_numerator_part2).norm() < std::numeric_limits<scalar_type>::min()) {
|
||||
dsdx[j_elem] = 0;
|
||||
} else {
|
||||
dsdx[j_elem] = (dsdxj_numerator_part1 - dsdxj_numerator_part2) / (denominator_s * denominator_s) * normalization_factor;
|
||||
}
|
||||
dzdx[j_elem] = -1.0 / lambda * dzdxj_numerator / denominator_s;
|
||||
if (z != nullptr) {
|
||||
*z = -1.0 / lambda * log_sum_exp_0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename element_type, typename scalar_type, path_sz path_type>
|
||||
void ArithmeticPathBase<element_type, scalar_type, path_type>::reComputeLambda(const vector<scalar_type>& rmsd_between_refs) {
|
||||
template <typename scalar_type>
|
||||
void ArithmeticPathBase<scalar_type>::reComputeLambda(const vector<scalar_type>& rmsd_between_refs) {
|
||||
scalar_type mean_square_displacements = 0.0;
|
||||
for (size_t i_frame = 1; i_frame < total_frames; ++i_frame) {
|
||||
cvm::log(std::string("Distance between frame ") + cvm::to_str(i_frame) + " and " + cvm::to_str(i_frame + 1) + " is " + cvm::to_str(rmsd_between_refs[i_frame - 1]) + std::string("\n"));
|
||||
@ -135,6 +93,45 @@ void ArithmeticPathBase<element_type, scalar_type, path_type>::reComputeLambda(c
|
||||
mean_square_displacements /= scalar_type(total_frames - 1);
|
||||
lambda = 1.0 / mean_square_displacements;
|
||||
}
|
||||
|
||||
// frame-wise derivatives for frames using optimal rotation
|
||||
template <typename scalar_type>
|
||||
template <typename element_type>
|
||||
void ArithmeticPathBase<scalar_type>::computeDerivatives(
|
||||
const vector<vector<element_type>>& frame_element_distances,
|
||||
vector<vector<element_type>> *dsdx,
|
||||
vector<vector<element_type>> *dzdx)
|
||||
{
|
||||
vector<scalar_type> softmax_out, tmps;
|
||||
softmax_out.reserve(total_frames);
|
||||
tmps.reserve(total_frames);
|
||||
for (size_t i_frame = 0; i_frame < total_frames; ++i_frame) {
|
||||
softmax_out.push_back(exponents[i_frame] / saved_exponent_sum);
|
||||
tmps.push_back(
|
||||
(static_cast<scalar_type>(i_frame) -
|
||||
static_cast<scalar_type>(total_frames - 1) * saved_s) *
|
||||
normalization_factor);
|
||||
}
|
||||
if (dsdx != nullptr) {
|
||||
for (size_t i_frame = 0; i_frame < total_frames; ++i_frame) {
|
||||
for (size_t j_elem = 0; j_elem < num_elements; ++j_elem) {
|
||||
(*dsdx)[i_frame][j_elem] =
|
||||
-2.0 * squared_weights[j_elem] * lambda *
|
||||
frame_element_distances[i_frame][j_elem] *
|
||||
softmax_out[i_frame] * tmps[i_frame];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dzdx != nullptr) {
|
||||
for (size_t i_frame = 0; i_frame < total_frames; ++i_frame) {
|
||||
for (size_t j_elem = 0; j_elem < num_elements; ++j_elem) {
|
||||
(*dzdx)[i_frame][j_elem] =
|
||||
2.0 * squared_weights[j_elem] * softmax_out[i_frame] *
|
||||
frame_element_distances[i_frame][j_elem];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ARITHMETICPATHCV_H
|
||||
|
||||
@ -8,12 +8,13 @@
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
namespace GeometricPathCV {
|
||||
|
||||
@ -171,10 +172,14 @@ void GeometricPathBase<element_type, scalar_type, path_type>::determineClosestFr
|
||||
sign = -1;
|
||||
}
|
||||
if (cvm::fabs(static_cast<long>(frame_index[0]) - static_cast<long>(frame_index[1])) > 1) {
|
||||
std::cout << "Warning: Geometrical pathCV relies on the assumption that the second closest frame is the neighbouring frame\n";
|
||||
std::cout << " Please check your configuration or increase restraint on z(σ)\n";
|
||||
std::string message(
|
||||
"Warning: Geometrical pathCV relies on the assumption that the second closest frame is "
|
||||
"the neighbouring frame\n"
|
||||
" Please check your configuration or increase restraint on z(σ)\n");
|
||||
for (size_t i_frame = 0; i_frame < frame_index.size(); ++i_frame) {
|
||||
std::cout << "Frame index: " << frame_index[i_frame] << " ; optimal RMSD = " << frame_distances[frame_index[i_frame]] << "\n";
|
||||
message += "Frame index: " + cvm::to_str(frame_index[i_frame]) +
|
||||
" ; optimal RMSD = " + cvm::to_str(frame_distances[frame_index[i_frame]]) +
|
||||
"\n";
|
||||
}
|
||||
}
|
||||
min_frame_index_1 = frame_index[0]; // s_m
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#if (__cplusplus >= 201103L)
|
||||
#include "colvar_neuralnetworkcompute.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvarproxy.h"
|
||||
@ -272,9 +271,12 @@ std::vector<std::vector<double>> neuralNetworkCompute::multiply_matrix(const std
|
||||
const size_t t = B[0].size();
|
||||
std::vector<std::vector<double>> C(m, std::vector<double>(t, 0.0));
|
||||
for (size_t i = 0; i < m; ++i) {
|
||||
for (size_t j = 0; j < t; ++j) {
|
||||
for (size_t k = 0; k < n; ++k) {
|
||||
C[i][j] += A[i][k] * B[k][j];
|
||||
const auto tmp = A[i][k];
|
||||
auto& C_i = C[i];
|
||||
auto& B_k = B[k];
|
||||
for (size_t j = 0; j < t; ++j) {
|
||||
C_i[j] += tmp * B_k[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -306,5 +308,3 @@ void neuralNetworkCompute::compute() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
// If you wish to distribute your changes, please submit them to the
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
#if (__cplusplus >= 201103L)
|
||||
#ifndef NEURALNETWORKCOMPUTE_H
|
||||
#define NEURALNETWORKCOMPUTE_H
|
||||
|
||||
@ -145,4 +144,3 @@ public:
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
627
lib/colvars/colvar_rotation_derivative.h
Normal file
627
lib/colvars/colvar_rotation_derivative.h
Normal file
@ -0,0 +1,627 @@
|
||||
#ifndef COLVAR_ROTATION_DERIVATIVE
|
||||
#define COLVAR_ROTATION_DERIVATIVE
|
||||
|
||||
#include "colvartypes.h"
|
||||
#include <type_traits>
|
||||
#include <cstring>
|
||||
|
||||
/// \brief Helper function for loading the ia-th atom in the vector pos to x, y and z (C++11 SFINAE is used)
|
||||
template <typename T, typename std::enable_if<std::is_same<T, cvm::atom_pos>::value, bool>::type = true>
|
||||
inline void read_atom_coord(
|
||||
size_t ia, const std::vector<T>& pos,
|
||||
cvm::real* x, cvm::real* y, cvm::real* z) {
|
||||
*x = pos[ia].x;
|
||||
*y = pos[ia].y;
|
||||
*z = pos[ia].z;
|
||||
}
|
||||
|
||||
template <typename T, typename std::enable_if<std::is_same<T, cvm::atom>::value, bool>::type = true>
|
||||
inline void read_atom_coord(
|
||||
size_t ia, const std::vector<T>& pos,
|
||||
cvm::real* x, cvm::real* y, cvm::real* z) {
|
||||
*x = pos[ia].pos.x;
|
||||
*y = pos[ia].pos.y;
|
||||
*z = pos[ia].pos.z;
|
||||
}
|
||||
|
||||
/// \brief Helper enum class for specifying options in rotation_derivative::prepare_derivative
|
||||
enum class rotation_derivative_dldq {
|
||||
/// Require the derivative of the leading eigenvalue with respect to the atom coordinats
|
||||
use_dl = 1 << 0,
|
||||
/// Require the derivative of the leading eigenvector with respect to the atom coordinats
|
||||
use_dq = 1 << 1
|
||||
};
|
||||
|
||||
inline constexpr rotation_derivative_dldq operator|(rotation_derivative_dldq Lhs, rotation_derivative_dldq Rhs) {
|
||||
return static_cast<rotation_derivative_dldq>(
|
||||
static_cast<std::underlying_type<rotation_derivative_dldq>::type>(Lhs) |
|
||||
static_cast<std::underlying_type<rotation_derivative_dldq>::type>(Rhs));
|
||||
}
|
||||
|
||||
inline constexpr bool operator&(rotation_derivative_dldq Lhs, rotation_derivative_dldq Rhs)
|
||||
{
|
||||
return (static_cast<std::underlying_type<rotation_derivative_dldq>::type>(Lhs) &
|
||||
static_cast<std::underlying_type<rotation_derivative_dldq>::type>(Rhs));
|
||||
}
|
||||
|
||||
/// \brief Helper class for calculating the derivative of rotation
|
||||
template <typename T1, typename T2>
|
||||
struct rotation_derivative {
|
||||
static_assert(std::is_same<T1, cvm::atom_pos>::value || std::is_same<T1, cvm::atom>::value,
|
||||
"class template rotation_derivative only supports cvm::atom_pos or cvm::atom types.");
|
||||
static_assert(std::is_same<T2, cvm::atom_pos>::value || std::is_same<T2, cvm::atom>::value,
|
||||
"class template rotation_derivative only supports cvm::atom_pos or cvm::atom types.");
|
||||
/// \brief Reference to the rotation
|
||||
const cvm::rotation &m_rot;
|
||||
/// \brief Reference to the atom positions of group 1
|
||||
const std::vector<T1> &m_pos1;
|
||||
/// \brief Reference to the atom positions of group 2
|
||||
const std::vector<T2> &m_pos2;
|
||||
/// \brief Temporary variable that will be updated if prepare_derivative called
|
||||
cvm::real tmp_Q0Q0[4][4];
|
||||
cvm::real tmp_Q0Q0_L[4][4][4];
|
||||
/*! @brief Constructor of the cvm::rotation::derivative class
|
||||
* @param[in] rot The cvm::rotation object (must have called
|
||||
* `calc_optimal_rotation` before calling
|
||||
* `calc_derivative_wrt_group1` and
|
||||
* `calc_derivative_wrt_group2`)
|
||||
* @param[in] pos1 The atom positions of group 1
|
||||
* @param[in] pos2 The atom positions of group 2
|
||||
*/
|
||||
rotation_derivative(
|
||||
const cvm::rotation &rot,
|
||||
const std::vector<T1> &pos1,
|
||||
const std::vector<T2> &pos2):
|
||||
m_rot(rot), m_pos1(pos1), m_pos2(pos2) {};
|
||||
/*! @brief This function must be called before `calc_derivative_wrt_group1`
|
||||
* and `calc_derivative_wrt_group2` in order to prepare the tmp_Q0Q0
|
||||
* and tmp_Q0Q0_L.
|
||||
* @param[in] require_dl_dq Require the calculation of the derivatives of L or/and Q
|
||||
* with respect to atoms.
|
||||
*/
|
||||
void prepare_derivative(rotation_derivative_dldq require_dl_dq) {
|
||||
if (require_dl_dq & rotation_derivative_dldq::use_dl) {
|
||||
const auto &Q0 = m_rot.S_eigvec[0];
|
||||
tmp_Q0Q0[0][0] = Q0[0] * Q0[0];
|
||||
tmp_Q0Q0[0][1] = Q0[0] * Q0[1];
|
||||
tmp_Q0Q0[0][2] = Q0[0] * Q0[2];
|
||||
tmp_Q0Q0[0][3] = Q0[0] * Q0[3];
|
||||
tmp_Q0Q0[1][0] = Q0[1] * Q0[0];
|
||||
tmp_Q0Q0[1][1] = Q0[1] * Q0[1];
|
||||
tmp_Q0Q0[1][2] = Q0[1] * Q0[2];
|
||||
tmp_Q0Q0[1][3] = Q0[1] * Q0[3];
|
||||
tmp_Q0Q0[2][0] = Q0[2] * Q0[0];
|
||||
tmp_Q0Q0[2][1] = Q0[2] * Q0[1];
|
||||
tmp_Q0Q0[2][2] = Q0[2] * Q0[2];
|
||||
tmp_Q0Q0[2][3] = Q0[2] * Q0[3];
|
||||
tmp_Q0Q0[3][0] = Q0[3] * Q0[0];
|
||||
tmp_Q0Q0[3][1] = Q0[3] * Q0[1];
|
||||
tmp_Q0Q0[3][2] = Q0[3] * Q0[2];
|
||||
tmp_Q0Q0[3][3] = Q0[3] * Q0[3];
|
||||
}
|
||||
if (require_dl_dq & rotation_derivative_dldq::use_dq) {
|
||||
const auto &Q0 = m_rot.S_eigvec[0];
|
||||
const auto &Q1 = m_rot.S_eigvec[1];
|
||||
const auto &Q2 = m_rot.S_eigvec[2];
|
||||
const auto &Q3 = m_rot.S_eigvec[3];
|
||||
cvm::real const L0 = m_rot.S_eigval[0];
|
||||
cvm::real const L1 = m_rot.S_eigval[1];
|
||||
cvm::real const L2 = m_rot.S_eigval[2];
|
||||
cvm::real const L3 = m_rot.S_eigval[3];
|
||||
|
||||
tmp_Q0Q0_L[0][0][0] = (Q1[0] * Q0[0]) / (L0-L1) * Q1[0] +
|
||||
(Q2[0] * Q0[0]) / (L0-L2) * Q2[0] +
|
||||
(Q3[0] * Q0[0]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][0][0] = (Q1[0] * Q0[0]) / (L0-L1) * Q1[1] +
|
||||
(Q2[0] * Q0[0]) / (L0-L2) * Q2[1] +
|
||||
(Q3[0] * Q0[0]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][0][0] = (Q1[0] * Q0[0]) / (L0-L1) * Q1[2] +
|
||||
(Q2[0] * Q0[0]) / (L0-L2) * Q2[2] +
|
||||
(Q3[0] * Q0[0]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][0][0] = (Q1[0] * Q0[0]) / (L0-L1) * Q1[3] +
|
||||
(Q2[0] * Q0[0]) / (L0-L2) * Q2[3] +
|
||||
(Q3[0] * Q0[0]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][0][1] = (Q1[0] * Q0[1]) / (L0-L1) * Q1[0] +
|
||||
(Q2[0] * Q0[1]) / (L0-L2) * Q2[0] +
|
||||
(Q3[0] * Q0[1]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][0][1] = (Q1[0] * Q0[1]) / (L0-L1) * Q1[1] +
|
||||
(Q2[0] * Q0[1]) / (L0-L2) * Q2[1] +
|
||||
(Q3[0] * Q0[1]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][0][1] = (Q1[0] * Q0[1]) / (L0-L1) * Q1[2] +
|
||||
(Q2[0] * Q0[1]) / (L0-L2) * Q2[2] +
|
||||
(Q3[0] * Q0[1]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][0][1] = (Q1[0] * Q0[1]) / (L0-L1) * Q1[3] +
|
||||
(Q2[0] * Q0[1]) / (L0-L2) * Q2[3] +
|
||||
(Q3[0] * Q0[1]) / (L0-L3) * Q3[3];
|
||||
|
||||
|
||||
tmp_Q0Q0_L[0][0][2] = (Q1[0] * Q0[2]) / (L0-L1) * Q1[0] +
|
||||
(Q2[0] * Q0[2]) / (L0-L2) * Q2[0] +
|
||||
(Q3[0] * Q0[2]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][0][2] = (Q1[0] * Q0[2]) / (L0-L1) * Q1[1] +
|
||||
(Q2[0] * Q0[2]) / (L0-L2) * Q2[1] +
|
||||
(Q3[0] * Q0[2]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][0][2] = (Q1[0] * Q0[2]) / (L0-L1) * Q1[2] +
|
||||
(Q2[0] * Q0[2]) / (L0-L2) * Q2[2] +
|
||||
(Q3[0] * Q0[2]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][0][2] = (Q1[0] * Q0[2]) / (L0-L1) * Q1[3] +
|
||||
(Q2[0] * Q0[2]) / (L0-L2) * Q2[3] +
|
||||
(Q3[0] * Q0[2]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][0][3] = (Q1[0] * Q0[3]) / (L0-L1) * Q1[0] +
|
||||
(Q2[0] * Q0[3]) / (L0-L2) * Q2[0] +
|
||||
(Q3[0] * Q0[3]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][0][3] = (Q1[0] * Q0[3]) / (L0-L1) * Q1[1] +
|
||||
(Q2[0] * Q0[3]) / (L0-L2) * Q2[1] +
|
||||
(Q3[0] * Q0[3]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][0][3] = (Q1[0] * Q0[3]) / (L0-L1) * Q1[2] +
|
||||
(Q2[0] * Q0[3]) / (L0-L2) * Q2[2] +
|
||||
(Q3[0] * Q0[3]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][0][3] = (Q1[0] * Q0[3]) / (L0-L1) * Q1[3] +
|
||||
(Q2[0] * Q0[3]) / (L0-L2) * Q2[3] +
|
||||
(Q3[0] * Q0[3]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][1][0] = (Q1[1] * Q0[0]) / (L0-L1) * Q1[0] +
|
||||
(Q2[1] * Q0[0]) / (L0-L2) * Q2[0] +
|
||||
(Q3[1] * Q0[0]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][1][0] = (Q1[1] * Q0[0]) / (L0-L1) * Q1[1] +
|
||||
(Q2[1] * Q0[0]) / (L0-L2) * Q2[1] +
|
||||
(Q3[1] * Q0[0]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][1][0] = (Q1[1] * Q0[0]) / (L0-L1) * Q1[2] +
|
||||
(Q2[1] * Q0[0]) / (L0-L2) * Q2[2] +
|
||||
(Q3[1] * Q0[0]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][1][0] = (Q1[1] * Q0[0]) / (L0-L1) * Q1[3] +
|
||||
(Q2[1] * Q0[0]) / (L0-L2) * Q2[3] +
|
||||
(Q3[1] * Q0[0]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][1][1] = (Q1[1] * Q0[1]) / (L0-L1) * Q1[0] +
|
||||
(Q2[1] * Q0[1]) / (L0-L2) * Q2[0] +
|
||||
(Q3[1] * Q0[1]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][1][1] = (Q1[1] * Q0[1]) / (L0-L1) * Q1[1] +
|
||||
(Q2[1] * Q0[1]) / (L0-L2) * Q2[1] +
|
||||
(Q3[1] * Q0[1]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][1][1] = (Q1[1] * Q0[1]) / (L0-L1) * Q1[2] +
|
||||
(Q2[1] * Q0[1]) / (L0-L2) * Q2[2] +
|
||||
(Q3[1] * Q0[1]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][1][1] = (Q1[1] * Q0[1]) / (L0-L1) * Q1[3] +
|
||||
(Q2[1] * Q0[1]) / (L0-L2) * Q2[3] +
|
||||
(Q3[1] * Q0[1]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][1][2] = (Q1[1] * Q0[2]) / (L0-L1) * Q1[0] +
|
||||
(Q2[1] * Q0[2]) / (L0-L2) * Q2[0] +
|
||||
(Q3[1] * Q0[2]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][1][2] = (Q1[1] * Q0[2]) / (L0-L1) * Q1[1] +
|
||||
(Q2[1] * Q0[2]) / (L0-L2) * Q2[1] +
|
||||
(Q3[1] * Q0[2]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][1][2] = (Q1[1] * Q0[2]) / (L0-L1) * Q1[2] +
|
||||
(Q2[1] * Q0[2]) / (L0-L2) * Q2[2] +
|
||||
(Q3[1] * Q0[2]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][1][2] = (Q1[1] * Q0[2]) / (L0-L1) * Q1[3] +
|
||||
(Q2[1] * Q0[2]) / (L0-L2) * Q2[3] +
|
||||
(Q3[1] * Q0[2]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][1][3] = (Q1[1] * Q0[3]) / (L0-L1) * Q1[0] +
|
||||
(Q2[1] * Q0[3]) / (L0-L2) * Q2[0] +
|
||||
(Q3[1] * Q0[3]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][1][3] = (Q1[1] * Q0[3]) / (L0-L1) * Q1[1] +
|
||||
(Q2[1] * Q0[3]) / (L0-L2) * Q2[1] +
|
||||
(Q3[1] * Q0[3]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][1][3] = (Q1[1] * Q0[3]) / (L0-L1) * Q1[2] +
|
||||
(Q2[1] * Q0[3]) / (L0-L2) * Q2[2] +
|
||||
(Q3[1] * Q0[3]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][1][3] = (Q1[1] * Q0[3]) / (L0-L1) * Q1[3] +
|
||||
(Q2[1] * Q0[3]) / (L0-L2) * Q2[3] +
|
||||
(Q3[1] * Q0[3]) / (L0-L3) * Q3[3];
|
||||
|
||||
|
||||
tmp_Q0Q0_L[0][2][0] = (Q1[2] * Q0[0]) / (L0-L1) * Q1[0] +
|
||||
(Q2[2] * Q0[0]) / (L0-L2) * Q2[0] +
|
||||
(Q3[2] * Q0[0]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][2][0] = (Q1[2] * Q0[0]) / (L0-L1) * Q1[1] +
|
||||
(Q2[2] * Q0[0]) / (L0-L2) * Q2[1] +
|
||||
(Q3[2] * Q0[0]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][2][0] = (Q1[2] * Q0[0]) / (L0-L1) * Q1[2] +
|
||||
(Q2[2] * Q0[0]) / (L0-L2) * Q2[2] +
|
||||
(Q3[2] * Q0[0]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][2][0] = (Q1[2] * Q0[0]) / (L0-L1) * Q1[3] +
|
||||
(Q2[2] * Q0[0]) / (L0-L2) * Q2[3] +
|
||||
(Q3[2] * Q0[0]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][2][1] = (Q1[2] * Q0[1]) / (L0-L1) * Q1[0] +
|
||||
(Q2[2] * Q0[1]) / (L0-L2) * Q2[0] +
|
||||
(Q3[2] * Q0[1]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][2][1] = (Q1[2] * Q0[1]) / (L0-L1) * Q1[1] +
|
||||
(Q2[2] * Q0[1]) / (L0-L2) * Q2[1] +
|
||||
(Q3[2] * Q0[1]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][2][1] = (Q1[2] * Q0[1]) / (L0-L1) * Q1[2] +
|
||||
(Q2[2] * Q0[1]) / (L0-L2) * Q2[2] +
|
||||
(Q3[2] * Q0[1]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][2][1] = (Q1[2] * Q0[1]) / (L0-L1) * Q1[3] +
|
||||
(Q2[2] * Q0[1]) / (L0-L2) * Q2[3] +
|
||||
(Q3[2] * Q0[1]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][2][2] = (Q1[2] * Q0[2]) / (L0-L1) * Q1[0] +
|
||||
(Q2[2] * Q0[2]) / (L0-L2) * Q2[0] +
|
||||
(Q3[2] * Q0[2]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][2][2] = (Q1[2] * Q0[2]) / (L0-L1) * Q1[1] +
|
||||
(Q2[2] * Q0[2]) / (L0-L2) * Q2[1] +
|
||||
(Q3[2] * Q0[2]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][2][2] = (Q1[2] * Q0[2]) / (L0-L1) * Q1[2] +
|
||||
(Q2[2] * Q0[2]) / (L0-L2) * Q2[2] +
|
||||
(Q3[2] * Q0[2]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][2][2] = (Q1[2] * Q0[2]) / (L0-L1) * Q1[3] +
|
||||
(Q2[2] * Q0[2]) / (L0-L2) * Q2[3] +
|
||||
(Q3[2] * Q0[2]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][2][3] = (Q1[2] * Q0[3]) / (L0-L1) * Q1[0] +
|
||||
(Q2[2] * Q0[3]) / (L0-L2) * Q2[0] +
|
||||
(Q3[2] * Q0[3]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][2][3] = (Q1[2] * Q0[3]) / (L0-L1) * Q1[1] +
|
||||
(Q2[2] * Q0[3]) / (L0-L2) * Q2[1] +
|
||||
(Q3[2] * Q0[3]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][2][3] = (Q1[2] * Q0[3]) / (L0-L1) * Q1[2] +
|
||||
(Q2[2] * Q0[3]) / (L0-L2) * Q2[2] +
|
||||
(Q3[2] * Q0[3]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][2][3] = (Q1[2] * Q0[3]) / (L0-L1) * Q1[3] +
|
||||
(Q2[2] * Q0[3]) / (L0-L2) * Q2[3] +
|
||||
(Q3[2] * Q0[3]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][3][0] = (Q1[3] * Q0[0]) / (L0-L1) * Q1[0] +
|
||||
(Q2[3] * Q0[0]) / (L0-L2) * Q2[0] +
|
||||
(Q3[3] * Q0[0]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][3][0] = (Q1[3] * Q0[0]) / (L0-L1) * Q1[1] +
|
||||
(Q2[3] * Q0[0]) / (L0-L2) * Q2[1] +
|
||||
(Q3[3] * Q0[0]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][3][0] = (Q1[3] * Q0[0]) / (L0-L1) * Q1[2] +
|
||||
(Q2[3] * Q0[0]) / (L0-L2) * Q2[2] +
|
||||
(Q3[3] * Q0[0]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][3][0] = (Q1[3] * Q0[0]) / (L0-L1) * Q1[3] +
|
||||
(Q2[3] * Q0[0]) / (L0-L2) * Q2[3] +
|
||||
(Q3[3] * Q0[0]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][3][1] = (Q1[3] * Q0[1]) / (L0-L1) * Q1[0] +
|
||||
(Q2[3] * Q0[1]) / (L0-L2) * Q2[0] +
|
||||
(Q3[3] * Q0[1]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][3][1] = (Q1[3] * Q0[1]) / (L0-L1) * Q1[1] +
|
||||
(Q2[3] * Q0[1]) / (L0-L2) * Q2[1] +
|
||||
(Q3[3] * Q0[1]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][3][1] = (Q1[3] * Q0[1]) / (L0-L1) * Q1[2] +
|
||||
(Q2[3] * Q0[1]) / (L0-L2) * Q2[2] +
|
||||
(Q3[3] * Q0[1]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][3][1] = (Q1[3] * Q0[1]) / (L0-L1) * Q1[3] +
|
||||
(Q2[3] * Q0[1]) / (L0-L2) * Q2[3] +
|
||||
(Q3[3] * Q0[1]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][3][2] = (Q1[3] * Q0[2]) / (L0-L1) * Q1[0] +
|
||||
(Q2[3] * Q0[2]) / (L0-L2) * Q2[0] +
|
||||
(Q3[3] * Q0[2]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][3][2] = (Q1[3] * Q0[2]) / (L0-L1) * Q1[1] +
|
||||
(Q2[3] * Q0[2]) / (L0-L2) * Q2[1] +
|
||||
(Q3[3] * Q0[2]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][3][2] = (Q1[3] * Q0[2]) / (L0-L1) * Q1[2] +
|
||||
(Q2[3] * Q0[2]) / (L0-L2) * Q2[2] +
|
||||
(Q3[3] * Q0[2]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][3][2] = (Q1[3] * Q0[2]) / (L0-L1) * Q1[3] +
|
||||
(Q2[3] * Q0[2]) / (L0-L2) * Q2[3] +
|
||||
(Q3[3] * Q0[2]) / (L0-L3) * Q3[3];
|
||||
|
||||
tmp_Q0Q0_L[0][3][3] = (Q1[3] * Q0[3]) / (L0-L1) * Q1[0] +
|
||||
(Q2[3] * Q0[3]) / (L0-L2) * Q2[0] +
|
||||
(Q3[3] * Q0[3]) / (L0-L3) * Q3[0];
|
||||
tmp_Q0Q0_L[1][3][3] = (Q1[3] * Q0[3]) / (L0-L1) * Q1[1] +
|
||||
(Q2[3] * Q0[3]) / (L0-L2) * Q2[1] +
|
||||
(Q3[3] * Q0[3]) / (L0-L3) * Q3[1];
|
||||
tmp_Q0Q0_L[2][3][3] = (Q1[3] * Q0[3]) / (L0-L1) * Q1[2] +
|
||||
(Q2[3] * Q0[3]) / (L0-L2) * Q2[2] +
|
||||
(Q3[3] * Q0[3]) / (L0-L3) * Q3[2];
|
||||
tmp_Q0Q0_L[3][3][3] = (Q1[3] * Q0[3]) / (L0-L1) * Q1[3] +
|
||||
(Q2[3] * Q0[3]) / (L0-L2) * Q2[3] +
|
||||
(Q3[3] * Q0[3]) / (L0-L3) * Q3[3];
|
||||
}
|
||||
}
|
||||
/*! @brief Actual implementation of the derivative calculation
|
||||
* @param[in] ds The derivative of matrix S with respect to an atom of
|
||||
* either group 1 or group 2
|
||||
* @param[out] dl0_out The output of derivative of L
|
||||
* @param[out] dq0_out The output of derivative of Q
|
||||
* @param[out] ds_out The output of derivative of overlap matrix S
|
||||
*/
|
||||
void calc_derivative_impl(
|
||||
const cvm::rvector (&ds)[4][4],
|
||||
cvm::rvector* const dl0_out,
|
||||
cvm::vector1d<cvm::rvector>* const dq0_out,
|
||||
cvm::matrix2d<cvm::rvector>* const ds_out) const {
|
||||
if (ds_out != nullptr) {
|
||||
// this code path is for debug_gradients, so not necessary to unroll the loop
|
||||
*ds_out = cvm::matrix2d<cvm::rvector>(4, 4);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
(*ds_out)[i][j] = ds[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dl0_out != nullptr) {
|
||||
/* manually loop unrolling of the following loop:
|
||||
dl0_1.reset();
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
dl0_1 += Q0[i] * ds_1[i][j] * Q0[j];
|
||||
}
|
||||
}
|
||||
*/
|
||||
*dl0_out = tmp_Q0Q0[0][0] * ds[0][0] +
|
||||
tmp_Q0Q0[0][1] * ds[0][1] +
|
||||
tmp_Q0Q0[0][2] * ds[0][2] +
|
||||
tmp_Q0Q0[0][3] * ds[0][3] +
|
||||
tmp_Q0Q0[1][0] * ds[1][0] +
|
||||
tmp_Q0Q0[1][1] * ds[1][1] +
|
||||
tmp_Q0Q0[1][2] * ds[1][2] +
|
||||
tmp_Q0Q0[1][3] * ds[1][3] +
|
||||
tmp_Q0Q0[2][0] * ds[2][0] +
|
||||
tmp_Q0Q0[2][1] * ds[2][1] +
|
||||
tmp_Q0Q0[2][2] * ds[2][2] +
|
||||
tmp_Q0Q0[2][3] * ds[2][3] +
|
||||
tmp_Q0Q0[3][0] * ds[3][0] +
|
||||
tmp_Q0Q0[3][1] * ds[3][1] +
|
||||
tmp_Q0Q0[3][2] * ds[3][2] +
|
||||
tmp_Q0Q0[3][3] * ds[3][3];
|
||||
}
|
||||
if (dq0_out != nullptr) {
|
||||
// we can skip this check if a fixed-size array is used
|
||||
if (dq0_out->size() != 4) dq0_out->resize(4);
|
||||
/* manually loop unrolling of the following loop:
|
||||
dq0_1.reset();
|
||||
for (size_t p = 0; p < 4; p++) {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
dq0_1[p] +=
|
||||
(Q1[i] * ds_1[i][j] * Q0[j]) / (L0-L1) * Q1[p] +
|
||||
(Q2[i] * ds_1[i][j] * Q0[j]) / (L0-L2) * Q2[p] +
|
||||
(Q3[i] * ds_1[i][j] * Q0[j]) / (L0-L3) * Q3[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
(*dq0_out)[0] = tmp_Q0Q0_L[0][0][0] * ds[0][0] +
|
||||
tmp_Q0Q0_L[0][0][1] * ds[0][1] +
|
||||
tmp_Q0Q0_L[0][0][2] * ds[0][2] +
|
||||
tmp_Q0Q0_L[0][0][3] * ds[0][3] +
|
||||
tmp_Q0Q0_L[0][1][0] * ds[1][0] +
|
||||
tmp_Q0Q0_L[0][1][1] * ds[1][1] +
|
||||
tmp_Q0Q0_L[0][1][2] * ds[1][2] +
|
||||
tmp_Q0Q0_L[0][1][3] * ds[1][3] +
|
||||
tmp_Q0Q0_L[0][2][0] * ds[2][0] +
|
||||
tmp_Q0Q0_L[0][2][1] * ds[2][1] +
|
||||
tmp_Q0Q0_L[0][2][2] * ds[2][2] +
|
||||
tmp_Q0Q0_L[0][2][3] * ds[2][3] +
|
||||
tmp_Q0Q0_L[0][3][0] * ds[3][0] +
|
||||
tmp_Q0Q0_L[0][3][1] * ds[3][1] +
|
||||
tmp_Q0Q0_L[0][3][2] * ds[3][2] +
|
||||
tmp_Q0Q0_L[0][3][3] * ds[3][3];
|
||||
|
||||
(*dq0_out)[1] = tmp_Q0Q0_L[1][0][0] * ds[0][0] +
|
||||
tmp_Q0Q0_L[1][0][1] * ds[0][1] +
|
||||
tmp_Q0Q0_L[1][0][2] * ds[0][2] +
|
||||
tmp_Q0Q0_L[1][0][3] * ds[0][3] +
|
||||
tmp_Q0Q0_L[1][1][0] * ds[1][0] +
|
||||
tmp_Q0Q0_L[1][1][1] * ds[1][1] +
|
||||
tmp_Q0Q0_L[1][1][2] * ds[1][2] +
|
||||
tmp_Q0Q0_L[1][1][3] * ds[1][3] +
|
||||
tmp_Q0Q0_L[1][2][0] * ds[2][0] +
|
||||
tmp_Q0Q0_L[1][2][1] * ds[2][1] +
|
||||
tmp_Q0Q0_L[1][2][2] * ds[2][2] +
|
||||
tmp_Q0Q0_L[1][2][3] * ds[2][3] +
|
||||
tmp_Q0Q0_L[1][3][0] * ds[3][0] +
|
||||
tmp_Q0Q0_L[1][3][1] * ds[3][1] +
|
||||
tmp_Q0Q0_L[1][3][2] * ds[3][2] +
|
||||
tmp_Q0Q0_L[1][3][3] * ds[3][3];
|
||||
|
||||
(*dq0_out)[2] = tmp_Q0Q0_L[2][0][0] * ds[0][0] +
|
||||
tmp_Q0Q0_L[2][0][1] * ds[0][1] +
|
||||
tmp_Q0Q0_L[2][0][2] * ds[0][2] +
|
||||
tmp_Q0Q0_L[2][0][3] * ds[0][3] +
|
||||
tmp_Q0Q0_L[2][1][0] * ds[1][0] +
|
||||
tmp_Q0Q0_L[2][1][1] * ds[1][1] +
|
||||
tmp_Q0Q0_L[2][1][2] * ds[1][2] +
|
||||
tmp_Q0Q0_L[2][1][3] * ds[1][3] +
|
||||
tmp_Q0Q0_L[2][2][0] * ds[2][0] +
|
||||
tmp_Q0Q0_L[2][2][1] * ds[2][1] +
|
||||
tmp_Q0Q0_L[2][2][2] * ds[2][2] +
|
||||
tmp_Q0Q0_L[2][2][3] * ds[2][3] +
|
||||
tmp_Q0Q0_L[2][3][0] * ds[3][0] +
|
||||
tmp_Q0Q0_L[2][3][1] * ds[3][1] +
|
||||
tmp_Q0Q0_L[2][3][2] * ds[3][2] +
|
||||
tmp_Q0Q0_L[2][3][3] * ds[3][3];
|
||||
|
||||
(*dq0_out)[3] = tmp_Q0Q0_L[3][0][0] * ds[0][0] +
|
||||
tmp_Q0Q0_L[3][0][1] * ds[0][1] +
|
||||
tmp_Q0Q0_L[3][0][2] * ds[0][2] +
|
||||
tmp_Q0Q0_L[3][0][3] * ds[0][3] +
|
||||
tmp_Q0Q0_L[3][1][0] * ds[1][0] +
|
||||
tmp_Q0Q0_L[3][1][1] * ds[1][1] +
|
||||
tmp_Q0Q0_L[3][1][2] * ds[1][2] +
|
||||
tmp_Q0Q0_L[3][1][3] * ds[1][3] +
|
||||
tmp_Q0Q0_L[3][2][0] * ds[2][0] +
|
||||
tmp_Q0Q0_L[3][2][1] * ds[2][1] +
|
||||
tmp_Q0Q0_L[3][2][2] * ds[2][2] +
|
||||
tmp_Q0Q0_L[3][2][3] * ds[2][3] +
|
||||
tmp_Q0Q0_L[3][3][0] * ds[3][0] +
|
||||
tmp_Q0Q0_L[3][3][1] * ds[3][1] +
|
||||
tmp_Q0Q0_L[3][3][2] * ds[3][2] +
|
||||
tmp_Q0Q0_L[3][3][3] * ds[3][3];
|
||||
}
|
||||
}
|
||||
/*! @brief Calculate the derivatives of S, the leading eigenvalue L and
|
||||
* the leading eigenvector Q with respect to `m_pos1`
|
||||
* @param[in] ia The index the of atom
|
||||
* @param[out] dl0_1_out The output of derivative of L with respect to
|
||||
* ia-th atom of group 1
|
||||
* @param[out] dq0_1_out The output of derivative of Q with respect to
|
||||
* ia-th atom of group 1
|
||||
* @param[out] ds_1_out The output of derivative of overlap matrix S with
|
||||
* respect to ia-th atom of group 1
|
||||
*/
|
||||
void calc_derivative_wrt_group1(
|
||||
size_t ia, cvm::rvector* const dl0_1_out = nullptr,
|
||||
cvm::vector1d<cvm::rvector>* const dq0_1_out = nullptr,
|
||||
cvm::matrix2d<cvm::rvector>* const ds_1_out = nullptr) const {
|
||||
if (dl0_1_out == nullptr && dq0_1_out == nullptr) return;
|
||||
cvm::real a2x, a2y, a2z;
|
||||
// we can get rid of the helper function read_atom_coord if C++17 (constexpr) is available
|
||||
read_atom_coord(ia, m_pos2, &a2x, &a2y, &a2z);
|
||||
cvm::rvector ds_1[4][4];
|
||||
ds_1[0][0].set( a2x, a2y, a2z);
|
||||
ds_1[1][0].set( 0.0, a2z, -a2y);
|
||||
ds_1[0][1] = ds_1[1][0];
|
||||
ds_1[2][0].set(-a2z, 0.0, a2x);
|
||||
ds_1[0][2] = ds_1[2][0];
|
||||
ds_1[3][0].set( a2y, -a2x, 0.0);
|
||||
ds_1[0][3] = ds_1[3][0];
|
||||
ds_1[1][1].set( a2x, -a2y, -a2z);
|
||||
ds_1[2][1].set( a2y, a2x, 0.0);
|
||||
ds_1[1][2] = ds_1[2][1];
|
||||
ds_1[3][1].set( a2z, 0.0, a2x);
|
||||
ds_1[1][3] = ds_1[3][1];
|
||||
ds_1[2][2].set(-a2x, a2y, -a2z);
|
||||
ds_1[3][2].set( 0.0, a2z, a2y);
|
||||
ds_1[2][3] = ds_1[3][2];
|
||||
ds_1[3][3].set(-a2x, -a2y, a2z);
|
||||
calc_derivative_impl(ds_1, dl0_1_out, dq0_1_out, ds_1_out);
|
||||
}
|
||||
/*! @brief Calculate the derivatives of S, the leading eigenvalue L and
|
||||
* the leading eigenvector Q with respect to `m_pos2`
|
||||
* @param[in] ia The index the of atom
|
||||
* @param[out] dl0_2_out The output of derivative of L with respect to
|
||||
* ia-th atom of group 2
|
||||
* @param[out] dq0_2_out The output of derivative of Q with respect to
|
||||
* ia-th atom of group 2
|
||||
* @param[out] ds_2_out The output of derivative of overlap matrix S with
|
||||
* respect to ia-th atom of group 2
|
||||
*/
|
||||
void calc_derivative_wrt_group2(
|
||||
size_t ia, cvm::rvector* const dl0_2_out = nullptr,
|
||||
cvm::vector1d<cvm::rvector>* const dq0_2_out = nullptr,
|
||||
cvm::matrix2d<cvm::rvector>* const ds_2_out = nullptr) const {
|
||||
if (dl0_2_out == nullptr && dq0_2_out == nullptr) return;
|
||||
cvm::real a1x, a1y, a1z;
|
||||
// we can get rid of the helper function read_atom_coord if C++17 (constexpr) is available
|
||||
read_atom_coord(ia, m_pos1, &a1x, &a1y, &a1z);
|
||||
cvm::rvector ds_2[4][4];
|
||||
ds_2[0][0].set( a1x, a1y, a1z);
|
||||
ds_2[1][0].set( 0.0, -a1z, a1y);
|
||||
ds_2[0][1] = ds_2[1][0];
|
||||
ds_2[2][0].set( a1z, 0.0, -a1x);
|
||||
ds_2[0][2] = ds_2[2][0];
|
||||
ds_2[3][0].set(-a1y, a1x, 0.0);
|
||||
ds_2[0][3] = ds_2[3][0];
|
||||
ds_2[1][1].set( a1x, -a1y, -a1z);
|
||||
ds_2[2][1].set( a1y, a1x, 0.0);
|
||||
ds_2[1][2] = ds_2[2][1];
|
||||
ds_2[3][1].set( a1z, 0.0, a1x);
|
||||
ds_2[1][3] = ds_2[3][1];
|
||||
ds_2[2][2].set(-a1x, a1y, -a1z);
|
||||
ds_2[3][2].set( 0.0, a1z, a1y);
|
||||
ds_2[2][3] = ds_2[3][2];
|
||||
ds_2[3][3].set(-a1x, -a1y, a1z);
|
||||
calc_derivative_impl(ds_2, dl0_2_out, dq0_2_out, ds_2_out);
|
||||
}
|
||||
};
|
||||
|
||||
/*! @brief Function for debugging gradients (allow using either
|
||||
* std::vector<cvm::atom_pos> or std::vector<cvm::atom> for
|
||||
* pos1 and pos2)
|
||||
* @param[in] pos1 Atom positions of group 1
|
||||
* @param[in] pos2 Atom positions of group 2
|
||||
*/
|
||||
template<typename T1, typename T2>
|
||||
void debug_gradients(
|
||||
cvm::rotation &rot,
|
||||
const std::vector<T1> &pos1,
|
||||
const std::vector<T2> &pos2) {
|
||||
static_assert(std::is_same<T1, cvm::atom_pos>::value || std::is_same<T1, cvm::atom>::value, "");
|
||||
static_assert(std::is_same<T2, cvm::atom_pos>::value || std::is_same<T2, cvm::atom>::value, "");
|
||||
// eigenvalues and eigenvectors
|
||||
cvm::real const L0 = rot.S_eigval[0];
|
||||
cvm::real const L1 = rot.S_eigval[1];
|
||||
cvm::real const L2 = rot.S_eigval[2];
|
||||
cvm::real const L3 = rot.S_eigval[3];
|
||||
cvm::quaternion const Q0(rot.S_eigvec[0]);
|
||||
cvm::quaternion const Q1(rot.S_eigvec[1]);
|
||||
cvm::quaternion const Q2(rot.S_eigvec[2]);
|
||||
cvm::quaternion const Q3(rot.S_eigvec[3]);
|
||||
|
||||
cvm::log("L0 = "+cvm::to_str(L0, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q0 = "+cvm::to_str(Q0, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q0*Q0 = "+cvm::to_str(Q0.inner(Q0), cvm::cv_width, cvm::cv_prec)+
|
||||
"\n");
|
||||
cvm::log("L1 = "+cvm::to_str(L1, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q1 = "+cvm::to_str(Q1, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q0*Q1 = "+cvm::to_str(Q0.inner(Q1), cvm::cv_width, cvm::cv_prec)+
|
||||
"\n");
|
||||
cvm::log("L2 = "+cvm::to_str(L2, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q2 = "+cvm::to_str(Q2, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q0*Q2 = "+cvm::to_str(Q0.inner(Q2), cvm::cv_width, cvm::cv_prec)+
|
||||
"\n");
|
||||
cvm::log("L3 = "+cvm::to_str(L3, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q3 = "+cvm::to_str(Q3, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q0*Q3 = "+cvm::to_str(Q0.inner(Q3), cvm::cv_width, cvm::cv_prec)+
|
||||
"\n");
|
||||
|
||||
rotation_derivative<T1, T2> deriv(rot, pos1, pos2);
|
||||
cvm::rvector dl0_2;
|
||||
cvm::vector1d<cvm::rvector> dq0_2(4);
|
||||
cvm::matrix2d<cvm::rvector> ds_2;
|
||||
#ifdef COLVARS_LAMMPS
|
||||
MathEigen::Jacobi<cvm::real,
|
||||
cvm::real[4],
|
||||
cvm::real[4][4]> *ecalc =
|
||||
reinterpret_cast<MathEigen::Jacobi<cvm::real,
|
||||
cvm::real[4],
|
||||
cvm::real[4][4]> *>(rot.jacobi);
|
||||
#endif
|
||||
deriv.prepare_derivative(rotation_derivative_dldq::use_dl | rotation_derivative_dldq::use_dq);
|
||||
cvm::real S_new[4][4];
|
||||
cvm::real S_new_eigval[4];
|
||||
cvm::real S_new_eigvec[4][4];
|
||||
for (size_t ia = 0; ia < pos2.size(); ++ia) {
|
||||
// cvm::real const &a1x = pos1[ia].x;
|
||||
// cvm::real const &a1y = pos1[ia].y;
|
||||
// cvm::real const &a1z = pos1[ia].z;
|
||||
deriv.calc_derivative_wrt_group2(ia, &dl0_2, &dq0_2, &ds_2);
|
||||
// make an infitesimal move along each cartesian coordinate of
|
||||
// this atom, and solve again the eigenvector problem
|
||||
for (size_t comp = 0; comp < 3; comp++) {
|
||||
std::memcpy(S_new, rot.S_backup, sizeof(cvm::real) * 4 * 4);
|
||||
std::memset(S_new_eigval, 0, sizeof(cvm::real) * 4);
|
||||
std::memset(S_new_eigvec, 0, sizeof(cvm::real) * 4 * 4);
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
S_new[i][j] +=
|
||||
colvarmodule::debug_gradients_step_size * ds_2[i][j][comp];
|
||||
}
|
||||
}
|
||||
#ifdef COLVARS_LAMMPS
|
||||
ecalc->Diagonalize(S_new, S_new_eigval, S_new_eigvec);
|
||||
#else
|
||||
NR::diagonalize_matrix(S_new, S_new_eigval, S_new_eigvec);
|
||||
#endif
|
||||
cvm::real const &L0_new = S_new_eigval[0];
|
||||
cvm::quaternion const Q0_new(S_new_eigvec[0]);
|
||||
|
||||
cvm::real const DL0 = (dl0_2[comp]) * colvarmodule::debug_gradients_step_size;
|
||||
cvm::quaternion const DQ0(dq0_2[0][comp] * colvarmodule::debug_gradients_step_size,
|
||||
dq0_2[1][comp] * colvarmodule::debug_gradients_step_size,
|
||||
dq0_2[2][comp] * colvarmodule::debug_gradients_step_size,
|
||||
dq0_2[3][comp] * colvarmodule::debug_gradients_step_size);
|
||||
|
||||
cvm::log( "|(l_0+dl_0) - l_0^new|/l_0 = "+
|
||||
cvm::to_str(cvm::fabs(L0+DL0 - L0_new)/L0, cvm::cv_width, cvm::cv_prec)+
|
||||
", |(q_0+dq_0) - q_0^new| = "+
|
||||
cvm::to_str((Q0+DQ0 - Q0_new).norm(), cvm::cv_width, cvm::cv_prec)+
|
||||
"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // COLVAR_ROTATION_DERIVATIVE
|
||||
@ -13,10 +13,12 @@
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "colvardeps.h"
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarproxy.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvaratoms.h"
|
||||
#include "colvar_rotation_derivative.h"
|
||||
|
||||
|
||||
cvm::atom::atom()
|
||||
@ -118,6 +120,11 @@ cvm::atom_group::~atom_group()
|
||||
fitting_group = NULL;
|
||||
}
|
||||
|
||||
if (rot_deriv != nullptr) {
|
||||
delete rot_deriv;
|
||||
rot_deriv = nullptr;
|
||||
}
|
||||
|
||||
cvm::main()->unregister_named_atom_group(this);
|
||||
}
|
||||
|
||||
@ -226,6 +233,7 @@ int cvm::atom_group::init()
|
||||
b_dummy = false;
|
||||
b_user_defined_fit = false;
|
||||
fitting_group = NULL;
|
||||
rot_deriv = nullptr;
|
||||
|
||||
noforce = false;
|
||||
|
||||
@ -278,7 +286,7 @@ int cvm::atom_group::init_dependencies() {
|
||||
// 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++) {
|
||||
for (i = feature_states.size(); i < colvardeps::f_ag_ntot; i++) {
|
||||
feature_states.push_back(feature_state(false, false));
|
||||
}
|
||||
|
||||
@ -317,6 +325,13 @@ int cvm::atom_group::setup()
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
void cvm::atom_group::setup_rotation_derivative() {
|
||||
if (rot_deriv != nullptr) delete rot_deriv;
|
||||
rot_deriv = new rotation_derivative<cvm::atom, cvm::atom_pos>(
|
||||
rot, fitting_group ? fitting_group->atoms : this->atoms, ref_pos
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void cvm::atom_group::update_total_mass()
|
||||
{
|
||||
@ -383,7 +398,7 @@ int cvm::atom_group::parse(std::string const &group_conf)
|
||||
// }
|
||||
// colvarparse::Parse_Mode mode = parse_normal;
|
||||
|
||||
int parse_error = COLVARS_OK;
|
||||
int error_code = COLVARS_OK;
|
||||
|
||||
// Optional group name will let other groups reuse atom definition
|
||||
if (get_keyval(group_conf, "name", name)) {
|
||||
@ -433,7 +448,7 @@ int cvm::atom_group::parse(std::string const &group_conf)
|
||||
cvm::error("Error: cannot find atom group with name " + atoms_of + ".\n");
|
||||
return COLVARS_ERROR;
|
||||
}
|
||||
parse_error |= add_atoms_of_group(ag);
|
||||
error_code |= add_atoms_of_group(ag);
|
||||
}
|
||||
}
|
||||
|
||||
@ -447,7 +462,7 @@ int cvm::atom_group::parse(std::string const &group_conf)
|
||||
std::string numbers_conf = "";
|
||||
size_t pos = 0;
|
||||
while (key_lookup(group_conf, "atomNumbers", &numbers_conf, &pos)) {
|
||||
parse_error |= add_atom_numbers(numbers_conf);
|
||||
error_code |= add_atom_numbers(numbers_conf);
|
||||
numbers_conf = "";
|
||||
}
|
||||
}
|
||||
@ -456,7 +471,7 @@ int cvm::atom_group::parse(std::string const &group_conf)
|
||||
std::string index_group_name;
|
||||
if (get_keyval(group_conf, "indexGroup", index_group_name)) {
|
||||
// use an index group from the index file read globally
|
||||
parse_error |= add_index_group(index_group_name);
|
||||
error_code |= add_index_group(index_group_name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,7 +480,7 @@ int cvm::atom_group::parse(std::string const &group_conf)
|
||||
size_t pos = 0;
|
||||
while (key_lookup(group_conf, "atomNumbersRange",
|
||||
&range_conf, &pos)) {
|
||||
parse_error |= add_atom_numbers_range(range_conf);
|
||||
error_code |= add_atom_numbers_range(range_conf);
|
||||
range_conf = "";
|
||||
}
|
||||
}
|
||||
@ -492,7 +507,7 @@ int cvm::atom_group::parse(std::string const &group_conf)
|
||||
cvm::error("Error: more instances of \"atomNameResidueRange\" than "
|
||||
"values of \"psfSegID\".\n", COLVARS_INPUT_ERROR);
|
||||
} else {
|
||||
parse_error |= add_atom_name_residue_range(psf_segids.size() ?
|
||||
error_code |= add_atom_name_residue_range(psf_segids.size() ?
|
||||
*psii : std::string(""), range_conf);
|
||||
if (psf_segids.size()) psii++;
|
||||
}
|
||||
@ -517,26 +532,26 @@ int cvm::atom_group::parse(std::string const &group_conf)
|
||||
cvm::error("Error: atomsColValue, if provided, must be non-zero.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
// NOTE: calls to add_atom() and/or add_atom_id() are in the proxy-implemented function
|
||||
parse_error |= cvm::load_atoms(atoms_file_name.c_str(), *this, atoms_col, atoms_col_value);
|
||||
error_code |= cvm::main()->proxy->load_atoms_pdb(atoms_file_name.c_str(), *this, atoms_col,
|
||||
atoms_col_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Catch any errors from all the initialization steps above
|
||||
if (parse_error || cvm::get_error()) return (parse_error || cvm::get_error());
|
||||
if (error_code || cvm::get_error()) return (error_code || cvm::get_error());
|
||||
|
||||
// checks of doubly-counted atoms have been handled by add_atom() already
|
||||
|
||||
if (get_keyval(group_conf, "dummyAtom", dummy_atom_pos, cvm::atom_pos())) {
|
||||
|
||||
parse_error |= set_dummy();
|
||||
parse_error |= set_dummy_pos(dummy_atom_pos);
|
||||
error_code |= set_dummy();
|
||||
error_code |= set_dummy_pos(dummy_atom_pos);
|
||||
|
||||
} else {
|
||||
|
||||
if (!(atoms_ids.size())) {
|
||||
parse_error |= cvm::error("Error: no atoms defined for atom group \""+
|
||||
key+"\".\n", COLVARS_INPUT_ERROR);
|
||||
error_code |= cvm::error("Error: no atoms defined for atom group \"" + key + "\".\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
// whether these atoms will ever receive forces or not
|
||||
@ -546,7 +561,7 @@ int cvm::atom_group::parse(std::string const &group_conf)
|
||||
}
|
||||
|
||||
// Now that atoms are defined we can parse the detailed fitting options
|
||||
parse_error |= parse_fitting_options(group_conf);
|
||||
error_code |= parse_fitting_options(group_conf);
|
||||
|
||||
if (is_enabled(f_ag_scalable) && !b_dummy) {
|
||||
cvm::log("Enabling scalable calculation for group \""+this->key+"\".\n");
|
||||
@ -583,7 +598,9 @@ int cvm::atom_group::parse(std::string const &group_conf)
|
||||
cvm::log(print_atom_ids());
|
||||
}
|
||||
|
||||
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
|
||||
if (is_enabled(f_ag_rotate)) setup_rotation_derivative();
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
@ -883,8 +900,6 @@ int cvm::atom_group::parse_fitting_options(std::string const &group_conf)
|
||||
"to its radius of gyration), the optimal rotation and its gradients may become discontinuous. "
|
||||
"If that happens, use fittingGroup (or a different definition for it if already defined) "
|
||||
"to align the coordinates.\n");
|
||||
// initialize rot member data
|
||||
rot.request_group1_gradients(group_for_fit->size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -912,7 +927,6 @@ void cvm::atom_group::do_feature_side_effects(int id)
|
||||
if (is_enabled(f_ag_center) || is_enabled(f_ag_rotate)) {
|
||||
atom_group *group_for_fit = fitting_group ? fitting_group : this;
|
||||
group_for_fit->fit_gradients.assign(group_for_fit->size(), cvm::atom_pos(0.0, 0.0, 0.0));
|
||||
rot.request_group1_gradients(group_for_fit->size());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1045,17 +1059,18 @@ void cvm::atom_group::calc_apply_roto_translation()
|
||||
// rotate the group (around the center of geometry if f_ag_center is
|
||||
// enabled, around the origin otherwise)
|
||||
rot.calc_optimal_rotation(fitting_group ?
|
||||
fitting_group->positions() :
|
||||
this->positions(),
|
||||
fitting_group->atoms:
|
||||
this->atoms,
|
||||
ref_pos);
|
||||
const auto rot_mat = rot.matrix();
|
||||
|
||||
cvm::atom_iter ai;
|
||||
for (ai = this->begin(); ai != this->end(); ai++) {
|
||||
ai->pos = rot.rotate(ai->pos);
|
||||
ai->pos = rot_mat * ai->pos;
|
||||
}
|
||||
if (fitting_group) {
|
||||
for (ai = fitting_group->begin(); ai != fitting_group->end(); ai++) {
|
||||
ai->pos = rot.rotate(ai->pos);
|
||||
ai->pos = rot_mat * ai->pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1095,9 +1110,10 @@ void cvm::atom_group::read_velocities()
|
||||
|
||||
if (is_enabled(f_ag_rotate)) {
|
||||
|
||||
const auto rot_mat = rot.matrix();
|
||||
for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) {
|
||||
ai->read_velocity();
|
||||
ai->vel = rot.rotate(ai->vel);
|
||||
ai->vel = rot_mat * ai->vel;
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -1116,9 +1132,10 @@ void cvm::atom_group::read_total_forces()
|
||||
|
||||
if (is_enabled(f_ag_rotate)) {
|
||||
|
||||
const auto rot_mat = rot.matrix();
|
||||
for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) {
|
||||
ai->read_total_force();
|
||||
ai->total_force = rot.rotate(ai->total_force);
|
||||
ai->total_force = rot_mat * ai->total_force;
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -1200,52 +1217,71 @@ void cvm::atom_group::calc_fit_gradients()
|
||||
if (cvm::debug())
|
||||
cvm::log("Calculating fit gradients.\n");
|
||||
|
||||
cvm::atom_group *group_for_fit = fitting_group ? fitting_group : this;
|
||||
|
||||
if (is_enabled(f_ag_center)) {
|
||||
// add the center of geometry contribution to the gradients
|
||||
cvm::rvector atom_grad;
|
||||
|
||||
for (size_t i = 0; i < this->size(); i++) {
|
||||
atom_grad += atoms[i].grad;
|
||||
}
|
||||
if (is_enabled(f_ag_rotate)) atom_grad = (rot.inverse()).rotate(atom_grad);
|
||||
atom_grad *= (-1.0)/(cvm::real(group_for_fit->size()));
|
||||
|
||||
for (size_t j = 0; j < group_for_fit->size(); j++) {
|
||||
group_for_fit->fit_gradients[j] = atom_grad;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_enabled(f_ag_rotate)) {
|
||||
|
||||
// add the rotation matrix contribution to the gradients
|
||||
cvm::rotation const rot_inv = rot.inverse();
|
||||
|
||||
for (size_t i = 0; i < this->size(); i++) {
|
||||
|
||||
// compute centered, unrotated position
|
||||
cvm::atom_pos const pos_orig =
|
||||
rot_inv.rotate((is_enabled(f_ag_center) ? (atoms[i].pos - ref_pos_cog) : (atoms[i].pos)));
|
||||
|
||||
// calculate \partial(R(q) \vec{x}_i)/\partial q) \cdot \partial\xi/\partial\vec{x}_i
|
||||
cvm::quaternion const dxdq =
|
||||
rot.q.position_derivative_inner(pos_orig, atoms[i].grad);
|
||||
|
||||
for (size_t j = 0; j < group_for_fit->size(); j++) {
|
||||
// multiply by {\partial q}/\partial\vec{x}_j and add it to the fit gradients
|
||||
for (size_t iq = 0; iq < 4; iq++) {
|
||||
group_for_fit->fit_gradients[j] += dxdq[iq] * rot.dQ0_1[j][iq];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_enabled(f_ag_center) && is_enabled(f_ag_rotate))
|
||||
calc_fit_gradients_impl<true, true>();
|
||||
if (is_enabled(f_ag_center) && !is_enabled(f_ag_rotate))
|
||||
calc_fit_gradients_impl<true, false>();
|
||||
if (!is_enabled(f_ag_center) && is_enabled(f_ag_rotate))
|
||||
calc_fit_gradients_impl<false, true>();
|
||||
if (!is_enabled(f_ag_center) && !is_enabled(f_ag_rotate))
|
||||
calc_fit_gradients_impl<false, false>();
|
||||
|
||||
if (cvm::debug())
|
||||
cvm::log("Done calculating fit gradients.\n");
|
||||
}
|
||||
|
||||
|
||||
template <bool B_ag_center, bool B_ag_rotate>
|
||||
void cvm::atom_group::calc_fit_gradients_impl() {
|
||||
cvm::atom_group *group_for_fit = fitting_group ? fitting_group : this;
|
||||
// the center of geometry contribution to the gradients
|
||||
cvm::rvector atom_grad;
|
||||
// the rotation matrix contribution to the gradients
|
||||
const auto rot_inv = rot.inverse().matrix();
|
||||
// temporary variables for computing and summing derivatives
|
||||
cvm::real sum_dxdq[4] = {0, 0, 0, 0};
|
||||
cvm::vector1d<cvm::rvector> dq0_1(4);
|
||||
// loop 1: iterate over the current atom group
|
||||
for (size_t i = 0; i < size(); i++) {
|
||||
cvm::atom_pos pos_orig;
|
||||
if (B_ag_center) {
|
||||
atom_grad += atoms[i].grad;
|
||||
if (B_ag_rotate) pos_orig = rot_inv * (atoms[i].pos - ref_pos_cog);
|
||||
} else {
|
||||
if (B_ag_rotate) pos_orig = atoms[i].pos;
|
||||
}
|
||||
if (B_ag_rotate) {
|
||||
// calculate \partial(R(q) \vec{x}_i)/\partial q) \cdot \partial\xi/\partial\vec{x}_i
|
||||
cvm::quaternion const dxdq =
|
||||
rot.q.position_derivative_inner(pos_orig, atoms[i].grad);
|
||||
sum_dxdq[0] += dxdq[0];
|
||||
sum_dxdq[1] += dxdq[1];
|
||||
sum_dxdq[2] += dxdq[2];
|
||||
sum_dxdq[3] += dxdq[3];
|
||||
}
|
||||
}
|
||||
if (B_ag_center) {
|
||||
if (B_ag_rotate) atom_grad = rot.inverse().matrix() * atom_grad;
|
||||
atom_grad *= (-1.0)/(cvm::real(group_for_fit->size()));
|
||||
}
|
||||
// loop 2: iterate over the fitting group
|
||||
if (B_ag_rotate) rot_deriv->prepare_derivative(rotation_derivative_dldq::use_dq);
|
||||
for (size_t j = 0; j < group_for_fit->size(); j++) {
|
||||
if (B_ag_center) {
|
||||
group_for_fit->fit_gradients[j] = atom_grad;
|
||||
}
|
||||
if (B_ag_rotate) {
|
||||
rot_deriv->calc_derivative_wrt_group1(j, nullptr, &dq0_1);
|
||||
// multiply by {\partial q}/\partial\vec{x}_j and add it to the fit gradients
|
||||
group_for_fit->fit_gradients[j] += sum_dxdq[0] * dq0_1[0] +
|
||||
sum_dxdq[1] * dq0_1[1] +
|
||||
sum_dxdq[2] * dq0_1[2] +
|
||||
sum_dxdq[3] * dq0_1[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<cvm::atom_pos> cvm::atom_group::positions() const
|
||||
{
|
||||
if (b_dummy) {
|
||||
@ -1373,9 +1409,9 @@ void cvm::atom_group::apply_colvar_force(cvm::real const &force)
|
||||
if (is_enabled(f_ag_rotate)) {
|
||||
|
||||
// rotate forces back to the original frame
|
||||
cvm::rotation const rot_inv = rot.inverse();
|
||||
const auto rot_inv = rot.inverse().matrix();
|
||||
for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) {
|
||||
ai->apply_force(rot_inv.rotate(force * ai->grad));
|
||||
ai->apply_force(rot_inv * (force * ai->grad));
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -1418,9 +1454,9 @@ void cvm::atom_group::apply_force(cvm::rvector const &force)
|
||||
|
||||
if (is_enabled(f_ag_rotate)) {
|
||||
|
||||
cvm::rotation const rot_inv = rot.inverse();
|
||||
const auto rot_inv = rot.inverse().matrix();
|
||||
for (cvm::atom_iter ai = this->begin(); ai != this->end(); ai++) {
|
||||
ai->apply_force(rot_inv.rotate((ai->mass/total_mass) * force));
|
||||
ai->apply_force(rot_inv * ((ai->mass/total_mass) * force));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@ -15,6 +15,9 @@
|
||||
#include "colvarparse.h"
|
||||
#include "colvardeps.h"
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct rotation_derivative;
|
||||
|
||||
|
||||
/// \brief Stores numeric id, mass and all mutable data for an atom,
|
||||
/// mostly used by a \link colvar::cvc \endlink
|
||||
@ -167,7 +170,7 @@ public:
|
||||
atom_group(std::vector<cvm::atom> const &atoms_in);
|
||||
|
||||
/// \brief Destructor
|
||||
~atom_group();
|
||||
~atom_group() override;
|
||||
|
||||
/// \brief Optional name to reuse properties of this in other groups
|
||||
std::string name;
|
||||
@ -180,7 +183,7 @@ public:
|
||||
int init();
|
||||
|
||||
/// \brief Initialize dependency tree
|
||||
virtual int init_dependencies();
|
||||
int init_dependencies() override;
|
||||
|
||||
/// \brief Update data required to calculate cvc's
|
||||
int setup();
|
||||
@ -221,16 +224,13 @@ public:
|
||||
static std::vector<feature *> ag_features;
|
||||
|
||||
/// \brief Implementation of the feature list accessor for atom group
|
||||
virtual const std::vector<feature *> &features() const
|
||||
const std::vector<feature *> &features() const override { return ag_features; }
|
||||
|
||||
std::vector<feature *> &modify_features() override { return ag_features; }
|
||||
|
||||
static void delete_features()
|
||||
{
|
||||
return ag_features;
|
||||
}
|
||||
virtual std::vector<feature *> &modify_features()
|
||||
{
|
||||
return ag_features;
|
||||
}
|
||||
static void delete_features() {
|
||||
for (size_t i=0; i < ag_features.size(); i++) {
|
||||
for (size_t i = 0; i < ag_features.size(); i++) {
|
||||
delete ag_features[i];
|
||||
}
|
||||
ag_features.clear();
|
||||
@ -330,6 +330,9 @@ public:
|
||||
/// The rotation calculated automatically if f_ag_rotate is defined
|
||||
cvm::rotation rot;
|
||||
|
||||
/// Rotation derivative;
|
||||
rotation_derivative<cvm::atom, cvm::atom_pos>* rot_deriv;
|
||||
|
||||
/// \brief Indicates that the user has explicitly set centerToReference or
|
||||
/// rotateReference, and the corresponding reference:
|
||||
/// cvc's (eg rmsd, eigenvector) will not override the user's choice
|
||||
@ -369,6 +372,8 @@ public:
|
||||
/// \brief (Re)calculate the optimal roto-translation
|
||||
void calc_apply_roto_translation();
|
||||
|
||||
void setup_rotation_derivative();
|
||||
|
||||
/// \brief Save aside the center of geometry of the reference positions,
|
||||
/// then subtract it from them
|
||||
///
|
||||
@ -492,6 +497,16 @@ public:
|
||||
/// \brief Calculate the derivatives of the fitting transformation
|
||||
void calc_fit_gradients();
|
||||
|
||||
/*! @brief Actual implementation of `calc_fit_gradients`. The template is
|
||||
* used to avoid branching inside the loops in case that the CPU
|
||||
* branch prediction is broken (or further migration to GPU code).
|
||||
* @tparam B_ag_center Centered the reference to origin? This should follow
|
||||
* the value of `is_enabled(f_ag_center)`.
|
||||
* @tparam B_ag_rotate Calculate the optimal rotation? This should follow
|
||||
* the value of `is_enabled(f_ag_rotate)`.
|
||||
*/
|
||||
template <bool B_ag_center, bool B_ag_rotate> void calc_fit_gradients_impl();
|
||||
|
||||
/// \brief Derivatives of the fitting transformation
|
||||
std::vector<cvm::atom_pos> fit_gradients;
|
||||
|
||||
@ -525,7 +540,7 @@ public:
|
||||
/// Implements possible actions to be carried out
|
||||
/// when a given feature is enabled
|
||||
/// This overloads the base function in colvardeps
|
||||
void do_feature_side_effects(int id);
|
||||
void do_feature_side_effects(int id) override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarbias.h"
|
||||
#include "colvargrid.h"
|
||||
#include "colvars_memstream.h"
|
||||
|
||||
|
||||
colvarbias::colvarbias(char const *key)
|
||||
@ -166,6 +167,10 @@ int colvarbias::init_dependencies() {
|
||||
|
||||
init_feature(f_cvb_get_total_force, "obtain_total_force", f_type_dynamic);
|
||||
require_feature_children(f_cvb_get_total_force, f_cv_total_force);
|
||||
// Depending on back-end, we may not obtain total force at step 0
|
||||
if (!cvm::main()->proxy->total_forces_same_step()) {
|
||||
exclude_feature_self(f_cvb_get_total_force, f_cvb_step_zero_data);
|
||||
}
|
||||
|
||||
init_feature(f_cvb_output_acc_work, "output_accumulated_work", f_type_user);
|
||||
require_feature_self(f_cvb_output_acc_work, f_cvb_apply_force);
|
||||
@ -192,6 +197,8 @@ int colvarbias::init_dependencies() {
|
||||
init_feature(f_cvb_scale_biasing_force, "scale_biasing_force", f_type_user);
|
||||
require_feature_children(f_cvb_scale_biasing_force, f_cv_grid);
|
||||
|
||||
init_feature(f_cvb_extended, "Bias on extended-Lagrangian variables", f_type_static);
|
||||
|
||||
// check that everything is initialized
|
||||
for (i = 0; i < colvardeps::f_cvb_ntot; i++) {
|
||||
if (is_not_set(i)) {
|
||||
@ -202,7 +209,7 @@ int colvarbias::init_dependencies() {
|
||||
|
||||
// Initialize feature_states for each instance
|
||||
feature_states.reserve(f_cvb_ntot);
|
||||
for (i = 0; i < f_cvb_ntot; i++) {
|
||||
for (i = feature_states.size(); i < f_cvb_ntot; i++) {
|
||||
feature_states.push_back(feature_state(true, false));
|
||||
// Most features are available, so we set them so
|
||||
// and list exceptions below
|
||||
@ -436,42 +443,54 @@ int colvarbias::bin_num()
|
||||
cvm::error("Error: bin_num() not implemented.\n");
|
||||
return COLVARS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
int colvarbias::current_bin()
|
||||
{
|
||||
cvm::error("Error: current_bin() not implemented.\n");
|
||||
return COLVARS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
int colvarbias::bin_count(int /* bin_index */)
|
||||
{
|
||||
cvm::error("Error: bin_count() not implemented.\n");
|
||||
return COLVARS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
int colvarbias::local_sample_count(int /* radius */)
|
||||
{
|
||||
cvm::error("Error: local_sample_count() not implemented.\n");
|
||||
return COLVARS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
int colvarbias::replica_share()
|
||||
{
|
||||
cvm::error("Error: replica_share() not implemented.\n");
|
||||
return COLVARS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
size_t colvarbias::replica_share_freq() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::string const colvarbias::get_state_params() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "step " << cvm::step_absolute() << "\n"
|
||||
<< "name " << this->name << "\n";
|
||||
os << " step " << cvm::step_absolute() << "\n"
|
||||
<< " name " << this->name << "\n";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
int colvarbias::set_state_params(std::string const &conf)
|
||||
int colvarbias::check_matching_state(std::string const &conf)
|
||||
{
|
||||
matching_state = false;
|
||||
|
||||
std::string check_name = "";
|
||||
colvarparse::get_keyval(conf, "name", check_name,
|
||||
std::string(""), colvarparse::parse_silent);
|
||||
|
||||
if (check_name.size() == 0) {
|
||||
cvm::error("Error: \""+bias_type+"\" block within the restart file "
|
||||
return cvm::error("Error: \""+bias_type+"\" block within the state file "
|
||||
"has no identifiers.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
@ -480,11 +499,17 @@ int colvarbias::set_state_params(std::string const &conf)
|
||||
cvm::log("Ignoring state of bias \""+check_name+
|
||||
"\": this bias is named \""+name+"\".\n");
|
||||
}
|
||||
return COLVARS_OK;
|
||||
matching_state = false;
|
||||
} else {
|
||||
matching_state = true;
|
||||
}
|
||||
|
||||
matching_state = true;
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
int colvarbias::set_state_params(std::string const &conf)
|
||||
{
|
||||
colvarparse::get_keyval(conf, "step", state_file_step,
|
||||
cvm::step_absolute(), colvarparse::parse_silent);
|
||||
|
||||
@ -495,76 +520,119 @@ int colvarbias::set_state_params(std::string const &conf)
|
||||
std::ostream & colvarbias::write_state(std::ostream &os)
|
||||
{
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Writing state file for bias \""+name+"\"\n");
|
||||
cvm::log("Writing formatted state for bias \""+name+"\"\n");
|
||||
}
|
||||
os.setf(std::ios::scientific, std::ios::floatfield);
|
||||
os.precision(cvm::cv_prec);
|
||||
os << state_keyword << " {\n"
|
||||
<< " configuration {\n";
|
||||
std::istringstream is(get_state_params());
|
||||
std::string line;
|
||||
while (std::getline(is, line)) {
|
||||
os << " " << line << "\n";
|
||||
}
|
||||
os << " }\n";
|
||||
<< " configuration {\n"
|
||||
<< get_state_params()
|
||||
<< " }\n";
|
||||
write_state_data(os);
|
||||
os << "}\n\n";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarbias::read_state(std::istream &is)
|
||||
cvm::memory_stream & colvarbias::write_state(cvm::memory_stream &os)
|
||||
{
|
||||
std::streampos const start_pos = is.tellg();
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Writing unformatted state for bias \""+name+"\"\n");
|
||||
}
|
||||
os << state_keyword << std::string("configuration") << get_state_params();
|
||||
write_state_data(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template <typename IST, typename SPT>
|
||||
void raise_error_rewind(IST &is, SPT start_pos, std::string const &bias_type,
|
||||
std::string const &bias_name, std::string const added_msg = "")
|
||||
{
|
||||
auto state = is.rdstate();
|
||||
is.clear();
|
||||
is.seekg(start_pos);
|
||||
is.setstate(state | std::ios::failbit);
|
||||
cvm::error("Error: in reading state for \"" + bias_type + "\" bias \"" + bias_name +
|
||||
"\" at position " + cvm::to_str(static_cast<size_t>(is.tellg())) + " in stream." +
|
||||
added_msg + "\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
|
||||
template <typename IST> IST & colvarbias::read_state_template_(IST &is)
|
||||
{
|
||||
auto const start_pos = is.tellg();
|
||||
|
||||
std::string key, brace, conf;
|
||||
if ( !(is >> key) || !(key == state_keyword || key == bias_type) ||
|
||||
!(is >> brace) || !(brace == "{") ||
|
||||
!(is >> colvarparse::read_block("configuration", &conf)) ||
|
||||
(set_state_params(conf) != COLVARS_OK) ) {
|
||||
cvm::error("Error: in reading state configuration for \""+bias_type+
|
||||
"\" bias \""+
|
||||
this->name+"\" at position "+
|
||||
cvm::to_str(static_cast<size_t>(is.tellg()))+
|
||||
" in stream.\n", COLVARS_INPUT_ERROR);
|
||||
is.clear();
|
||||
is.seekg(start_pos, std::ios::beg);
|
||||
is.setstate(std::ios::failbit);
|
||||
if (is >> key) {
|
||||
if (key == state_keyword || key == bias_type) {
|
||||
|
||||
if (! std::is_same<IST, cvm::memory_stream>::value) {
|
||||
// Formatted input only
|
||||
if (!(is >> brace) || !(brace == "{") ) {
|
||||
raise_error_rewind(is, start_pos, bias_type, name);
|
||||
return is;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(is >> colvarparse::read_block("configuration", &conf)) ||
|
||||
(check_matching_state(conf) != COLVARS_OK)) {
|
||||
raise_error_rewind(is, start_pos, bias_type, name);
|
||||
return is;
|
||||
}
|
||||
|
||||
if (matching_state == false) {
|
||||
// This state is not for this bias
|
||||
is.seekg(start_pos, std::ios::beg);
|
||||
} else {
|
||||
// Not a match for this bias type, rewind without error
|
||||
is.seekg(start_pos);
|
||||
return is;
|
||||
}
|
||||
|
||||
cvm::log("Restarting "+bias_type+" bias \""+name+"\" from step number "+
|
||||
cvm::to_str(state_file_step)+".\n");
|
||||
|
||||
if (!read_state_data(is)) {
|
||||
cvm::error("Error: in reading state data for \""+bias_type+"\" bias \""+
|
||||
this->name+"\" at position "+
|
||||
cvm::to_str(static_cast<size_t>(is.tellg()))+
|
||||
" in stream.\n", COLVARS_INPUT_ERROR);
|
||||
is.clear();
|
||||
is.seekg(start_pos, std::ios::beg);
|
||||
is.setstate(std::ios::failbit);
|
||||
} else {
|
||||
raise_error_rewind(is, start_pos, bias_type, name);
|
||||
return is;
|
||||
}
|
||||
|
||||
if (!matching_state) {
|
||||
// No errors, but not a match for this bias instance; rewind
|
||||
is.seekg(start_pos);
|
||||
return is;
|
||||
}
|
||||
|
||||
if ((set_state_params(conf) != COLVARS_OK) || !read_state_data(is)) {
|
||||
raise_error_rewind(is, start_pos, bias_type, name);
|
||||
}
|
||||
|
||||
if (! std::is_same<IST, cvm::memory_stream>::value) {
|
||||
is >> brace;
|
||||
if (brace != "}") {
|
||||
cvm::error("Error: corrupt restart information for \""+bias_type+"\" bias \""+
|
||||
this->name+"\": no matching brace at position "+
|
||||
cvm::to_str(static_cast<size_t>(is.tellg()))+
|
||||
" in stream.\n");
|
||||
is.setstate(std::ios::failbit);
|
||||
raise_error_rewind(is, start_pos, bias_type, name);
|
||||
}
|
||||
}
|
||||
|
||||
cvm::log("Restarted " + bias_type + " bias \"" + name + "\" with step number " +
|
||||
cvm::to_str(state_file_step) + ".\n");
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
std::istream &colvarbias::read_state(std::istream &is)
|
||||
{
|
||||
return read_state_template_<std::istream>(is);
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream &colvarbias::read_state(cvm::memory_stream &is)
|
||||
{
|
||||
return read_state_template_<cvm::memory_stream>(is);
|
||||
}
|
||||
|
||||
|
||||
int colvarbias::write_state_prefix(std::string const &prefix)
|
||||
{
|
||||
std::string const filename =
|
||||
@ -635,25 +703,51 @@ int colvarbias::read_state_string(char const *buffer)
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarbias::read_state_data_key(std::istream &is, char const *key)
|
||||
std::ostream &colvarbias::write_state_data_key(std::ostream &os, std::string const &key,
|
||||
bool header)
|
||||
{
|
||||
std::streampos const start_pos = is.tellg();
|
||||
os << (header ? "\n" : "") << key << (header ? "\n" : " ");
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream &colvarbias::write_state_data_key(cvm::memory_stream &os, std::string const &key,
|
||||
bool /* header */)
|
||||
{
|
||||
os << std::string(key);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template <typename IST>
|
||||
IST &colvarbias::read_state_data_key_template_(IST &is, std::string const &key)
|
||||
{
|
||||
auto const start_pos = is.tellg();
|
||||
std::string key_in;
|
||||
if ( !(is >> key_in) ||
|
||||
!(to_lower_cppstr(key_in) == to_lower_cppstr(std::string(key))) ) {
|
||||
cvm::error("Error: in reading restart configuration for "+
|
||||
bias_type+" bias \""+this->name+"\" at position "+
|
||||
cvm::to_str(static_cast<size_t>(is.tellg()))+
|
||||
" in stream.\n", COLVARS_INPUT_ERROR);
|
||||
is.clear();
|
||||
is.seekg(start_pos, std::ios::beg);
|
||||
is.setstate(std::ios::failbit);
|
||||
return is;
|
||||
if (is >> key_in) {
|
||||
if (key_in != key) {
|
||||
raise_error_rewind(is, start_pos, bias_type, name,
|
||||
" Expected keyword \"" + std::string(key) + "\", found \"" + key_in +
|
||||
"\".");
|
||||
}
|
||||
} else {
|
||||
raise_error_rewind(is, start_pos, bias_type, name);
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarbias::read_state_data_key(std::istream &is, std::string const &key)
|
||||
{
|
||||
return read_state_data_key_template_<std::istream>(is, key);
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream & colvarbias::read_state_data_key(cvm::memory_stream &is, std::string const &key)
|
||||
{
|
||||
return read_state_data_key_template_<cvm::memory_stream>(is, key);
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarbias::write_traj_label(std::ostream &os)
|
||||
{
|
||||
@ -686,28 +780,11 @@ colvarbias_ti::colvarbias_ti(char const *key)
|
||||
// Samples at step zero can not be collected
|
||||
feature_states[f_cvb_step_zero_data].available = false;
|
||||
}
|
||||
ti_avg_forces = NULL;
|
||||
ti_count = NULL;
|
||||
}
|
||||
|
||||
|
||||
colvarbias_ti::~colvarbias_ti()
|
||||
{
|
||||
colvarbias_ti::clear_state_data();
|
||||
}
|
||||
|
||||
|
||||
int colvarbias_ti::clear_state_data()
|
||||
{
|
||||
if (ti_avg_forces != NULL) {
|
||||
delete ti_avg_forces;
|
||||
ti_avg_forces = NULL;
|
||||
}
|
||||
if (ti_count != NULL) {
|
||||
delete ti_count;
|
||||
ti_count = NULL;
|
||||
}
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -765,7 +842,7 @@ int colvarbias_ti::init(std::string const &conf)
|
||||
int colvarbias_ti::init_grids()
|
||||
{
|
||||
if (is_enabled(f_cvb_calc_ti_samples)) {
|
||||
if (ti_avg_forces == NULL) {
|
||||
if (!ti_avg_forces) {
|
||||
ti_bin.resize(num_variables());
|
||||
ti_system_forces.resize(num_variables());
|
||||
for (size_t icv = 0; icv < num_variables(); icv++) {
|
||||
@ -773,8 +850,8 @@ int colvarbias_ti::init_grids()
|
||||
ti_system_forces[icv].is_derivative();
|
||||
ti_system_forces[icv].reset();
|
||||
}
|
||||
ti_avg_forces = new colvar_grid_gradient(colvars);
|
||||
ti_count = new colvar_grid_count(colvars);
|
||||
ti_avg_forces.reset(new colvar_grid_gradient(colvars));
|
||||
ti_count.reset(new colvar_grid_count(colvars));
|
||||
ti_avg_forces->samples = ti_count;
|
||||
ti_count->has_parent_data = true;
|
||||
}
|
||||
@ -860,9 +937,22 @@ std::ostream & colvarbias_ti::write_state_data(std::ostream &os)
|
||||
if (! is_enabled(f_cvb_calc_ti_samples)) {
|
||||
return os;
|
||||
}
|
||||
os << "\nhistogram\n";
|
||||
write_state_data_key(os, "histogram");
|
||||
ti_count->write_raw(os);
|
||||
os << "\nsystem_forces\n";
|
||||
write_state_data_key(os, "system_forces");
|
||||
ti_avg_forces->write_raw(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream & colvarbias_ti::write_state_data(cvm::memory_stream &os)
|
||||
{
|
||||
if (! is_enabled(f_cvb_calc_ti_samples)) {
|
||||
return os;
|
||||
}
|
||||
write_state_data_key(os, "histogram");
|
||||
ti_count->write_raw(os);
|
||||
write_state_data_key(os, "system_forces");
|
||||
ti_avg_forces->write_raw(os);
|
||||
return os;
|
||||
}
|
||||
@ -895,6 +985,33 @@ std::istream & colvarbias_ti::read_state_data(std::istream &is)
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream & colvarbias_ti::read_state_data(cvm::memory_stream &is)
|
||||
{
|
||||
if (! is_enabled(f_cvb_calc_ti_samples)) {
|
||||
return is;
|
||||
}
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Reading state data for the TI estimator.\n");
|
||||
}
|
||||
if (! read_state_data_key(is, "histogram")) {
|
||||
return is;
|
||||
}
|
||||
if (! ti_count->read_raw(is)) {
|
||||
return is;
|
||||
}
|
||||
if (! read_state_data_key(is, "system_forces")) {
|
||||
return is;
|
||||
}
|
||||
if (! ti_avg_forces->read_raw(is)) {
|
||||
return is;
|
||||
}
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Done reading state data for the TI estimator.\n");
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
int colvarbias_ti::write_output_files()
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
#ifndef COLVARBIAS_H
|
||||
#define COLVARBIAS_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "colvar.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvardeps.h"
|
||||
@ -91,11 +93,16 @@ public:
|
||||
// FIXME this is currently 1D only
|
||||
virtual int current_bin();
|
||||
//// Give the count at a given bin index.
|
||||
// FIXME this is currently 1D only
|
||||
virtual int bin_count(int bin_index);
|
||||
/// Return the average number of samples in a given "radius" around current bin
|
||||
virtual int local_sample_count(int radius);
|
||||
|
||||
//// Share information between replicas, whatever it may be.
|
||||
virtual int replica_share();
|
||||
|
||||
/// Report the frequency at which this bias needs to communicate with replicas
|
||||
virtual size_t replica_share_freq() const;
|
||||
|
||||
/// Perform analysis tasks
|
||||
virtual void analyze() {}
|
||||
|
||||
@ -133,32 +140,87 @@ public:
|
||||
/// Write the values of specific mutable properties to a string
|
||||
virtual std::string const get_state_params() const;
|
||||
|
||||
/// Check the name of the bias vs. the given string, set the matching_state flag accordingly
|
||||
int check_matching_state(std::string const &conf);
|
||||
|
||||
/// Read the values of specific mutable properties from a string
|
||||
virtual int set_state_params(std::string const &state_conf);
|
||||
|
||||
/// Write all mutable data not already written by get_state_params()
|
||||
/// Write all mutable data not already written by get_state_params() to a formatted stream
|
||||
virtual std::ostream & write_state_data(std::ostream &os)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
/// Read all mutable data not already set by set_state_params()
|
||||
/// Write all mutable data not already written by get_state_params() to an unformatted stream
|
||||
virtual cvm::memory_stream & write_state_data(cvm::memory_stream &os)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
/// Read all mutable data not already set by set_state_params() from a formatted stream
|
||||
virtual std::istream & read_state_data(std::istream &is)
|
||||
{
|
||||
return is;
|
||||
}
|
||||
|
||||
/// Read a keyword from the state data (typically a header)
|
||||
/// \param Input stream
|
||||
/// \param Keyword labeling the header block
|
||||
std::istream & read_state_data_key(std::istream &is, char const *key);
|
||||
/// Read all mutable data not already set by set_state_params() from an unformatted stream
|
||||
virtual cvm::memory_stream & read_state_data(cvm::memory_stream &is)
|
||||
{
|
||||
return is;
|
||||
}
|
||||
|
||||
/// Write the bias configuration to a state file or other stream
|
||||
std::ostream & write_state(std::ostream &os);
|
||||
/// Write a keyword header for a data sequence to a formatted stream
|
||||
/// \param[in,out] os Output stream
|
||||
/// \param[in] key Keyword labeling the header block
|
||||
/// \param[in] header Whether this is the header of a multi-line segment vs a single line
|
||||
std::ostream &write_state_data_key(std::ostream &os, std::string const &key, bool header = true);
|
||||
|
||||
/// Read the bias configuration from a restart file or other stream
|
||||
/// Write a keyword header for a data sequence to an unformatted stream
|
||||
/// \param[in,out] os Output stream
|
||||
/// \param[in] key Keyword labeling the header block
|
||||
/// \param[in] header Ignored
|
||||
cvm::memory_stream &write_state_data_key(cvm::memory_stream &os, std::string const &key,
|
||||
bool header = true);
|
||||
|
||||
private:
|
||||
|
||||
/// Read a keyword header for a data sequence from a stream
|
||||
/// \param[in,out] Input stream
|
||||
/// \param[in] Keyword labeling the header block; an error will be raised if not matching
|
||||
template <typename IST> IST &read_state_data_key_template_(IST &is, std::string const &key);
|
||||
|
||||
public:
|
||||
|
||||
/// Read a keyword header for a data sequence from a formatted stream
|
||||
/// \param[in,out] Input stream
|
||||
/// \param[in] Keyword labeling the header block; an error will be raised if not matching
|
||||
std::istream & read_state_data_key(std::istream &is, std::string const &key);
|
||||
|
||||
/// Read a keyword header for a data sequence from an unformatted stream
|
||||
/// \param[in,out] Input stream
|
||||
/// \param[in] Keyword labeling the header block; an error will be raised if not matching
|
||||
cvm::memory_stream & read_state_data_key(cvm::memory_stream &is, std::string const &key);
|
||||
|
||||
private:
|
||||
|
||||
/// Generic stream reading function (formatted and not)
|
||||
template <typename IST> IST & read_state_template_(IST &is);
|
||||
|
||||
public:
|
||||
|
||||
/// Write the bias configuration to a formatted stream
|
||||
std::ostream &write_state(std::ostream &os);
|
||||
|
||||
/// Write the bias configuration to an unformatted stream
|
||||
cvm::memory_stream & write_state(cvm::memory_stream &os);
|
||||
|
||||
/// Read the bias configuration from a formatted stream
|
||||
std::istream & read_state(std::istream &is);
|
||||
|
||||
/// Read the bias configuration from an unformatted stream
|
||||
cvm::memory_stream & read_state(cvm::memory_stream &is);
|
||||
|
||||
/// Write the bias state to a file with the given prefix
|
||||
int write_state_prefix(std::string const &prefix);
|
||||
|
||||
@ -274,8 +336,6 @@ public:
|
||||
colvarbias_ti(char const *key);
|
||||
virtual ~colvarbias_ti();
|
||||
|
||||
virtual int clear_state_data();
|
||||
|
||||
virtual int init(std::string const &conf);
|
||||
virtual int init_grids();
|
||||
virtual int update();
|
||||
@ -288,7 +348,9 @@ public:
|
||||
virtual std::string const get_state_params() const;
|
||||
virtual int set_state_params(std::string const &state_conf);
|
||||
virtual std::ostream & write_state_data(std::ostream &os);
|
||||
virtual cvm::memory_stream & write_state_data(cvm::memory_stream &os);
|
||||
virtual std::istream & read_state_data(std::istream &is);
|
||||
virtual cvm::memory_stream & read_state_data(cvm::memory_stream &is);
|
||||
virtual int write_output_files();
|
||||
|
||||
protected:
|
||||
@ -297,10 +359,10 @@ protected:
|
||||
std::vector<colvarvalue> ti_system_forces;
|
||||
|
||||
/// Averaged system forces
|
||||
colvar_grid_gradient *ti_avg_forces;
|
||||
std::shared_ptr<colvar_grid_gradient> ti_avg_forces;
|
||||
|
||||
/// Histogram of sampled data
|
||||
colvar_grid_count *ti_count;
|
||||
std::shared_ptr<colvar_grid_count> ti_count;
|
||||
|
||||
/// Because total forces may be from the last simulation step,
|
||||
/// store the index of the variables then
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -14,13 +14,14 @@
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
|
||||
#include "colvarproxy.h"
|
||||
#include "colvarbias.h"
|
||||
#include "colvargrid.h"
|
||||
#include "colvar_UIestimator.h"
|
||||
|
||||
typedef cvm::real* gradient_t;
|
||||
typedef cvm::real *gradient_t;
|
||||
|
||||
|
||||
/// ABF bias
|
||||
@ -31,17 +32,14 @@ public:
|
||||
/// Constructor for ABF bias
|
||||
colvarbias_abf(char const *key);
|
||||
/// Initializer for ABF bias
|
||||
virtual int init(std::string const &conf);
|
||||
int init(std::string const &conf) override;
|
||||
/// Default destructor for ABF bias
|
||||
virtual ~colvarbias_abf();
|
||||
~colvarbias_abf() override;
|
||||
/// Per-timestep update of ABF bias
|
||||
virtual int update();
|
||||
int update() override;
|
||||
|
||||
private:
|
||||
|
||||
/// Filename prefix for human-readable gradient/sample count output
|
||||
std::string output_prefix;
|
||||
|
||||
/// Base filename(s) for reading previous gradient data (replaces data from restart file)
|
||||
std::vector<std::string> input_prefix;
|
||||
|
||||
@ -57,8 +55,8 @@ private:
|
||||
size_t full_samples;
|
||||
/// Number of samples per bin before applying a scaled-down biasing force
|
||||
size_t min_samples;
|
||||
/// Write combined files with a history of all output data?
|
||||
bool b_history_files;
|
||||
/// Latest absolute time step at which history files were written
|
||||
cvm::step_number history_last_step;
|
||||
/// Write CZAR output file for stratified eABF (.zgrad)
|
||||
bool b_czar_window_file;
|
||||
/// Number of timesteps between recording data in history files (if non-zero)
|
||||
@ -99,75 +97,104 @@ private:
|
||||
gradient_t system_force;
|
||||
|
||||
/// n-dim grid of free energy gradients
|
||||
colvar_grid_gradient *gradients;
|
||||
std::shared_ptr<colvar_grid_gradient> gradients;
|
||||
/// n-dim grid of number of samples
|
||||
colvar_grid_count *samples;
|
||||
std::shared_ptr<colvar_grid_count> samples;
|
||||
/// n-dim grid of pmf (dimension 1 to 3)
|
||||
integrate_potential *pmf;
|
||||
std::shared_ptr<integrate_potential> pmf;
|
||||
/// n-dim grid: average force on "real" coordinate for eABF z-based estimator
|
||||
colvar_grid_gradient *z_gradients;
|
||||
std::shared_ptr<colvar_grid_gradient> z_gradients;
|
||||
/// n-dim grid of number of samples on "real" coordinate for eABF z-based estimator
|
||||
colvar_grid_count *z_samples;
|
||||
/// n-dim grid containing CZAR estimator of "real" free energy gradients
|
||||
colvar_grid_gradient *czar_gradients;
|
||||
std::shared_ptr<colvar_grid_count> z_samples;
|
||||
/// n-dim grid containing CZAR estimatr of "real" free energy gradients
|
||||
std::shared_ptr<colvar_grid_gradient> czar_gradients;
|
||||
/// n-dim grid of CZAR pmf (dimension 1 to 3)
|
||||
integrate_potential *czar_pmf;
|
||||
std::shared_ptr<integrate_potential> czar_pmf;
|
||||
|
||||
inline int update_system_force(size_t i)
|
||||
{
|
||||
if (colvars[i]->is_enabled(f_cv_subtract_applied_force)) {
|
||||
// this colvar is already subtracting the ABF force
|
||||
system_force[i] = colvars[i]->total_force().real_value;
|
||||
} else {
|
||||
system_force[i] = colvars[i]->total_force().real_value
|
||||
- colvar_forces[i].real_value;
|
||||
// If hideJacobian is active then total_force has an extra term of -fj
|
||||
// which is the Jacobian-compensating force at the colvar level
|
||||
}
|
||||
if (cvm::debug())
|
||||
cvm::log("ABF System force calc: cv " + cvm::to_str(i) +
|
||||
" fs " + cvm::to_str(system_force[i]) +
|
||||
" = ft " + cvm::to_str(colvars[i]->total_force().real_value) +
|
||||
" - fa " + cvm::to_str(colvar_forces[i].real_value));
|
||||
return COLVARS_OK;
|
||||
}
|
||||
/// Calculate system force for all colvars
|
||||
int update_system_force();
|
||||
|
||||
/// Calulate the biasing force for the current bin
|
||||
int calc_biasing_force(std::vector<cvm::real> &force);
|
||||
|
||||
/// Calulate the smoothing factor to apply to biasing forces for given local count
|
||||
cvm::real smoothing_factor(cvm::real weight);
|
||||
|
||||
// shared ABF
|
||||
bool shared_on;
|
||||
size_t shared_freq;
|
||||
cvm::step_number shared_last_step;
|
||||
// Share between replicas -- may be called independently of update
|
||||
virtual int replica_share();
|
||||
|
||||
// Store the last set for shared ABF
|
||||
colvar_grid_gradient *last_gradients;
|
||||
colvar_grid_count *last_samples;
|
||||
// Share between replicas -- may be called independently of update
|
||||
int replica_share() override;
|
||||
|
||||
// Share data needed for CZAR between replicas - called before output only
|
||||
int replica_share_CZAR();
|
||||
|
||||
/// Report the frequency at which this bias needs to communicate with replicas
|
||||
size_t replica_share_freq() const override;
|
||||
|
||||
// Data just after the last share (start of cycle) in shared ABF
|
||||
std::unique_ptr<colvar_grid_gradient> last_gradients;
|
||||
std::shared_ptr<colvar_grid_count> last_samples;
|
||||
// eABF/CZAR local data last shared
|
||||
std::unique_ptr<colvar_grid_gradient> z_gradients_in;
|
||||
std::shared_ptr<colvar_grid_count> z_samples_in;
|
||||
// ABF data from local replica only in shared ABF
|
||||
std::shared_ptr<colvar_grid_gradient> local_gradients;
|
||||
std::shared_ptr<colvar_grid_count> local_samples;
|
||||
std::unique_ptr<integrate_potential> local_pmf;
|
||||
// eABF/CZAR data collected from all replicas in shared eABF on replica 0
|
||||
// if non-shared, aliases of regular CZAR grids, for output purposes
|
||||
std::shared_ptr<colvar_grid_gradient> global_z_gradients;
|
||||
std::shared_ptr<colvar_grid_count> global_z_samples;
|
||||
std::shared_ptr<colvar_grid_gradient> global_czar_gradients;
|
||||
std::shared_ptr<integrate_potential> global_czar_pmf;
|
||||
|
||||
|
||||
// For Tcl implementation of selection rules.
|
||||
/// Give the total number of bins for a given bias.
|
||||
virtual int bin_num();
|
||||
int bin_num() override;
|
||||
/// Calculate the bin index for a given bias.
|
||||
virtual int current_bin();
|
||||
int current_bin() override;
|
||||
//// Give the count at a given bin index.
|
||||
virtual int bin_count(int bin_index);
|
||||
int bin_count(int bin_index) override;
|
||||
/// Return the average number of samples in a given "radius" around current bin
|
||||
int local_sample_count(int radius) override;
|
||||
|
||||
/// Write human-readable FE gradients and sample count, and DX file in dim > 2
|
||||
void write_gradients_samples(const std::string &prefix, bool close = true);
|
||||
/// \param local write grids contining replica-local data in shared ABF
|
||||
void write_gradients_samples(const std::string &prefix, bool close = true, bool local = false);
|
||||
|
||||
/// Read human-readable FE gradients and sample count (if not using restart)
|
||||
int read_gradients_samples();
|
||||
|
||||
/// Template used in write_gradient_samples()
|
||||
/// Shorthand template used in write_gradient_samples()
|
||||
template <class T> int write_grid_to_file(T const *grid,
|
||||
std::string const &name,
|
||||
bool close);
|
||||
|
||||
virtual std::istream& read_state_data(std::istream&);
|
||||
virtual std::ostream& write_state_data(std::ostream&);
|
||||
virtual int write_output_files();
|
||||
private:
|
||||
|
||||
/// Generic stream writing function (formatted and not)
|
||||
template <typename OST> OST &write_state_data_template_(OST &os);
|
||||
|
||||
/// Generic stream readingx function (formatted and not)
|
||||
template <typename IST> IST &read_state_data_template_(IST &is);
|
||||
|
||||
public:
|
||||
|
||||
std::ostream &write_state_data(std::ostream &os) override;
|
||||
|
||||
cvm::memory_stream &write_state_data(cvm::memory_stream &os) override;
|
||||
|
||||
std::istream &read_state_data(std::istream &is) override;
|
||||
|
||||
cvm::memory_stream &read_state_data(cvm::memory_stream &is) override;
|
||||
|
||||
int write_output_files() override;
|
||||
|
||||
/// Calculate the bias energy for 1D ABF
|
||||
virtual int calc_energy(std::vector<colvarvalue> const *values);
|
||||
int calc_energy(std::vector<colvarvalue> const *values) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
136
lib/colvars/colvarbias_abmd.cpp
Normal file
136
lib/colvars/colvarbias_abmd.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
// -*- 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.
|
||||
|
||||
|
||||
#include "colvarbias_abmd.h"
|
||||
#include "colvarproxy.h"
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
colvarbias_abmd::colvarbias_abmd(char const *key)
|
||||
: colvarbias(key),
|
||||
colvarbias_ti(key)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int colvarbias_abmd::init(std::string const &conf)
|
||||
{
|
||||
cvm::main()->cite_feature("ABMD bias");
|
||||
|
||||
int err = colvarbias::init(conf);
|
||||
err |= colvarbias_ti::init(conf);
|
||||
if (err != COLVARS_OK) return err;
|
||||
|
||||
enable(f_cvb_apply_force);
|
||||
|
||||
if (num_variables() != 1) {
|
||||
return cvm::error("ABMD requires exactly one collective variable.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if ( ! (variables(0))->is_enabled(f_cv_scalar) ) {
|
||||
return cvm::error("ABMD colvar must be scalar.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
get_keyval(conf, "forceConstant", k);
|
||||
get_keyval(conf, "decreasing", decreasing, decreasing);
|
||||
get_keyval(conf, "stoppingValue", stopping_val);
|
||||
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
int colvarbias_abmd::update()
|
||||
{
|
||||
if (!cvm::main()->proxy->simulation_running()) {
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
colvar const *cv = variables(0);
|
||||
cvm::real const val = cv->value().real_value;
|
||||
|
||||
if (!ref_initialized) {
|
||||
ref_val = val;
|
||||
ref_initialized = true;
|
||||
}
|
||||
|
||||
// Compute sign factor to unify increasing and decreasing cases below
|
||||
// less conditionals, more arithmetic
|
||||
cvm::real const sign = decreasing ? -1. : 1.;
|
||||
cvm::real const diff = (val - ref_val) * sign;
|
||||
|
||||
if ( diff > 0. ) {
|
||||
colvar_forces[0] = 0.;
|
||||
bias_energy = 0.;
|
||||
if ( (ref_val-stopping_val) * sign <= 0. ) ref_val = val;
|
||||
} else {
|
||||
colvar_forces[0] = - sign * k * diff;
|
||||
bias_energy = 0.5 * k * diff * diff;;
|
||||
}
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
std::string const colvarbias_abmd::get_state_params() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os.setf(std::ios::scientific, std::ios::floatfield);
|
||||
|
||||
os << " refValue "
|
||||
<< std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width)
|
||||
<< ref_val << "\n";
|
||||
os << " stoppingValue " << stopping_val << "\n";
|
||||
os << " forceConstant " << k << "\n";
|
||||
os << " decreasing " << (decreasing ? "on" : "off") << "\n";
|
||||
|
||||
return (colvarbias::get_state_params() + os.str());
|
||||
}
|
||||
|
||||
|
||||
int colvarbias_abmd::set_state_params(std::string const &conf)
|
||||
{
|
||||
int error_code = colvarbias::set_state_params(conf);
|
||||
|
||||
if (error_code != COLVARS_OK) {
|
||||
return error_code;
|
||||
}
|
||||
|
||||
get_keyval(conf, "refValue", ref_val, ref_val,
|
||||
colvarparse::parse_restart | colvarparse::parse_required);
|
||||
ref_initialized = true;
|
||||
|
||||
get_keyval(conf, "forceConstant", k, k,
|
||||
colvarparse::parse_restart | colvarparse::parse_required);
|
||||
get_keyval(conf, "decreasing", decreasing, decreasing,
|
||||
colvarparse::parse_restart | colvarparse::parse_required);
|
||||
get_keyval(conf, "stoppingValue", stopping_val, stopping_val,
|
||||
colvarparse::parse_restart | colvarparse::parse_required);
|
||||
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarbias_abmd::write_traj_label(std::ostream &os)
|
||||
{
|
||||
size_t const this_cv_width = (variables(0)->value()).output_width(cvm::cv_width);
|
||||
os << " ref_"
|
||||
<< cvm::wrap_string(variables(0)->name, this_cv_width-4);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarbias_abmd::write_traj(std::ostream &os)
|
||||
{
|
||||
os << " "
|
||||
<< std::setprecision(cvm::en_prec) << std::setw(cvm::en_width)
|
||||
<< ref_val;
|
||||
|
||||
return os;
|
||||
}
|
||||
49
lib/colvars/colvarbias_abmd.h
Normal file
49
lib/colvars/colvarbias_abmd.h
Normal file
@ -0,0 +1,49 @@
|
||||
// -*- 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 COLVARBIAS_ABMD_H
|
||||
#define COLVARBIAS_ABMD_H
|
||||
|
||||
#include "colvarbias_restraint.h"
|
||||
|
||||
|
||||
/// \brief Adiabatic Bias MD
|
||||
class colvarbias_abmd
|
||||
: public colvarbias_ti
|
||||
{
|
||||
public:
|
||||
|
||||
colvarbias_abmd(char const *key);
|
||||
virtual int init(std::string const &conf);
|
||||
virtual int update();
|
||||
virtual std::string const get_state_params() const;
|
||||
virtual int set_state_params(std::string const &conf);
|
||||
virtual std::ostream & write_traj_label(std::ostream &os);
|
||||
virtual std::ostream & write_traj(std::ostream &os);
|
||||
|
||||
protected:
|
||||
|
||||
/// \brief Location of the moving wall
|
||||
cvm::real ref_val = 0.;
|
||||
|
||||
/// \brief Has ref_val already been set?
|
||||
bool ref_initialized = false;
|
||||
|
||||
/// \brief Value of the reference where it stops moving
|
||||
cvm::real stopping_val = 0.;
|
||||
|
||||
/// \brief Is the target moving down?
|
||||
bool decreasing = false;
|
||||
|
||||
/// \brief Restraint force constant
|
||||
cvm::real k = 0.;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@ -9,7 +9,6 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarproxy.h"
|
||||
@ -40,7 +39,10 @@ colvarbias_alb::colvarbias_alb(char const *key)
|
||||
int colvarbias_alb::init(std::string const &conf)
|
||||
{
|
||||
colvarproxy *proxy = cvm::main()->proxy;
|
||||
colvarbias::init(conf);
|
||||
int err = colvarbias::init(conf);
|
||||
if (err != COLVARS_OK) {
|
||||
return err;
|
||||
}
|
||||
cvm::main()->cite_feature("ALB colvar bias implementation");
|
||||
|
||||
enable(f_cvb_scalar_variables);
|
||||
|
||||
@ -7,10 +7,13 @@
|
||||
// If you wish to distribute your changes, please submit them to the
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarproxy.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarbias_histogram.h"
|
||||
#include "colvars_memstream.h"
|
||||
|
||||
|
||||
colvarbias_histogram::colvarbias_histogram(char const *key)
|
||||
@ -23,7 +26,10 @@ colvarbias_histogram::colvarbias_histogram(char const *key)
|
||||
|
||||
int colvarbias_histogram::init(std::string const &conf)
|
||||
{
|
||||
colvarbias::init(conf);
|
||||
int err = colvarbias::init(conf);
|
||||
if (err != COLVARS_OK) {
|
||||
return err;
|
||||
}
|
||||
cvm::main()->cite_feature("Histogram colvar bias implementation");
|
||||
|
||||
enable(f_cvb_scalar_variables);
|
||||
@ -125,22 +131,6 @@ int colvarbias_histogram::update()
|
||||
// assign a valid bin size
|
||||
bin.assign(num_variables(), 0);
|
||||
|
||||
if (out_name.size() == 0) {
|
||||
// At the first timestep, we need to assign out_name since
|
||||
// output_prefix is unset during the constructor
|
||||
if (cvm::step_relative() == 0) {
|
||||
out_name = cvm::output_prefix() + "." + this->name + ".dat";
|
||||
cvm::log("Histogram " + this->name + " will be written to file \"" + out_name + "\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (out_name_dx.size() == 0) {
|
||||
if (cvm::step_relative() == 0) {
|
||||
out_name_dx = cvm::output_prefix() + "." + this->name + ".dx";
|
||||
cvm::log("Histogram " + this->name + " will be written to file \"" + out_name_dx + "\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (colvar_array_size == 0) {
|
||||
// update indices for scalar values
|
||||
size_t i;
|
||||
@ -181,6 +171,16 @@ int colvarbias_histogram::write_output_files()
|
||||
|
||||
int error_code = COLVARS_OK;
|
||||
|
||||
// Set default filenames, if none have been provided
|
||||
if (!cvm::output_prefix().empty()) {
|
||||
if (out_name.empty()) {
|
||||
out_name = cvm::output_prefix() + "." + this->name + ".dat";
|
||||
}
|
||||
if (out_name_dx.empty()) {
|
||||
out_name_dx = cvm::output_prefix() + "." + this->name + ".dx";
|
||||
}
|
||||
}
|
||||
|
||||
if (out_name.size() && out_name != "none") {
|
||||
cvm::log("Writing the histogram file \""+out_name+"\".\n");
|
||||
error_code |= grid->write_multicol(out_name, "histogram output file");
|
||||
@ -197,13 +197,18 @@ int colvarbias_histogram::write_output_files()
|
||||
|
||||
std::istream & colvarbias_histogram::read_state_data(std::istream& is)
|
||||
{
|
||||
if (! read_state_data_key(is, "grid")) {
|
||||
return is;
|
||||
if (read_state_data_key(is, "grid")) {
|
||||
grid->read_raw(is);
|
||||
}
|
||||
if (! grid->read_raw(is)) {
|
||||
return is;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream & colvarbias_histogram::read_state_data(cvm::memory_stream& is)
|
||||
{
|
||||
if (read_state_data_key(is, "grid")) {
|
||||
grid->read_raw(is);
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
@ -212,8 +217,16 @@ std::ostream & colvarbias_histogram::write_state_data(std::ostream& os)
|
||||
{
|
||||
std::ios::fmtflags flags(os.flags());
|
||||
os.setf(std::ios::fmtflags(0), std::ios::floatfield);
|
||||
os << "grid\n";
|
||||
write_state_data_key(os, "grid");
|
||||
grid->write_raw(os, 8);
|
||||
os.flags(flags);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream & colvarbias_histogram::write_state_data(cvm::memory_stream& os)
|
||||
{
|
||||
write_state_data_key(os, "grid");
|
||||
grid->write_raw(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
@ -24,11 +24,16 @@ class colvarbias_histogram : public colvarbias {
|
||||
public:
|
||||
|
||||
colvarbias_histogram(char const *key);
|
||||
~colvarbias_histogram();
|
||||
virtual ~colvarbias_histogram();
|
||||
virtual int init(std::string const &conf);
|
||||
virtual int update();
|
||||
virtual int write_output_files();
|
||||
|
||||
virtual std::ostream & write_state_data(std::ostream &os);
|
||||
virtual cvm::memory_stream & write_state_data(cvm::memory_stream &os);
|
||||
virtual std::istream & read_state_data(std::istream &is);
|
||||
virtual cvm::memory_stream & read_state_data(cvm::memory_stream &is);
|
||||
|
||||
protected:
|
||||
|
||||
/// n-dim histogram
|
||||
@ -40,9 +45,6 @@ protected:
|
||||
size_t colvar_array_size;
|
||||
/// If colvar_array_size is larger than 1, weigh each one by this number before accumulating the histogram
|
||||
std::vector<cvm::real> weights;
|
||||
|
||||
virtual std::istream & read_state_data(std::istream &is);
|
||||
virtual std::ostream & write_state_data(std::ostream &os);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
#include "colvarbias_histogram_reweight_amd.h"
|
||||
#include "colvarproxy.h"
|
||||
#include "colvars_memstream.h"
|
||||
|
||||
colvarbias_reweightaMD::colvarbias_reweightaMD(char const *key)
|
||||
: colvarbias_histogram(key), grid_count(NULL), grid_dV(NULL),
|
||||
@ -343,23 +344,37 @@ void colvarbias_reweightaMD::compute_cumulant_expansion_factor(
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream & colvarbias_reweightaMD::write_state_data(std::ostream& os)
|
||||
|
||||
template <typename OST> OST & colvarbias_reweightaMD::write_state_data_template_(OST& os)
|
||||
{
|
||||
std::ios::fmtflags flags(os.flags());
|
||||
os.setf(std::ios::fmtflags(0), std::ios::floatfield);
|
||||
os << "grid\n";
|
||||
write_state_data_key(os, "grid");
|
||||
grid->write_raw(os, 8);
|
||||
os << "grid_count\n";
|
||||
write_state_data_key(os, "grid_count");
|
||||
grid_count->write_raw(os, 8);
|
||||
os << "grid_dV\n";
|
||||
write_state_data_key(os, "grid_dV");
|
||||
grid_dV->write_raw(os, 8);
|
||||
os << "grid_dV_square\n";
|
||||
write_state_data_key(os, "grid_dV_square");
|
||||
grid_dV_square->write_raw(os, 8);
|
||||
os.flags(flags);
|
||||
return os;
|
||||
}
|
||||
|
||||
std::istream & colvarbias_reweightaMD::read_state_data(std::istream& is)
|
||||
|
||||
std::ostream & colvarbias_reweightaMD::write_state_data(std::ostream& os)
|
||||
{
|
||||
return write_state_data_template_<std::ostream>(os);
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream & colvarbias_reweightaMD::write_state_data(cvm::memory_stream& os)
|
||||
{
|
||||
return write_state_data_template_<cvm::memory_stream>(os);
|
||||
}
|
||||
|
||||
|
||||
template <typename IST> IST & colvarbias_reweightaMD::read_state_data_template_(IST& is)
|
||||
{
|
||||
if (! read_state_data_key(is, "grid")) {
|
||||
return is;
|
||||
@ -387,3 +402,15 @@ std::istream & colvarbias_reweightaMD::read_state_data(std::istream& is)
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarbias_reweightaMD::read_state_data(std::istream& is)
|
||||
{
|
||||
return read_state_data_template_<std::istream>(is);
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream & colvarbias_reweightaMD::read_state_data(cvm::memory_stream& is)
|
||||
{
|
||||
return read_state_data_template_<cvm::memory_stream>(is);
|
||||
}
|
||||
|
||||
@ -18,15 +18,9 @@ class colvarbias_reweightaMD : public colvarbias_histogram {
|
||||
public:
|
||||
colvarbias_reweightaMD(char const *key);
|
||||
virtual ~colvarbias_reweightaMD();
|
||||
#if (__cplusplus >= 201103L)
|
||||
virtual int init(std::string const &conf) override;
|
||||
virtual int update() override;
|
||||
virtual int write_output_files() override;
|
||||
#else
|
||||
virtual int init(std::string const &conf);
|
||||
virtual int update();
|
||||
virtual int write_output_files();
|
||||
#endif
|
||||
|
||||
/// @brief convert histogram to PMF by taking logarithm and multiplying
|
||||
/// it with -1/beta
|
||||
@ -85,14 +79,15 @@ protected:
|
||||
/// Write gradients of the PMF?
|
||||
bool b_write_gradients;
|
||||
|
||||
template <typename OST> OST & write_state_data_template_(OST& os);
|
||||
template <typename IST> IST & read_state_data_template_(IST& is);
|
||||
|
||||
/// save and restore
|
||||
#if (__cplusplus >= 201103L)
|
||||
virtual std::istream & read_state_data(std::istream &is) override;
|
||||
virtual cvm::memory_stream & read_state_data(cvm::memory_stream &is) override;
|
||||
virtual std::ostream & write_state_data(std::ostream &os) override;
|
||||
#else
|
||||
virtual std::istream & read_state_data(std::istream &is);
|
||||
virtual std::ostream & write_state_data(std::ostream &os);
|
||||
#endif
|
||||
virtual cvm::memory_stream & write_state_data(cvm::memory_stream &os) override;
|
||||
|
||||
private:
|
||||
/// temporary grids for evaluating PMFs
|
||||
colvar_grid_scalar *pmf_grid_exp_avg;
|
||||
|
||||
@ -7,29 +7,33 @@
|
||||
// If you wish to distribute your changes, please submit them to the
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
|
||||
// used to set the absolute path of a replica file
|
||||
// Define function to get the absolute path of a replica file
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include <direct.h>
|
||||
#define CHDIR ::_chdir
|
||||
#define GETCWD ::_getcwd
|
||||
#define GETCWD(BUF, SIZE) ::_getcwd(BUF, SIZE)
|
||||
#define PATHSEP "\\"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#define CHDIR ::chdir
|
||||
#define GETCWD ::getcwd
|
||||
#define GETCWD(BUF, SIZE) ::getcwd(BUF, SIZE)
|
||||
#define PATHSEP "/"
|
||||
#endif
|
||||
|
||||
#ifdef __cpp_lib_filesystem
|
||||
// When std::filesystem is available, use it
|
||||
#include <filesystem>
|
||||
#undef GETCWD
|
||||
#define GETCWD(BUF, SIZE) (std::filesystem::current_path().string().c_str())
|
||||
#endif
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarproxy.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarbias_meta.h"
|
||||
#include "colvars_memstream.h"
|
||||
|
||||
|
||||
colvarbias_meta::colvarbias_meta(char const *key)
|
||||
@ -58,7 +62,6 @@ colvarbias_meta::colvarbias_meta(char const *key)
|
||||
|
||||
ebmeta_equil_steps = 0L;
|
||||
|
||||
replica_update_freq = 0;
|
||||
replica_id.clear();
|
||||
}
|
||||
|
||||
@ -392,11 +395,8 @@ colvarbias_meta::add_hill(colvarbias_meta::hill const &h)
|
||||
|
||||
// output to trajectory (if specified)
|
||||
if (b_hills_traj) {
|
||||
// Open trajectory file or access the one already open
|
||||
std::ostream &hills_traj_os =
|
||||
cvm::proxy->output_stream(hills_traj_file_name());
|
||||
hills_traj_os << (hills.back()).output_traj();
|
||||
cvm::proxy->flush_output_stream(hills_traj_file_name());
|
||||
// Save the current hill to a buffer for further traj output
|
||||
hills_traj_os_buf << (hills.back()).output_traj();
|
||||
}
|
||||
|
||||
has_data = true;
|
||||
@ -427,13 +427,10 @@ colvarbias_meta::delete_hill(hill_iter &h)
|
||||
}
|
||||
|
||||
if (b_hills_traj) {
|
||||
// output to the trajectory
|
||||
std::ostream &hills_traj_os =
|
||||
cvm::proxy->output_stream(hills_traj_file_name());
|
||||
hills_traj_os << "# DELETED this hill: "
|
||||
// Save the current hill to a buffer for further traj output
|
||||
hills_traj_os_buf << "# DELETED this hill: "
|
||||
<< (hills.back()).output_traj()
|
||||
<< "\n";
|
||||
cvm::proxy->flush_output_stream(hills_traj_file_name());
|
||||
}
|
||||
|
||||
return hills.erase(h);
|
||||
@ -624,9 +621,9 @@ int colvarbias_meta::update_bias()
|
||||
add_hill(hill(cvm::step_absolute(), hill_weight*hills_scale,
|
||||
colvar_values, colvar_sigmas, replica_id));
|
||||
std::ostream &replica_hills_os =
|
||||
cvm::proxy->output_stream(replica_hills_file);
|
||||
cvm::proxy->output_stream(replica_hills_file, "replica hills file");
|
||||
if (replica_hills_os) {
|
||||
replica_hills_os << hills.back();
|
||||
write_hill(replica_hills_os, hills.back());
|
||||
} else {
|
||||
return cvm::error("Error: in metadynamics bias \""+this->name+"\""+
|
||||
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
|
||||
@ -985,9 +982,9 @@ void colvarbias_meta::recount_hills_off_grid(colvarbias_meta::hill_iter h_first
|
||||
int colvarbias_meta::replica_share()
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
colvarproxy *proxy = cvm::proxy;
|
||||
// sync with the other replicas (if needed)
|
||||
if (comm == multiple_replicas) {
|
||||
colvarproxy *proxy = cvm::main()->proxy;
|
||||
// reread the replicas registry
|
||||
error_code |= update_replicas_registry();
|
||||
// empty the output buffer
|
||||
@ -998,6 +995,12 @@ int colvarbias_meta::replica_share()
|
||||
}
|
||||
|
||||
|
||||
size_t colvarbias_meta::replica_share_freq() const
|
||||
{
|
||||
return replica_update_freq;
|
||||
}
|
||||
|
||||
|
||||
int colvarbias_meta::update_replicas_registry()
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
@ -1299,21 +1302,40 @@ int colvarbias_meta::set_state_params(std::string const &state_conf)
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarbias_meta::read_state_data(std::istream& is)
|
||||
template <typename IST, typename GT>
|
||||
IST & colvarbias_meta::read_grid_data_template_(IST& is, std::string const &key,
|
||||
GT *grid, GT *backup_grid)
|
||||
{
|
||||
auto const start_pos = is.tellg();
|
||||
std::string key_in;
|
||||
if (is >> key_in) {
|
||||
if ((key != key_in) || !(grid->read_restart(is))) {
|
||||
is.clear();
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
if (!rebin_grids) {
|
||||
if ((backup_grid == nullptr) || (comm == single_replica)) {
|
||||
cvm::error("Error: couldn't read grid data for metadynamics bias \""+
|
||||
this->name+"\""+
|
||||
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
|
||||
"; if useGrids was off when the state file was written, "
|
||||
"try enabling rebinGrids now to regenerate the grids.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
is.clear();
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
template <typename IST> IST &colvarbias_meta::read_state_data_template_(IST &is)
|
||||
{
|
||||
if (use_grids) {
|
||||
|
||||
if (expand_grids) {
|
||||
// the boundaries of the colvars may have been changed; TODO:
|
||||
// this reallocation is only for backward-compatibility, and may
|
||||
// be deleted when grid_parameters (i.e. colvargrid's own
|
||||
// internal reallocation) has kicked in
|
||||
delete hills_energy;
|
||||
delete hills_energy_gradients;
|
||||
hills_energy = new colvar_grid_scalar(colvars);
|
||||
hills_energy_gradients = new colvar_grid_gradient(colvars);
|
||||
}
|
||||
|
||||
colvar_grid_scalar *hills_energy_backup = NULL;
|
||||
colvar_grid_gradient *hills_energy_gradients_backup = NULL;
|
||||
|
||||
@ -1328,95 +1350,26 @@ std::istream & colvarbias_meta::read_state_data(std::istream& is)
|
||||
hills_energy_gradients = new colvar_grid_gradient(colvars);
|
||||
}
|
||||
|
||||
std::streampos const hills_energy_pos = is.tellg();
|
||||
std::string key;
|
||||
if (!(is >> key)) {
|
||||
if (hills_energy_backup != NULL) {
|
||||
delete hills_energy;
|
||||
delete hills_energy_gradients;
|
||||
hills_energy = hills_energy_backup;
|
||||
hills_energy_gradients = hills_energy_gradients_backup;
|
||||
}
|
||||
is.clear();
|
||||
is.seekg(hills_energy_pos, std::ios::beg);
|
||||
is.setstate(std::ios::failbit);
|
||||
return is;
|
||||
} else if (!(key == std::string("hills_energy")) ||
|
||||
!(hills_energy->read_restart(is))) {
|
||||
is.clear();
|
||||
is.seekg(hills_energy_pos, std::ios::beg);
|
||||
if (!rebin_grids) {
|
||||
if ((hills_energy_backup == NULL) || (comm == single_replica)) {
|
||||
cvm::error("Error: couldn't read the energy grid for metadynamics bias \""+
|
||||
this->name+"\""+
|
||||
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
|
||||
"; if useGrids was off when the state file was written, "
|
||||
"enable rebinGrids now to regenerate the grids.\n");
|
||||
} else {
|
||||
delete hills_energy;
|
||||
delete hills_energy_gradients;
|
||||
hills_energy = hills_energy_backup;
|
||||
hills_energy_gradients = hills_energy_gradients_backup;
|
||||
is.setstate(std::ios::failbit);
|
||||
return is;
|
||||
}
|
||||
}
|
||||
}
|
||||
read_grid_data_template_<IST, colvar_grid_scalar>(is, "hills_energy", hills_energy,
|
||||
hills_energy_backup);
|
||||
|
||||
std::streampos const hills_energy_gradients_pos = is.tellg();
|
||||
if (!(is >> key)) {
|
||||
if (hills_energy_backup != NULL) {
|
||||
delete hills_energy;
|
||||
delete hills_energy_gradients;
|
||||
hills_energy = hills_energy_backup;
|
||||
hills_energy_gradients = hills_energy_gradients_backup;
|
||||
}
|
||||
is.clear();
|
||||
is.seekg(hills_energy_gradients_pos, std::ios::beg);
|
||||
is.setstate(std::ios::failbit);
|
||||
return is;
|
||||
} else if (!(key == std::string("hills_energy_gradients")) ||
|
||||
!(hills_energy_gradients->read_restart(is))) {
|
||||
is.clear();
|
||||
is.seekg(hills_energy_gradients_pos, std::ios::beg);
|
||||
if (!rebin_grids) {
|
||||
if ((hills_energy_backup == NULL) || (comm == single_replica)) {
|
||||
cvm::error("Error: couldn't read the gradients grid for metadynamics bias \""+
|
||||
this->name+"\""+
|
||||
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+
|
||||
"; if useGrids was off when the state file was written, "
|
||||
"enable rebinGrids now to regenerate the grids.\n");
|
||||
} else {
|
||||
delete hills_energy;
|
||||
delete hills_energy_gradients;
|
||||
hills_energy = hills_energy_backup;
|
||||
hills_energy_gradients = hills_energy_gradients_backup;
|
||||
is.setstate(std::ios::failbit);
|
||||
return is;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cvm::debug())
|
||||
cvm::log("Successfully read new grids for bias \""+
|
||||
this->name+"\""+
|
||||
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+"\n");
|
||||
|
||||
cvm::log(" read biasing energy and forces from grids.\n");
|
||||
|
||||
if (hills_energy_backup != NULL) {
|
||||
// now that we have successfully updated the grids, delete the
|
||||
// backup copies
|
||||
if (cvm::debug())
|
||||
cvm::log("Deallocating the older grids.\n");
|
||||
read_grid_data_template_<IST, colvar_grid_gradient>(
|
||||
is, "hills_energy_gradients", hills_energy_gradients, hills_energy_gradients_backup);
|
||||
|
||||
if (is) {
|
||||
cvm::log(" successfully read the biasing potential and its gradients from grids.\n");
|
||||
if (hills_energy_backup != nullptr) {
|
||||
// Now that we have successfully updated the grids, delete the backup copies
|
||||
delete hills_energy_backup;
|
||||
delete hills_energy_gradients_backup;
|
||||
}
|
||||
} else {
|
||||
return is;
|
||||
}
|
||||
}
|
||||
|
||||
// Save references to the end of the list of existing hills, so that it can
|
||||
// be cleared if hills are read successfully state
|
||||
// Save references to the end of the list of existing hills, so that they can
|
||||
// be cleared if hills are read successfully from the stream
|
||||
bool const existing_hills = !hills.empty();
|
||||
size_t const old_hills_size = hills.size();
|
||||
hill_iter old_hills_end = hills.end();
|
||||
@ -1430,17 +1383,20 @@ std::istream & colvarbias_meta::read_state_data(std::istream& is)
|
||||
while (read_hill(is)) {
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Read a previously saved hill under the "
|
||||
"metadynamics bias \""+
|
||||
this->name+"\", created at step "+
|
||||
cvm::to_str((hills.back()).it)+".\n");
|
||||
"metadynamics bias \"" +
|
||||
this->name + "\", created at step " + cvm::to_str((hills.back()).it) +
|
||||
"; position in stream is " + cvm::to_str(is.tellg()) + ".\n");
|
||||
}
|
||||
}
|
||||
|
||||
is.clear();
|
||||
|
||||
new_hills_begin = hills.end();
|
||||
cvm::log(" read "+cvm::to_str(hills.size() - old_hills_size)+
|
||||
" additional explicit hills.\n");
|
||||
cvm::log(" successfully read "+cvm::to_str(hills.size() - old_hills_size)+
|
||||
" explicit hills from state.\n");
|
||||
|
||||
if (existing_hills) {
|
||||
// Prune any hills that pre-existed those just read
|
||||
hills.erase(hills.begin(), old_hills_end);
|
||||
hills_off_grid.erase(hills_off_grid.begin(), old_hills_off_grid_end);
|
||||
if (cvm::debug()) {
|
||||
@ -1449,6 +1405,46 @@ std::istream & colvarbias_meta::read_state_data(std::istream& is)
|
||||
}
|
||||
}
|
||||
|
||||
// If rebinGrids is set, rebin the grids based on the current information
|
||||
rebin_grids_after_restart();
|
||||
|
||||
if (use_grids) {
|
||||
if (!hills_off_grid.empty()) {
|
||||
cvm::log(cvm::to_str(hills_off_grid.size())+" hills are near the "
|
||||
"grid boundaries: they will be computed analytically "
|
||||
"and saved to the state files.\n");
|
||||
}
|
||||
}
|
||||
|
||||
colvarbias_ti::read_state_data(is);
|
||||
|
||||
if (cvm::debug())
|
||||
cvm::log("colvarbias_meta::read_restart() done\n");
|
||||
|
||||
has_data = true;
|
||||
|
||||
if (comm == multiple_replicas) {
|
||||
read_replica_files();
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarbias_meta::read_state_data(std::istream& is)
|
||||
{
|
||||
return read_state_data_template_<std::istream>(is);
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream &colvarbias_meta::read_state_data(cvm::memory_stream &is)
|
||||
{
|
||||
return read_state_data_template_<cvm::memory_stream>(is);
|
||||
}
|
||||
|
||||
|
||||
void colvarbias_meta::rebin_grids_after_restart()
|
||||
{
|
||||
if (rebin_grids) {
|
||||
|
||||
// allocate new grids (based on the new boundaries and widths just
|
||||
@ -1463,9 +1459,9 @@ std::istream & colvarbias_meta::read_state_data(std::istream& is)
|
||||
if (cvm::debug()) {
|
||||
std::ostringstream tmp_os;
|
||||
tmp_os << "hills_energy parameters:\n";
|
||||
hills_energy->write_params(tmp_os);
|
||||
tmp_os << hills_energy->get_state_params();
|
||||
tmp_os << "new_hills_energy parameters:\n";
|
||||
new_hills_energy->write_params(tmp_os);
|
||||
tmp_os << new_hills_energy->get_state_params();
|
||||
cvm::log(tmp_os.str());
|
||||
}
|
||||
|
||||
@ -1495,96 +1491,150 @@ std::istream & colvarbias_meta::read_state_data(std::istream& is)
|
||||
if (!hills.empty())
|
||||
recount_hills_off_grid(hills.begin(), hills.end(), hills_energy);
|
||||
}
|
||||
|
||||
if (use_grids) {
|
||||
if (!hills_off_grid.empty()) {
|
||||
cvm::log(cvm::to_str(hills_off_grid.size())+" hills are near the "
|
||||
"grid boundaries: they will be computed analytically "
|
||||
"and saved to the state files.\n");
|
||||
}
|
||||
}
|
||||
|
||||
colvarbias_ti::read_state_data(is);
|
||||
|
||||
if (cvm::debug())
|
||||
cvm::log("colvarbias_meta::read_restart() done\n");
|
||||
|
||||
has_data = true;
|
||||
|
||||
if (comm != single_replica) {
|
||||
read_replica_files();
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
inline std::istream & reset_istream(std::istream &is, size_t start_pos)
|
||||
template <typename OST>
|
||||
OST &colvarbias_meta::write_hill_template_(OST &os, colvarbias_meta::hill const &h)
|
||||
{
|
||||
bool const formatted = !std::is_same<OST, cvm::memory_stream>::value;
|
||||
|
||||
if (formatted) {
|
||||
os.setf(std::ios::scientific, std::ios::floatfield);
|
||||
}
|
||||
|
||||
write_state_data_key(os, "hill", false);
|
||||
|
||||
if (formatted)
|
||||
os << "{\n";
|
||||
|
||||
write_state_data_key(os, "step", false);
|
||||
if (formatted)
|
||||
os << std::setw(cvm::it_width);
|
||||
os << h.it;
|
||||
if (formatted)
|
||||
os << "\n";
|
||||
|
||||
write_state_data_key(os, "weight", false);
|
||||
if (formatted)
|
||||
os << std::setprecision(cvm::en_prec) << std::setw(cvm::en_width);
|
||||
os << h.W;
|
||||
if (formatted)
|
||||
os << "\n";
|
||||
|
||||
size_t i;
|
||||
write_state_data_key(os, "centers", false);
|
||||
for (i = 0; i < (h.centers).size(); i++) {
|
||||
if (formatted)
|
||||
os << " " << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width);
|
||||
os << h.centers[i];
|
||||
}
|
||||
if (formatted)
|
||||
os << "\n";
|
||||
|
||||
// For backward compatibility, write the widths instead of the sigmas
|
||||
write_state_data_key(os, "widths", false);
|
||||
for (i = 0; i < (h.sigmas).size(); i++) {
|
||||
if (formatted)
|
||||
os << " " << std::setprecision(cvm::cv_prec) << std::setw(cvm::cv_width);
|
||||
os << 2.0 * h.sigmas[i];
|
||||
}
|
||||
if (formatted)
|
||||
os << "\n";
|
||||
|
||||
if (h.replica.size()) {
|
||||
write_state_data_key(os, "replicaID", false);
|
||||
os << h.replica;
|
||||
if (formatted)
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
if (formatted)
|
||||
os << "}\n";
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
std::ostream &colvarbias_meta::write_hill(std::ostream &os, colvarbias_meta::hill const &h)
|
||||
{
|
||||
return write_hill_template_<std::ostream>(os, h);
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream &colvarbias_meta::write_hill(cvm::memory_stream &os,
|
||||
colvarbias_meta::hill const &h)
|
||||
{
|
||||
return write_hill_template_<cvm::memory_stream>(os, h);
|
||||
}
|
||||
|
||||
|
||||
template <typename IST> IST &hill_stream_error(IST &is, size_t start_pos, std::string const &key)
|
||||
{
|
||||
is.clear();
|
||||
is.seekg(start_pos, std::ios::beg);
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
cvm::error("Error: in reading data for keyword \"" + key + "\" from stream.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarbias_meta::read_hill(std::istream &is)
|
||||
template <typename IST> IST &colvarbias_meta::read_hill_template_(IST &is)
|
||||
{
|
||||
if (!is) return is; // do nothing if failbit is set
|
||||
if (!is)
|
||||
return is; // do nothing if failbit is set
|
||||
|
||||
std::streampos const start_pos = is.tellg();
|
||||
size_t i = 0;
|
||||
bool const formatted = !std::is_same<IST, cvm::memory_stream>::value;
|
||||
|
||||
std::string data;
|
||||
if ( !(is >> read_block("hill", &data)) ) {
|
||||
return reset_istream(is, start_pos);
|
||||
auto const start_pos = is.tellg();
|
||||
|
||||
std::string key;
|
||||
if (!(is >> key) || (key != "hill")) {
|
||||
is.clear();
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
return is;
|
||||
}
|
||||
|
||||
std::istringstream data_is(data);
|
||||
if (formatted) {
|
||||
std::string brace;
|
||||
if (!(is >> brace) || (brace != "{")) {
|
||||
return hill_stream_error<IST>(is, start_pos, "hill");
|
||||
}
|
||||
}
|
||||
|
||||
cvm::step_number h_it = 0L;
|
||||
cvm::real h_weight;
|
||||
cvm::real h_weight = 0.0;
|
||||
std::vector<colvarvalue> h_centers(num_variables());
|
||||
for (i = 0; i < num_variables(); i++) {
|
||||
for (size_t i = 0; i < num_variables(); i++) {
|
||||
h_centers[i].type(variables(i)->value());
|
||||
}
|
||||
std::vector<cvm::real> h_sigmas(num_variables());
|
||||
std::string h_replica;
|
||||
|
||||
std::string keyword;
|
||||
while (data_is >> keyword) {
|
||||
|
||||
if (keyword == "step") {
|
||||
if ( !(data_is >> h_it)) {
|
||||
return reset_istream(is, start_pos);
|
||||
if (!read_state_data_key(is, "step") || !(is >> h_it)) {
|
||||
return hill_stream_error<IST>(is, start_pos, "step");
|
||||
}
|
||||
if ((h_it <= state_file_step) && !restart_keep_hills) {
|
||||
if (cvm::debug())
|
||||
cvm::log("Skipping a hill older than the state file for metadynamics bias \""+
|
||||
this->name+"\""+
|
||||
((comm != single_replica) ? ", replica \""+replica_id+"\"" : "")+"\n");
|
||||
return is;
|
||||
|
||||
if (read_state_data_key(is, "weight")) {
|
||||
if (!(is >> h_weight)) {
|
||||
return hill_stream_error<IST>(is, start_pos, "weight");
|
||||
}
|
||||
}
|
||||
|
||||
if (keyword == "weight") {
|
||||
if ( !(data_is >> h_weight)) {
|
||||
return reset_istream(is, start_pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (keyword == "centers") {
|
||||
for (i = 0; i < num_variables(); i++) {
|
||||
if ( !(data_is >> h_centers[i])) {
|
||||
return reset_istream(is, start_pos);
|
||||
if (read_state_data_key(is, "centers")) {
|
||||
for (size_t i = 0; i < num_variables(); i++) {
|
||||
if (!(is >> h_centers[i])) {
|
||||
return hill_stream_error<IST>(is, start_pos, "centers");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (keyword == "widths") {
|
||||
for (i = 0; i < num_variables(); i++) {
|
||||
if ( !(data_is >> h_sigmas[i])) {
|
||||
return reset_istream(is, start_pos);
|
||||
if (read_state_data_key(is, "widths")) {
|
||||
for (size_t i = 0; i < num_variables(); i++) {
|
||||
if (!(is >> h_sigmas[i])) {
|
||||
return hill_stream_error<IST>(is, start_pos, "widths");
|
||||
}
|
||||
// For backward compatibility, read the widths instead of the sigmas
|
||||
h_sigmas[i] /= 2.0;
|
||||
@ -1592,17 +1642,31 @@ std::istream & colvarbias_meta::read_hill(std::istream &is)
|
||||
}
|
||||
|
||||
if (comm != single_replica) {
|
||||
if (keyword == "replicaID") {
|
||||
if ( !(data_is >> h_replica)) {
|
||||
return reset_istream(is, start_pos);
|
||||
if (read_state_data_key(is, "replicaID")) {
|
||||
if (!(is >> h_replica)) {
|
||||
return hill_stream_error<IST>(is, start_pos, "replicaID");
|
||||
}
|
||||
if (h_replica != replica_id) {
|
||||
cvm::error("Error: trying to read a hill created by replica \""+
|
||||
h_replica+"\" for replica \""+replica_id+
|
||||
"\"; did you swap output files?\n", COLVARS_INPUT_ERROR);
|
||||
cvm::error("Error: trying to read a hill created by replica \"" + h_replica +
|
||||
"\" for replica \"" + replica_id + "\"; did you swap output files?\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return hill_stream_error<IST>(is, start_pos, "replicaID");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (formatted) {
|
||||
std::string brace;
|
||||
if (!(is >> brace) || (brace != "}")) {
|
||||
return hill_stream_error<IST>(is, start_pos, "hill");
|
||||
}
|
||||
}
|
||||
|
||||
if ((h_it <= state_file_step) && !restart_keep_hills) {
|
||||
if (cvm::debug())
|
||||
cvm::log("Skipping a hill older than the state file for metadynamics bias \"" + this->name +
|
||||
"\"" + ((comm != single_replica) ? ", replica \"" + replica_id + "\"" : "") + "\n");
|
||||
return is;
|
||||
}
|
||||
|
||||
hill_iter const hills_end = hills.end();
|
||||
@ -1628,6 +1692,18 @@ std::istream & colvarbias_meta::read_hill(std::istream &is)
|
||||
}
|
||||
|
||||
|
||||
std::istream &colvarbias_meta::read_hill(std::istream &is)
|
||||
{
|
||||
return read_hill_template_<std::istream>(is);
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream &colvarbias_meta::read_hill(cvm::memory_stream &is)
|
||||
{
|
||||
return read_hill_template_<cvm::memory_stream>(is);
|
||||
}
|
||||
|
||||
|
||||
int colvarbias_meta::setup_output()
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
@ -1644,7 +1720,10 @@ int colvarbias_meta::setup_output()
|
||||
|
||||
// TODO: one may want to specify the path manually for intricated filesystems?
|
||||
char *pwd = new char[3001];
|
||||
if (GETCWD(pwd, 3000) == NULL) {
|
||||
if (GETCWD(pwd, 3000) == nullptr) {
|
||||
if (pwd != nullptr) { //
|
||||
delete[] pwd;
|
||||
}
|
||||
return cvm::error("Error: cannot get the path of the current working directory.\n",
|
||||
COLVARS_BUG_ERROR);
|
||||
}
|
||||
@ -1701,7 +1780,7 @@ int colvarbias_meta::setup_output()
|
||||
|
||||
// if we're running without grids, use a growing list of "hills" files
|
||||
// otherwise, just one state file and one "hills" file as buffer
|
||||
std::ostream &list_os = cvm::proxy->output_stream(replica_list_file);
|
||||
std::ostream &list_os = cvm::proxy->output_stream(replica_list_file, "replica list file");
|
||||
if (list_os) {
|
||||
list_os << "stateFile " << replica_state_file << "\n";
|
||||
list_os << "hillsFile " << replica_hills_file << "\n";
|
||||
@ -1723,7 +1802,7 @@ int colvarbias_meta::setup_output()
|
||||
|
||||
if (b_hills_traj) {
|
||||
std::ostream &hills_traj_os =
|
||||
cvm::proxy->output_stream(hills_traj_file_name());
|
||||
cvm::proxy->output_stream(hills_traj_file_name(), "hills trajectory file");
|
||||
if (!hills_traj_os) {
|
||||
error_code |= COLVARS_FILE_ERROR;
|
||||
}
|
||||
@ -1757,36 +1836,32 @@ std::string const colvarbias_meta::get_state_params() const
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarbias_meta::write_state_data(std::ostream& os)
|
||||
template <typename OST> OST &colvarbias_meta::write_state_data_template_(OST &os)
|
||||
{
|
||||
if (use_grids) {
|
||||
|
||||
// this is a very good time to project hills, if you haven't done
|
||||
// it already!
|
||||
project_hills(new_hills_begin, hills.end(),
|
||||
hills_energy, hills_energy_gradients);
|
||||
project_hills(new_hills_begin, hills.end(), hills_energy, hills_energy_gradients);
|
||||
new_hills_begin = hills.end();
|
||||
|
||||
// write down the grids to the restart file
|
||||
os << " hills_energy\n";
|
||||
write_state_data_key(os, "hills_energy");
|
||||
hills_energy->write_restart(os);
|
||||
os << " hills_energy_gradients\n";
|
||||
write_state_data_key(os, "hills_energy_gradients");
|
||||
hills_energy_gradients->write_restart(os);
|
||||
}
|
||||
|
||||
if ( (!use_grids) || keep_hills ) {
|
||||
if ((!use_grids) || keep_hills) {
|
||||
// write all hills currently in memory
|
||||
for (std::list<hill>::const_iterator h = this->hills.begin();
|
||||
h != this->hills.end();
|
||||
h++) {
|
||||
os << *h;
|
||||
for (std::list<hill>::const_iterator h = this->hills.begin(); h != this->hills.end(); h++) {
|
||||
write_hill(os, *h);
|
||||
}
|
||||
} else {
|
||||
// write just those that are near the grid boundaries
|
||||
for (std::list<hill>::const_iterator h = this->hills_off_grid.begin();
|
||||
h != this->hills_off_grid.end();
|
||||
h++) {
|
||||
os << *h;
|
||||
h != this->hills_off_grid.end(); h++) {
|
||||
write_hill(os, *h);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1795,6 +1870,18 @@ std::ostream & colvarbias_meta::write_state_data(std::ostream& os)
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarbias_meta::write_state_data(std::ostream& os)
|
||||
{
|
||||
return write_state_data_template_<std::ostream>(os);
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream &colvarbias_meta::write_state_data(cvm::memory_stream &os)
|
||||
{
|
||||
return write_state_data_template_<cvm::memory_stream>(os);
|
||||
}
|
||||
|
||||
|
||||
int colvarbias_meta::write_state_to_replicas()
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
@ -1816,6 +1903,15 @@ int colvarbias_meta::write_output_files()
|
||||
if (dump_fes) {
|
||||
write_pmf();
|
||||
}
|
||||
if (b_hills_traj) {
|
||||
std::ostream &hills_traj_os =
|
||||
cvm::proxy->output_stream(hills_traj_file_name(), "hills trajectory file");
|
||||
hills_traj_os << hills_traj_os_buf.str();
|
||||
cvm::proxy->flush_output_stream(hills_traj_file_name());
|
||||
// clear the buffer
|
||||
hills_traj_os_buf.str("");
|
||||
hills_traj_os_buf.clear();
|
||||
}
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
@ -1915,7 +2011,7 @@ int colvarbias_meta::write_replica_state_file()
|
||||
// Write to temporary state file
|
||||
std::string const tmp_state_file(replica_state_file+".tmp");
|
||||
error_code |= proxy->remove_file(tmp_state_file);
|
||||
std::ostream &rep_state_os = cvm::proxy->output_stream(tmp_state_file);
|
||||
std::ostream &rep_state_os = cvm::proxy->output_stream(tmp_state_file, "temporary state file");
|
||||
if (rep_state_os) {
|
||||
if (!write_state(rep_state_os)) {
|
||||
error_code |= cvm::error("Error: in writing to temporary file \""+
|
||||
@ -1934,11 +2030,11 @@ int colvarbias_meta::reopen_replica_buffer_file()
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
colvarproxy *proxy = cvm::proxy;
|
||||
if (proxy->output_stream(replica_hills_file)) {
|
||||
if (proxy->output_stream(replica_hills_file, "replica hills file")) {
|
||||
error_code |= proxy->close_output_stream(replica_hills_file);
|
||||
}
|
||||
error_code |= proxy->remove_file(replica_hills_file);
|
||||
std::ostream &replica_hills_os = proxy->output_stream(replica_hills_file);
|
||||
std::ostream &replica_hills_os = proxy->output_stream(replica_hills_file, "replica hills file");
|
||||
if (replica_hills_os) {
|
||||
replica_hills_os.setf(std::ios::scientific, std::ios::floatfield);
|
||||
} else {
|
||||
@ -2037,43 +2133,3 @@ colvarbias_meta::hill::operator = (colvarbias_meta::hill const &h)
|
||||
|
||||
colvarbias_meta::hill::~hill()
|
||||
{}
|
||||
|
||||
|
||||
std::ostream & operator << (std::ostream &os, colvarbias_meta::hill const &h)
|
||||
{
|
||||
os.setf(std::ios::scientific, std::ios::floatfield);
|
||||
|
||||
os << "hill {\n";
|
||||
os << " step " << std::setw(cvm::it_width) << h.it << "\n";
|
||||
os << " weight "
|
||||
<< std::setprecision(cvm::en_prec)
|
||||
<< std::setw(cvm::en_width)
|
||||
<< h.W << "\n";
|
||||
|
||||
if (h.replica.size())
|
||||
os << " replicaID " << h.replica << "\n";
|
||||
|
||||
size_t i;
|
||||
os << " centers ";
|
||||
for (i = 0; i < (h.centers).size(); i++) {
|
||||
os << " "
|
||||
<< std::setprecision(cvm::cv_prec)
|
||||
<< std::setw(cvm::cv_width)
|
||||
<< h.centers[i];
|
||||
}
|
||||
os << "\n";
|
||||
|
||||
// For backward compatibility, write the widths instead of the sigmas
|
||||
os << " widths ";
|
||||
for (i = 0; i < (h.sigmas).size(); i++) {
|
||||
os << " "
|
||||
<< std::setprecision(cvm::cv_prec)
|
||||
<< std::setw(cvm::cv_width)
|
||||
<< 2.0 * h.sigmas[i];
|
||||
}
|
||||
os << "\n";
|
||||
|
||||
os << "}\n";
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include "colvarbias.h"
|
||||
#include "colvargrid.h"
|
||||
|
||||
|
||||
/// Metadynamics bias (implementation of \link colvarbias \endlink)
|
||||
class colvarbias_meta
|
||||
: public virtual colvarbias,
|
||||
@ -51,14 +52,32 @@ public:
|
||||
virtual int update_bias();
|
||||
virtual int update_grid_data();
|
||||
virtual int replica_share();
|
||||
virtual size_t replica_share_freq() const;
|
||||
|
||||
virtual int calc_energy(std::vector<colvarvalue> const *values);
|
||||
virtual int calc_forces(std::vector<colvarvalue> const *values);
|
||||
|
||||
virtual std::string const get_state_params() const;
|
||||
virtual int set_state_params(std::string const &state_conf);
|
||||
virtual std::ostream & write_state_data(std::ostream &os);
|
||||
virtual std::istream & read_state_data(std::istream &os);
|
||||
|
||||
virtual std::ostream &write_state_data(std::ostream &os);
|
||||
virtual cvm::memory_stream &write_state_data(cvm::memory_stream &os);
|
||||
virtual std::istream &read_state_data(std::istream &is);
|
||||
virtual cvm::memory_stream &read_state_data(cvm::memory_stream &is);
|
||||
|
||||
private:
|
||||
|
||||
template <typename IST, typename GT>
|
||||
IST &read_grid_data_template_(IST &is, std::string const &key, GT *grid, GT *backup_grid);
|
||||
|
||||
template <typename IST> IST &read_state_data_template_(IST &is);
|
||||
|
||||
template <typename OST> OST &write_state_data_template_(OST &os);
|
||||
|
||||
public:
|
||||
|
||||
/// Function called by read_state_data() to execute rebinning (if requested)
|
||||
void rebin_grids_after_restart();
|
||||
|
||||
virtual int setup_output();
|
||||
virtual int write_output_files();
|
||||
@ -107,9 +126,22 @@ protected:
|
||||
void recount_hills_off_grid(hill_iter h_first, hill_iter h_last,
|
||||
colvar_grid_scalar *ge);
|
||||
|
||||
/// Read a hill from a file
|
||||
template <typename OST> OST &write_hill_template_(OST &os, colvarbias_meta::hill const &h);
|
||||
|
||||
/// Write a hill to a formatted stream
|
||||
std::ostream &write_hill(std::ostream &os, hill const &h);
|
||||
|
||||
/// Write a hill to an unformatted stream
|
||||
cvm::memory_stream &write_hill(cvm::memory_stream &os, hill const &h);
|
||||
|
||||
template <typename IST> IST &read_hill_template_(IST &is);
|
||||
|
||||
/// Read a new hill from a formatted stream
|
||||
std::istream & read_hill(std::istream &is);
|
||||
|
||||
/// Read a new hill from an unformatted stream
|
||||
cvm::memory_stream & read_hill(cvm::memory_stream &is);
|
||||
|
||||
/// \brief Add a new hill; if a .hills trajectory is written,
|
||||
/// write it there; if there is more than one replica, communicate
|
||||
/// it to the others
|
||||
@ -230,7 +262,7 @@ protected:
|
||||
std::vector<colvarbias_meta *> replicas;
|
||||
|
||||
/// \brief Frequency at which data the "mirror" biases are updated
|
||||
size_t replica_update_freq;
|
||||
size_t replica_update_freq = 0;
|
||||
|
||||
/// List of replicas (and their output list files): contents are
|
||||
/// copied into replicas_registry for convenience
|
||||
@ -258,6 +290,8 @@ protected:
|
||||
/// Position within replica_hills_file (when reading it)
|
||||
std::streampos replica_hills_file_pos;
|
||||
|
||||
/// Cache of the hills trajectory
|
||||
std::ostringstream hills_traj_os_buf;
|
||||
};
|
||||
|
||||
|
||||
@ -399,9 +433,6 @@ public:
|
||||
/// Represent the hill ina string suitable for a trajectory file
|
||||
std::string output_traj();
|
||||
|
||||
/// Write the hill to an output stream
|
||||
friend std::ostream & operator << (std::ostream &os, hill const &h);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -27,7 +27,10 @@ colvarbias_restraint::colvarbias_restraint(char const *key)
|
||||
|
||||
int colvarbias_restraint::init(std::string const &conf)
|
||||
{
|
||||
colvarbias::init(conf);
|
||||
int err = colvarbias::init(conf);
|
||||
if (err != COLVARS_OK) {
|
||||
return err;
|
||||
}
|
||||
enable(f_cvb_apply_force);
|
||||
|
||||
colvarbias_ti::init(conf);
|
||||
@ -202,6 +205,8 @@ int colvarbias_restraint_moving::init(std::string const &conf)
|
||||
|
||||
first_step = cvm::step_absolute();
|
||||
|
||||
cvm::log("Initial step for restraint change: " + cvm::to_str(first_step) + "\n");
|
||||
|
||||
get_keyval(conf, "targetNumSteps", target_nsteps, target_nsteps);
|
||||
if (!target_nsteps) {
|
||||
cvm::error("Error: targetNumSteps must be non-zero.\n", COLVARS_INPUT_ERROR);
|
||||
@ -232,10 +237,9 @@ std::string const colvarbias_restraint_moving::get_state_params() const
|
||||
std::ostringstream os;
|
||||
os.setf(std::ios::scientific, std::ios::floatfield);
|
||||
if (b_chg_centers || b_chg_force_k) {
|
||||
// TODO move this
|
||||
os << "firstStep " << std::setw(cvm::it_width) << first_step << "\n";
|
||||
if (target_nstages) {
|
||||
os << "stage " << std::setw(cvm::it_width)
|
||||
<< stage << "\n";
|
||||
os << "stage " << std::setw(cvm::it_width) << stage << "\n";
|
||||
}
|
||||
}
|
||||
return os.str();
|
||||
@ -245,6 +249,12 @@ std::string const colvarbias_restraint_moving::get_state_params() const
|
||||
int colvarbias_restraint_moving::set_state_params(std::string const &conf)
|
||||
{
|
||||
if (b_chg_centers || b_chg_force_k) {
|
||||
auto first_step_flags = colvarparse::parse_restart;
|
||||
if (cvm::main()->restart_version_number() > 20230906) {
|
||||
// Only require the first step when the code could produce it
|
||||
first_step_flags = colvarparse::parse_restart | colvarparse::parse_required;
|
||||
}
|
||||
get_keyval(conf, "firstStep", first_step, first_step, first_step_flags);
|
||||
if (target_nstages) {
|
||||
get_keyval(conf, "stage", stage, stage,
|
||||
colvarparse::parse_restart | colvarparse::parse_required);
|
||||
@ -837,18 +847,6 @@ int colvarbias_restraint_harmonic::set_state_params(std::string const &conf)
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarbias_restraint_harmonic::write_state_data(std::ostream &os)
|
||||
{
|
||||
return colvarbias_ti::write_state_data(os);
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarbias_restraint_harmonic::read_state_data(std::istream &is)
|
||||
{
|
||||
return colvarbias_ti::read_state_data(is);
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarbias_restraint_harmonic::write_traj_label(std::ostream &os)
|
||||
{
|
||||
colvarbias_restraint::write_traj_label(os);
|
||||
@ -1136,18 +1134,6 @@ int colvarbias_restraint_harmonic_walls::set_state_params(std::string const &con
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarbias_restraint_harmonic_walls::write_state_data(std::ostream &os)
|
||||
{
|
||||
return colvarbias_ti::write_state_data(os);
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarbias_restraint_harmonic_walls::read_state_data(std::istream &is)
|
||||
{
|
||||
return colvarbias_ti::read_state_data(is);
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarbias_restraint_harmonic_walls::write_traj_label(std::ostream &os)
|
||||
{
|
||||
colvarbias_restraint::write_traj_label(os);
|
||||
@ -1293,18 +1279,6 @@ int colvarbias_restraint_linear::set_state_params(std::string const &conf)
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarbias_restraint_linear::write_state_data(std::ostream &os)
|
||||
{
|
||||
return colvarbias_ti::write_state_data(os);
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarbias_restraint_linear::read_state_data(std::istream &is)
|
||||
{
|
||||
return colvarbias_ti::read_state_data(is);
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarbias_restraint_linear::write_traj_label(std::ostream &os)
|
||||
{
|
||||
colvarbias_restraint::write_traj_label(os);
|
||||
@ -1338,7 +1312,10 @@ int colvarbias_restraint_histogram::init(std::string const &conf)
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
|
||||
colvarbias::init(conf);
|
||||
int err = colvarbias::init(conf);
|
||||
if (err != COLVARS_OK) {
|
||||
return err;
|
||||
}
|
||||
enable(f_cvb_apply_force);
|
||||
|
||||
cvm::main()->cite_feature("histogramRestraint colvar bias implementation");
|
||||
|
||||
@ -38,9 +38,6 @@ public:
|
||||
|
||||
virtual std::string const get_state_params() const;
|
||||
virtual int set_state_params(std::string const &conf);
|
||||
// virtual std::ostream & write_state_data(std::ostream &os);
|
||||
// virtual std::istream & read_state_data(std::istream &os);
|
||||
|
||||
virtual std::ostream & write_traj_label(std::ostream &os);
|
||||
virtual std::ostream & write_traj(std::ostream &os);
|
||||
|
||||
@ -242,8 +239,6 @@ public:
|
||||
virtual int update();
|
||||
virtual std::string const get_state_params() const;
|
||||
virtual int set_state_params(std::string const &conf);
|
||||
virtual std::ostream & write_state_data(std::ostream &os);
|
||||
virtual std::istream & read_state_data(std::istream &os);
|
||||
virtual std::ostream & write_traj_label(std::ostream &os);
|
||||
virtual std::ostream & write_traj(std::ostream &os);
|
||||
virtual int change_configuration(std::string const &conf);
|
||||
@ -269,8 +264,6 @@ public:
|
||||
virtual int update();
|
||||
virtual std::string const get_state_params() const;
|
||||
virtual int set_state_params(std::string const &conf);
|
||||
virtual std::ostream & write_state_data(std::ostream &os);
|
||||
virtual std::istream & read_state_data(std::istream &os);
|
||||
virtual std::ostream & write_traj_label(std::ostream &os);
|
||||
virtual std::ostream & write_traj(std::ostream &os);
|
||||
|
||||
@ -311,8 +304,6 @@ public:
|
||||
|
||||
virtual std::string const get_state_params() const;
|
||||
virtual int set_state_params(std::string const &conf);
|
||||
virtual std::ostream & write_state_data(std::ostream &os);
|
||||
virtual std::istream & read_state_data(std::istream &os);
|
||||
virtual std::ostream & write_traj_label(std::ostream &os);
|
||||
virtual std::ostream & write_traj(std::ostream &os);
|
||||
|
||||
|
||||
@ -19,45 +19,40 @@
|
||||
colvar::cvc::cvc()
|
||||
{
|
||||
description = "uninitialized colvar component";
|
||||
b_try_scalable = true;
|
||||
sup_coeff = 1.0;
|
||||
sup_np = 1;
|
||||
period = 0.0;
|
||||
wrap_center = 0.0;
|
||||
width = 0.0;
|
||||
cvc::init_dependencies();
|
||||
}
|
||||
|
||||
|
||||
colvar::cvc::cvc(std::string const &conf)
|
||||
int colvar::cvc::update_description()
|
||||
{
|
||||
description = "uninitialized colvar component";
|
||||
b_try_scalable = true;
|
||||
sup_coeff = 1.0;
|
||||
sup_np = 1;
|
||||
period = 0.0;
|
||||
wrap_center = 0.0;
|
||||
width = 0.0;
|
||||
init_dependencies();
|
||||
colvar::cvc::init(conf);
|
||||
if (name.size() > 0) {
|
||||
description = "cvc \"" + name + "\"";
|
||||
} else {
|
||||
description = "unnamed cvc";
|
||||
}
|
||||
description += " of type \"" + function_type() + "\"";
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
std::string colvar::cvc::function_type() const
|
||||
{
|
||||
if (function_types.empty()) {
|
||||
return "unset";
|
||||
}
|
||||
return function_types.back();
|
||||
}
|
||||
|
||||
|
||||
int colvar::cvc::set_function_type(std::string const &type)
|
||||
{
|
||||
function_type = type;
|
||||
if (function_types.size() == 0) {
|
||||
function_types.push_back(function_type);
|
||||
} else {
|
||||
if (function_types.back() != function_type) {
|
||||
function_types.push_back(function_type);
|
||||
}
|
||||
}
|
||||
function_types.push_back(type);
|
||||
update_description();
|
||||
cvm::main()->cite_feature(function_types[0]+" colvar component");
|
||||
for (size_t i = function_types.size()-1; i > 0; i--) {
|
||||
cvm::main()->cite_feature(function_types[i]+" colvar component"+
|
||||
" (derived from "+function_types[i-1]+")");
|
||||
}
|
||||
cvm::main()->cite_feature(function_types[0]+" colvar component");
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
@ -67,6 +62,8 @@ int colvar::cvc::init(std::string const &conf)
|
||||
if (cvm::debug())
|
||||
cvm::log("Initializing cvc base object.\n");
|
||||
|
||||
int error_code = COLVARS_OK;
|
||||
|
||||
std::string const old_name(name);
|
||||
|
||||
if (name.size() > 0) {
|
||||
@ -74,18 +71,14 @@ int colvar::cvc::init(std::string const &conf)
|
||||
}
|
||||
|
||||
if (get_keyval(conf, "name", name, name)) {
|
||||
if (name.size() > 0) {
|
||||
description = "cvc \"" + name + "\" of type " + function_type;
|
||||
} else {
|
||||
description = "unnamed cvc";
|
||||
}
|
||||
if ((name != old_name) && (old_name.size() > 0)) {
|
||||
cvm::error("Error: cannot rename component \""+old_name+
|
||||
"\" after initialization (new name = \""+name+"\")",
|
||||
error_code |= cvm::error("Error: cannot rename component \"" + old_name +
|
||||
"\" after initialization (new name = \"" + name + "\")",
|
||||
COLVARS_INPUT_ERROR);
|
||||
name = old_name;
|
||||
}
|
||||
}
|
||||
update_description();
|
||||
|
||||
get_keyval(conf, "componentCoeff", sup_coeff, sup_coeff);
|
||||
get_keyval(conf, "componentExp", sup_np, sup_np);
|
||||
@ -102,6 +95,24 @@ int colvar::cvc::init(std::string const &conf)
|
||||
register_param("period", reinterpret_cast<void *>(&period));
|
||||
register_param("wrapAround", reinterpret_cast<void *>(&wrap_center));
|
||||
|
||||
if (period != 0.0) {
|
||||
if (!is_available(f_cvc_periodic)) {
|
||||
error_code |=
|
||||
cvm::error("Error: invalid use of period and/or "
|
||||
"wrapAround in a \"" +
|
||||
function_type() + "\" component.\n" + "Period: " + cvm::to_str(period) +
|
||||
" wrapAround: " + cvm::to_str(wrap_center),
|
||||
COLVARS_INPUT_ERROR);
|
||||
} else {
|
||||
enable(f_cvc_periodic);
|
||||
}
|
||||
}
|
||||
|
||||
if ((wrap_center != 0.0) && !is_enabled(f_cvc_periodic)) {
|
||||
error_code |= cvm::error("Error: wrapAround was defined for a non-periodic component.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
get_keyval_feature(this, conf, "debugGradients",
|
||||
f_cvc_debug_gradient, false, parse_silent);
|
||||
|
||||
@ -119,7 +130,7 @@ int colvar::cvc::init(std::string const &conf)
|
||||
if (cvm::debug())
|
||||
cvm::log("Done initializing cvc base object.\n");
|
||||
|
||||
return cvm::get_error();
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
@ -157,10 +168,13 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf,
|
||||
char const *group_key,
|
||||
bool optional)
|
||||
{
|
||||
cvm::atom_group *group = NULL;
|
||||
int error_code = COLVARS_OK;
|
||||
|
||||
cvm::atom_group *group = nullptr;
|
||||
std::string group_conf;
|
||||
|
||||
if (key_lookup(conf, group_key, &group_conf)) {
|
||||
|
||||
group = new cvm::atom_group(group_key);
|
||||
|
||||
if (b_try_scalable) {
|
||||
@ -177,31 +191,42 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf,
|
||||
// TODO check for other types of parallelism here
|
||||
}
|
||||
|
||||
if (group_conf.size() == 0) {
|
||||
cvm::error("Error: atom group \""+group->key+
|
||||
"\" is set, but has no definition.\n",
|
||||
if (group_conf.empty()) {
|
||||
error_code |= cvm::error("Error: atom group \"" + group->key + "\" has no definition.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
delete group;
|
||||
group = nullptr;
|
||||
// Silence unused variable warning; TODO stop returning a pointer
|
||||
(void) error_code;
|
||||
return group;
|
||||
}
|
||||
|
||||
cvm::increase_depth();
|
||||
if (group->parse(group_conf) == COLVARS_OK) {
|
||||
error_code |= group->parse(group_conf);
|
||||
if (error_code != COLVARS_OK) {
|
||||
error_code |=
|
||||
cvm::error("Error: in definition of atom group \"" + std::string(group_key) + "\".",
|
||||
COLVARS_INPUT_ERROR);
|
||||
delete group;
|
||||
group = nullptr;
|
||||
} else {
|
||||
register_atom_group(group);
|
||||
}
|
||||
group->check_keywords(group_conf, group_key);
|
||||
if (cvm::get_error()) {
|
||||
cvm::error("Error parsing definition for atom group \""+
|
||||
std::string(group_key)+"\".", COLVARS_INPUT_ERROR);
|
||||
error_code |= group->check_keywords(group_conf, group_key);
|
||||
}
|
||||
cvm::decrease_depth();
|
||||
|
||||
} else {
|
||||
if (! optional) {
|
||||
cvm::error("Error: definition for atom group \""+
|
||||
std::string(group_key)+"\" not found.\n");
|
||||
|
||||
if (!optional) {
|
||||
error_code |=
|
||||
cvm::error("Error: atom group \"" + std::string(group_key) + "\" is required.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
// Silence unused variable warning; TODO stop returning a pointer
|
||||
(void) error_code;
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
@ -228,6 +253,8 @@ int colvar::cvc::init_dependencies() {
|
||||
|
||||
init_feature(f_cvc_upper_boundary, "defined_upper_boundary", f_type_static);
|
||||
|
||||
init_feature(f_cvc_explicit_atom_groups, "explicit_atom_groups", f_type_static);
|
||||
|
||||
init_feature(f_cvc_gradient, "gradient", f_type_dynamic);
|
||||
|
||||
init_feature(f_cvc_explicit_gradient, "explicit_gradient", f_type_static);
|
||||
@ -264,6 +291,7 @@ int colvar::cvc::init_dependencies() {
|
||||
|
||||
init_feature(f_cvc_collect_atom_ids, "collect_atom_ids", f_type_dynamic);
|
||||
require_feature_children(f_cvc_collect_atom_ids, f_ag_collect_atom_ids);
|
||||
require_feature_self(f_cvc_collect_atom_ids, f_cvc_explicit_atom_groups);
|
||||
|
||||
// TODO only enable this when f_ag_scalable can be turned on for a pre-initialized group
|
||||
// require_feature_children(f_cvc_scalable, f_ag_scalable);
|
||||
@ -281,7 +309,7 @@ int colvar::cvc::init_dependencies() {
|
||||
// default as available, not enabled
|
||||
// except dynamic features which default as unavailable
|
||||
feature_states.reserve(f_cvc_ntot);
|
||||
for (i = 0; i < colvardeps::f_cvc_ntot; i++) {
|
||||
for (i = feature_states.size(); i < colvardeps::f_cvc_ntot; i++) {
|
||||
bool avail = is_dynamic(i) ? false : true;
|
||||
feature_states.push_back(feature_state(avail, false));
|
||||
}
|
||||
@ -292,6 +320,8 @@ int colvar::cvc::init_dependencies() {
|
||||
feature_states[f_cvc_gradient].available = true;
|
||||
feature_states[f_cvc_collect_atom_ids].available = true;
|
||||
|
||||
feature_states[f_cvc_periodic].available = false;
|
||||
|
||||
// CVCs are enabled from the start - get disabled based on flags
|
||||
enable(f_cvc_active);
|
||||
|
||||
@ -314,7 +344,7 @@ int colvar::cvc::init_dependencies() {
|
||||
|
||||
int colvar::cvc::setup()
|
||||
{
|
||||
description = "cvc " + name;
|
||||
update_description();
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
@ -349,6 +379,7 @@ void colvar::cvc::init_as_angle()
|
||||
void colvar::cvc::init_as_periodic_angle()
|
||||
{
|
||||
x.type(colvarvalue::type_scalar);
|
||||
provide(f_cvc_periodic);
|
||||
enable(f_cvc_periodic);
|
||||
period = 360.0;
|
||||
init_scalar_boundaries(-180.0, 180.0);
|
||||
@ -372,6 +403,7 @@ void colvar::cvc::register_atom_group(cvm::atom_group *ag)
|
||||
{
|
||||
atom_groups.push_back(ag);
|
||||
add_child(ag);
|
||||
enable(f_cvc_explicit_atom_groups);
|
||||
}
|
||||
|
||||
|
||||
@ -411,29 +443,21 @@ int colvar::cvc::set_param(std::string const ¶m_name,
|
||||
|
||||
void colvar::cvc::read_data()
|
||||
{
|
||||
size_t ig;
|
||||
for (ig = 0; ig < atom_groups.size(); ig++) {
|
||||
cvm::atom_group &atoms = *(atom_groups[ig]);
|
||||
if (is_enabled(f_cvc_explicit_atom_groups)) {
|
||||
for (auto agi = atom_groups.begin(); agi != atom_groups.end(); agi++) {
|
||||
cvm::atom_group &atoms = *(*agi);
|
||||
atoms.reset_atoms_data();
|
||||
atoms.read_positions();
|
||||
atoms.calc_required_properties();
|
||||
// each atom group will take care of its own fitting_group, if defined
|
||||
}
|
||||
|
||||
//// Don't try to get atom velocities, as no back-end currently implements it
|
||||
// if (tasks[task_output_velocity] && !tasks[task_fdiff_velocity]) {
|
||||
// for (i = 0; i < cvcs.size(); i++) {
|
||||
// for (ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
|
||||
// cvcs[i]->atom_groups[ig]->read_velocities();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::vector<int> > colvar::cvc::get_atom_lists()
|
||||
std::vector<std::vector<int>> colvar::cvc::get_atom_lists()
|
||||
{
|
||||
std::vector<std::vector<int> > lists;
|
||||
std::vector<std::vector<int>> lists;
|
||||
|
||||
std::vector<cvm::atom_group *>::iterator agi = atom_groups.begin();
|
||||
for ( ; agi != atom_groups.end(); ++agi) {
|
||||
@ -462,12 +486,12 @@ void colvar::cvc::collect_gradients(std::vector<int> const &atom_ids, std::vecto
|
||||
// If necessary, apply inverse rotation to get atomic
|
||||
// gradient in the laboratory frame
|
||||
if (ag.is_enabled(f_ag_rotate)) {
|
||||
cvm::rotation const rot_inv = ag.rot.inverse();
|
||||
const auto rot_inv = ag.rot.inverse().matrix();
|
||||
|
||||
for (size_t k = 0; k < ag.size(); k++) {
|
||||
size_t a = std::lower_bound(atom_ids.begin(), atom_ids.end(),
|
||||
ag[k].id) - atom_ids.begin();
|
||||
atomic_gradients[a] += coeff * rot_inv.rotate(ag[k].grad);
|
||||
atomic_gradients[a] += coeff * (rot_inv * ag[k].grad);
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -494,7 +518,7 @@ void colvar::cvc::collect_gradients(std::vector<int> const &atom_ids, std::vecto
|
||||
void colvar::cvc::calc_force_invgrads()
|
||||
{
|
||||
cvm::error("Error: calculation of inverse gradients is not implemented "
|
||||
"for colvar components of type \""+function_type+"\".\n",
|
||||
"for colvar components of type \""+function_type()+"\".\n",
|
||||
COLVARS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
@ -502,7 +526,7 @@ void colvar::cvc::calc_force_invgrads()
|
||||
void colvar::cvc::calc_Jacobian_derivative()
|
||||
{
|
||||
cvm::error("Error: calculation of inverse gradients is not implemented "
|
||||
"for colvar components of type \""+function_type+"\".\n",
|
||||
"for colvar components of type \""+function_type()+"\".\n",
|
||||
COLVARS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
@ -515,6 +539,18 @@ void colvar::cvc::calc_fit_gradients()
|
||||
}
|
||||
|
||||
|
||||
void colvar::cvc::apply_force(colvarvalue const &cvforce)
|
||||
{
|
||||
if (is_enabled(f_cvc_explicit_atom_groups)) {
|
||||
for (auto agi = atom_groups.begin(); agi != atom_groups.end(); agi++) {
|
||||
if (!(*agi)->noforce) {
|
||||
(*agi)->apply_colvar_force(cvforce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void colvar::cvc::debug_gradients()
|
||||
{
|
||||
// this function should work for any scalar cvc:
|
||||
@ -528,8 +564,8 @@ void colvar::cvc::debug_gradients()
|
||||
cvm::atom_group *group = atom_groups[ig];
|
||||
if (group->b_dummy) continue;
|
||||
|
||||
cvm::rotation const rot_0 = group->rot;
|
||||
cvm::rotation const rot_inv = group->rot.inverse();
|
||||
const auto rot_0 = group->rot.matrix();
|
||||
const auto rot_inv = group->rot.inverse().matrix();
|
||||
|
||||
cvm::real x_0 = x.real_value;
|
||||
if ((x.type() == colvarvalue::type_vector) && (x.size() == 1)) x_0 = x[0];
|
||||
@ -550,7 +586,7 @@ void colvar::cvc::debug_gradients()
|
||||
cvm::log((group->fitting_group ? std::string("refPosGroup") : group->key) +
|
||||
"[" + cvm::to_str(j) + "] = " +
|
||||
(group->is_enabled(f_ag_rotate) ?
|
||||
cvm::to_str(rot_0.rotate(group_for_fit->fit_gradients[j])) :
|
||||
cvm::to_str(rot_0 * (group_for_fit->fit_gradients[j])) :
|
||||
cvm::to_str(group_for_fit->fit_gradients[j])));
|
||||
}
|
||||
}
|
||||
@ -561,7 +597,7 @@ void colvar::cvc::debug_gradients()
|
||||
|
||||
// tests are best conducted in the unrotated (simulation) frame
|
||||
cvm::rvector const atom_grad = (group->is_enabled(f_ag_rotate) ?
|
||||
rot_inv.rotate((*group)[ia].grad) :
|
||||
rot_inv * ((*group)[ia].grad) :
|
||||
(*group)[ia].grad);
|
||||
gradient_sum += atom_grad;
|
||||
|
||||
@ -634,34 +670,43 @@ void colvar::cvc::debug_gradients()
|
||||
}
|
||||
|
||||
|
||||
cvm::real colvar::cvc::dist2(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
cvm::real colvar::cvc::dist2(colvarvalue const &x1, colvarvalue const &x2) const
|
||||
{
|
||||
return x1.dist2(x2);
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
if (is_enabled(f_cvc_periodic)) {
|
||||
cvm::real const shift = cvm::floor(diff / period + 0.5);
|
||||
diff -= shift * period;
|
||||
}
|
||||
return diff * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::cvc::dist2_lgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
colvarvalue colvar::cvc::dist2_lgrad(colvarvalue const &x1, colvarvalue const &x2) const
|
||||
{
|
||||
return x1.dist2_grad(x2);
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
if (is_enabled(f_cvc_periodic)) {
|
||||
cvm::real const shift = cvm::floor(diff / period + 0.5);
|
||||
diff -= shift * period;
|
||||
}
|
||||
return 2.0 * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::cvc::dist2_rgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
colvarvalue colvar::cvc::dist2_rgrad(colvarvalue const &x1, colvarvalue const &x2) const
|
||||
{
|
||||
return x2.dist2_grad(x1);
|
||||
return cvc::dist2_lgrad(x1, x2);
|
||||
}
|
||||
|
||||
|
||||
void colvar::cvc::wrap(colvarvalue & /* x_unwrapped */) const
|
||||
void colvar::cvc::wrap(colvarvalue &x_unwrapped) const
|
||||
{
|
||||
return;
|
||||
if (is_enabled(f_cvc_periodic)) {
|
||||
cvm::real const shift = cvm::floor((x_unwrapped.real_value - wrap_center) / period + 0.5);
|
||||
x_unwrapped.real_value -= shift * period;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Static members
|
||||
|
||||
std::vector<colvardeps::feature *> colvar::cvc::cvc_features;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -12,13 +12,11 @@
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarcomp.h"
|
||||
|
||||
|
||||
colvar::alch_lambda::alch_lambda(std::string const &conf)
|
||||
: cvc(conf)
|
||||
colvar::alch_lambda::alch_lambda()
|
||||
{
|
||||
set_function_type("alchLambda");
|
||||
|
||||
@ -56,12 +54,9 @@ void colvar::alch_lambda::apply_force(colvarvalue const & /* force */)
|
||||
cvm::proxy->set_alch_lambda(x.real_value);
|
||||
}
|
||||
|
||||
simple_scalar_dist_functions(alch_lambda)
|
||||
|
||||
|
||||
|
||||
colvar::alch_Flambda::alch_Flambda(std::string const &conf)
|
||||
: cvc(conf)
|
||||
colvar::alch_Flambda::alch_Flambda()
|
||||
{
|
||||
set_function_type("alch_Flambda");
|
||||
|
||||
@ -103,4 +98,3 @@ void colvar::alch_Flambda::apply_force(colvarvalue const &force)
|
||||
cvm::proxy->indirect_lambda_biasing_force += d2E_dlambda2 * f;
|
||||
}
|
||||
|
||||
simple_scalar_dist_functions(alch_Flambda)
|
||||
|
||||
@ -12,8 +12,7 @@
|
||||
#include "colvarcomp.h"
|
||||
|
||||
|
||||
colvar::angle::angle(std::string const &conf)
|
||||
: cvc(conf)
|
||||
colvar::angle::angle()
|
||||
{
|
||||
set_function_type("angle");
|
||||
init_as_angle();
|
||||
@ -21,26 +20,25 @@ colvar::angle::angle(std::string const &conf)
|
||||
provide(f_cvc_inv_gradient);
|
||||
provide(f_cvc_Jacobian);
|
||||
enable(f_cvc_com_based);
|
||||
}
|
||||
|
||||
|
||||
int colvar::angle::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
|
||||
group1 = parse_group(conf, "group1");
|
||||
group2 = parse_group(conf, "group2");
|
||||
group3 = parse_group(conf, "group3");
|
||||
|
||||
init_total_force_params(conf);
|
||||
error_code |= init_total_force_params(conf);
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
colvar::angle::angle(cvm::atom const &a1,
|
||||
cvm::atom const &a2,
|
||||
cvm::atom const &a3)
|
||||
colvar::angle::angle(cvm::atom const &a1, cvm::atom const &a2, cvm::atom const &a3) : angle()
|
||||
{
|
||||
set_function_type("angle");
|
||||
init_as_angle();
|
||||
|
||||
provide(f_cvc_inv_gradient);
|
||||
provide(f_cvc_Jacobian);
|
||||
enable(f_cvc_com_based);
|
||||
|
||||
group1 = new cvm::atom_group(std::vector<cvm::atom>(1, a1));
|
||||
group2 = new cvm::atom_group(std::vector<cvm::atom>(1, a2));
|
||||
group3 = new cvm::atom_group(std::vector<cvm::atom>(1, a3));
|
||||
@ -120,52 +118,6 @@ void colvar::angle::calc_Jacobian_derivative()
|
||||
}
|
||||
|
||||
|
||||
void colvar::angle::apply_force(colvarvalue const &force)
|
||||
{
|
||||
if (!group1->noforce)
|
||||
group1->apply_colvar_force(force.real_value);
|
||||
|
||||
if (!group2->noforce)
|
||||
group2->apply_colvar_force(force.real_value);
|
||||
|
||||
if (!group3->noforce)
|
||||
group3->apply_colvar_force(force.real_value);
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(angle)
|
||||
|
||||
|
||||
|
||||
colvar::dipole_angle::dipole_angle(std::string const &conf)
|
||||
: cvc(conf)
|
||||
{
|
||||
set_function_type("dipoleAngle");
|
||||
init_as_angle();
|
||||
|
||||
group1 = parse_group(conf, "group1");
|
||||
group2 = parse_group(conf, "group2");
|
||||
group3 = parse_group(conf, "group3");
|
||||
|
||||
init_total_force_params(conf);
|
||||
}
|
||||
|
||||
|
||||
colvar::dipole_angle::dipole_angle(cvm::atom const &a1,
|
||||
cvm::atom const &a2,
|
||||
cvm::atom const &a3)
|
||||
{
|
||||
set_function_type("dipoleAngle");
|
||||
init_as_angle();
|
||||
|
||||
group1 = new cvm::atom_group(std::vector<cvm::atom>(1, a1));
|
||||
group2 = new cvm::atom_group(std::vector<cvm::atom>(1, a2));
|
||||
group3 = new cvm::atom_group(std::vector<cvm::atom>(1, a3));
|
||||
register_atom_group(group1);
|
||||
register_atom_group(group2);
|
||||
register_atom_group(group3);
|
||||
}
|
||||
|
||||
|
||||
colvar::dipole_angle::dipole_angle()
|
||||
{
|
||||
@ -174,6 +126,19 @@ colvar::dipole_angle::dipole_angle()
|
||||
}
|
||||
|
||||
|
||||
int colvar::dipole_angle::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
|
||||
group1 = parse_group(conf, "group1");
|
||||
group2 = parse_group(conf, "group2");
|
||||
group3 = parse_group(conf, "group3");
|
||||
|
||||
error_code |= init_total_force_params(conf);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
void colvar::dipole_angle::calc_value()
|
||||
{
|
||||
cvm::atom_pos const g1_pos = group1->center_of_mass();
|
||||
@ -229,52 +194,35 @@ void colvar::dipole_angle::calc_gradients()
|
||||
}
|
||||
|
||||
|
||||
void colvar::dipole_angle::apply_force(colvarvalue const &force)
|
||||
{
|
||||
if (!group1->noforce)
|
||||
group1->apply_colvar_force(force.real_value);
|
||||
|
||||
if (!group2->noforce)
|
||||
group2->apply_colvar_force(force.real_value);
|
||||
|
||||
if (!group3->noforce)
|
||||
group3->apply_colvar_force(force.real_value);
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(dipole_angle)
|
||||
|
||||
|
||||
|
||||
colvar::dihedral::dihedral(std::string const &conf)
|
||||
: cvc(conf)
|
||||
colvar::dihedral::dihedral()
|
||||
{
|
||||
set_function_type("dihedral");
|
||||
init_as_periodic_angle();
|
||||
provide(f_cvc_inv_gradient);
|
||||
provide(f_cvc_Jacobian);
|
||||
enable(f_cvc_com_based);
|
||||
}
|
||||
|
||||
|
||||
int colvar::dihedral::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
|
||||
group1 = parse_group(conf, "group1");
|
||||
group2 = parse_group(conf, "group2");
|
||||
group3 = parse_group(conf, "group3");
|
||||
group4 = parse_group(conf, "group4");
|
||||
|
||||
init_total_force_params(conf);
|
||||
error_code |= init_total_force_params(conf);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
colvar::dihedral::dihedral(cvm::atom const &a1,
|
||||
cvm::atom const &a2,
|
||||
cvm::atom const &a3,
|
||||
colvar::dihedral::dihedral(cvm::atom const &a1, cvm::atom const &a2, cvm::atom const &a3,
|
||||
cvm::atom const &a4)
|
||||
: dihedral()
|
||||
{
|
||||
set_function_type("dihedral");
|
||||
init_as_periodic_angle();
|
||||
provide(f_cvc_inv_gradient);
|
||||
provide(f_cvc_Jacobian);
|
||||
enable(f_cvc_com_based);
|
||||
|
||||
b_1site_force = false;
|
||||
|
||||
group1 = new cvm::atom_group(std::vector<cvm::atom>(1, a1));
|
||||
@ -288,16 +236,6 @@ colvar::dihedral::dihedral(cvm::atom const &a1,
|
||||
}
|
||||
|
||||
|
||||
colvar::dihedral::dihedral()
|
||||
{
|
||||
set_function_type("dihedral");
|
||||
init_as_periodic_angle();
|
||||
enable(f_cvc_periodic);
|
||||
provide(f_cvc_inv_gradient);
|
||||
provide(f_cvc_Jacobian);
|
||||
}
|
||||
|
||||
|
||||
void colvar::dihedral::calc_value()
|
||||
{
|
||||
cvm::atom_pos const g1_pos = group1->center_of_mass();
|
||||
@ -323,7 +261,7 @@ void colvar::dihedral::calc_value()
|
||||
cvm::real const sin_phi = n1 * r34 * r23.norm();
|
||||
|
||||
x.real_value = (180.0/PI) * cvm::atan2(sin_phi, cos_phi);
|
||||
this->wrap(x);
|
||||
wrap(x);
|
||||
}
|
||||
|
||||
|
||||
@ -349,7 +287,7 @@ void colvar::dihedral::calc_gradients()
|
||||
A *= rA;
|
||||
cvm::rvector const dcosdA = rA*(cos_phi*A-B);
|
||||
cvm::rvector const dcosdB = rB*(cos_phi*B-A);
|
||||
rA = 1.0;
|
||||
// rA = 1.0;
|
||||
|
||||
cvm::real const K = (1.0/sin_phi) * (180.0/PI);
|
||||
|
||||
@ -363,7 +301,7 @@ void colvar::dihedral::calc_gradients()
|
||||
C *= rC;
|
||||
cvm::rvector const dsindC = rC*(sin_phi*C-B);
|
||||
cvm::rvector const dsindB = rB*(sin_phi*B-C);
|
||||
rC = 1.0;
|
||||
// rC = 1.0;
|
||||
|
||||
cvm::real const K = (-1.0/cos_phi) * (180.0/PI);
|
||||
|
||||
@ -439,81 +377,22 @@ void colvar::dihedral::calc_Jacobian_derivative()
|
||||
}
|
||||
|
||||
|
||||
void colvar::dihedral::apply_force(colvarvalue const &force)
|
||||
{
|
||||
if (!group1->noforce)
|
||||
group1->apply_colvar_force(force.real_value);
|
||||
|
||||
if (!group2->noforce)
|
||||
group2->apply_colvar_force(force.real_value);
|
||||
|
||||
if (!group3->noforce)
|
||||
group3->apply_colvar_force(force.real_value);
|
||||
|
||||
if (!group4->noforce)
|
||||
group4->apply_colvar_force(force.real_value);
|
||||
}
|
||||
|
||||
|
||||
// metrics functions for cvc implementations with a periodicity
|
||||
|
||||
cvm::real colvar::dihedral::dist2(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return diff * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::dihedral::dist2_lgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return 2.0 * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::dihedral::dist2_rgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return (-2.0) * diff;
|
||||
}
|
||||
|
||||
|
||||
void colvar::dihedral::wrap(colvarvalue &x_unwrapped) const
|
||||
{
|
||||
if ((x_unwrapped.real_value - wrap_center) >= 180.0) {
|
||||
x_unwrapped.real_value -= 360.0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((x_unwrapped.real_value - wrap_center) < -180.0) {
|
||||
x_unwrapped.real_value += 360.0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
colvar::polar_theta::polar_theta(std::string const &conf)
|
||||
: cvc(conf)
|
||||
{
|
||||
set_function_type("polarTheta");
|
||||
enable(f_cvc_com_based);
|
||||
|
||||
atoms = parse_group(conf, "atoms");
|
||||
init_total_force_params(conf);
|
||||
x.type(colvarvalue::type_scalar);
|
||||
}
|
||||
|
||||
|
||||
colvar::polar_theta::polar_theta()
|
||||
{
|
||||
r = theta = phi = 0.0;
|
||||
set_function_type("polarTheta");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
enable(f_cvc_com_based);
|
||||
init_as_angle();
|
||||
}
|
||||
|
||||
|
||||
int colvar::polar_theta::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
atoms = parse_group(conf, "atoms");
|
||||
error_code |= init_total_force_params(conf);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
@ -540,35 +419,25 @@ void colvar::polar_theta::calc_gradients()
|
||||
}
|
||||
|
||||
|
||||
void colvar::polar_theta::apply_force(colvarvalue const &force)
|
||||
{
|
||||
if (!atoms->noforce)
|
||||
atoms->apply_colvar_force(force.real_value);
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(polar_theta)
|
||||
|
||||
|
||||
colvar::polar_phi::polar_phi(std::string const &conf)
|
||||
: cvc(conf)
|
||||
{
|
||||
set_function_type("polarPhi");
|
||||
init_as_periodic_angle();
|
||||
enable(f_cvc_com_based);
|
||||
|
||||
atoms = parse_group(conf, "atoms");
|
||||
init_total_force_params(conf);
|
||||
}
|
||||
|
||||
|
||||
colvar::polar_phi::polar_phi()
|
||||
{
|
||||
r = theta = phi = 0.0;
|
||||
set_function_type("polarPhi");
|
||||
enable(f_cvc_com_based);
|
||||
init_as_periodic_angle();
|
||||
}
|
||||
|
||||
|
||||
int colvar::polar_phi::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
atoms = parse_group(conf, "atoms");
|
||||
error_code |= init_total_force_params(conf);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
void colvar::polar_phi::calc_value()
|
||||
{
|
||||
cvm::rvector pos = atoms->center_of_mass();
|
||||
@ -587,55 +456,3 @@ void colvar::polar_phi::calc_gradients()
|
||||
(180.0/PI) * cvm::cos(phi) / (r*cvm::sin(theta)),
|
||||
0.));
|
||||
}
|
||||
|
||||
|
||||
void colvar::polar_phi::apply_force(colvarvalue const &force)
|
||||
{
|
||||
if (!atoms->noforce)
|
||||
atoms->apply_colvar_force(force.real_value);
|
||||
}
|
||||
|
||||
|
||||
// Same as dihedral, for polar_phi
|
||||
|
||||
cvm::real colvar::polar_phi::dist2(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return diff * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::polar_phi::dist2_lgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return 2.0 * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::polar_phi::dist2_rgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return (-2.0) * diff;
|
||||
}
|
||||
|
||||
|
||||
void colvar::polar_phi::wrap(colvarvalue &x_unwrapped) const
|
||||
{
|
||||
if ((x_unwrapped.real_value - wrap_center) >= 180.0) {
|
||||
x_unwrapped.real_value -= 360.0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((x_unwrapped.real_value - wrap_center) < -180.0) {
|
||||
x_unwrapped.real_value += 360.0;
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1,78 +1,312 @@
|
||||
#if (__cplusplus >= 201103L)
|
||||
// -*- 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.
|
||||
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarcomp.h"
|
||||
#include "colvar_arithmeticpath.h"
|
||||
|
||||
colvar::aspathCV::aspathCV(std::string const &conf): CVBasedPath(conf) {
|
||||
|
||||
struct ArithmeticPathImpl: public ArithmeticPathCV::ArithmeticPathBase<cvm::real> {
|
||||
std::vector<std::vector<colvarvalue>> frame_element_distances;
|
||||
std::vector<std::vector<colvarvalue>> dsdx;
|
||||
std::vector<std::vector<colvarvalue>> dzdx;
|
||||
template <typename T>
|
||||
void updateCartesianDistanceToReferenceFrames(T* obj) {
|
||||
for (size_t i_frame = 0; i_frame < obj->reference_frames.size(); ++i_frame) {
|
||||
for (size_t i_atom = 0; i_atom < obj->atoms->size(); ++i_atom) {
|
||||
frame_element_distances[i_frame][i_atom] = (*(obj->comp_atoms[i_frame]))[i_atom].pos - obj->reference_frames[i_frame][i_atom];
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
void updateCVDistanceToReferenceFrames(T* obj) {
|
||||
for (size_t i_cv = 0; i_cv < obj->cv.size(); ++i_cv) {
|
||||
obj->cv[i_cv]->calc_value();
|
||||
}
|
||||
for (size_t i_frame = 0; i_frame < obj->ref_cv.size(); ++i_frame) {
|
||||
for (size_t i_cv = 0; i_cv < obj->cv.size(); ++i_cv) {
|
||||
colvarvalue ref_cv_value(obj->ref_cv[i_frame][i_cv]);
|
||||
colvarvalue current_cv_value(obj->cv[i_cv]->value());
|
||||
if (current_cv_value.type() == colvarvalue::type_scalar) {
|
||||
frame_element_distances[i_frame][i_cv] = 0.5 * obj->cv[i_cv]->dist2_lgrad(obj->cv[i_cv]->sup_coeff * (cvm::pow(current_cv_value.real_value, obj->cv[i_cv]->sup_np)), ref_cv_value.real_value);
|
||||
} else {
|
||||
frame_element_distances[i_frame][i_cv] = 0.5 * obj->cv[i_cv]->dist2_lgrad(obj->cv[i_cv]->sup_coeff * current_cv_value, ref_cv_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ArithmeticPathImpl(size_t p_num_elements, size_t p_total_frames, cvm::real p_lambda, const std::vector<cvm::real>& p_weights) {
|
||||
ArithmeticPathCV::ArithmeticPathBase<cvm::real>::initialize(p_num_elements, p_total_frames, p_lambda, p_weights);
|
||||
frame_element_distances.resize(p_total_frames, std::vector<colvarvalue>(p_num_elements, colvarvalue(colvarvalue::Type::type_notset)));
|
||||
dsdx.resize(p_total_frames, std::vector<colvarvalue>(p_num_elements, colvarvalue(colvarvalue::Type::type_notset)));
|
||||
dzdx.resize(p_total_frames, std::vector<colvarvalue>(p_num_elements, colvarvalue(colvarvalue::Type::type_notset)));
|
||||
}
|
||||
cvm::real get_lambda() const {return lambda;}
|
||||
cvm::real compute_s() {
|
||||
cvm::real s;
|
||||
computeValue(frame_element_distances, &s, nullptr);
|
||||
return s;
|
||||
}
|
||||
cvm::real compute_z() {
|
||||
cvm::real z;
|
||||
computeValue(frame_element_distances, nullptr, &z);
|
||||
return z;
|
||||
}
|
||||
void compute_s_derivatives() {
|
||||
computeDerivatives<colvarvalue>(frame_element_distances, &dsdx, nullptr);
|
||||
}
|
||||
void compute_z_derivatives() {
|
||||
computeDerivatives<colvarvalue>(frame_element_distances, nullptr, &dzdx);
|
||||
}
|
||||
// for debug gradients of implicit sub CVs
|
||||
template <typename T>
|
||||
colvarvalue compute_s_analytical_derivative_ij(size_t i, size_t j, cvm::real eps, T* obj) const {
|
||||
ArithmeticPathImpl tmp_left(*this), tmp_right(*this);
|
||||
const size_t value_size = frame_element_distances[i][j].size();
|
||||
colvarvalue result(frame_element_distances[i][j].type());
|
||||
colvarvalue ref_cv_value(obj->ref_cv[i][j]);
|
||||
for (size_t k = 0; k < value_size; ++k) {
|
||||
// get the current CV value
|
||||
colvarvalue current_cv_value(obj->cv[j]->value());
|
||||
// save the old values in frame element distance matrices
|
||||
const auto saved_left = tmp_left.frame_element_distances[i][j][k];
|
||||
const auto saved_right = tmp_right.frame_element_distances[i][j][k];
|
||||
// update frame element distance matrices
|
||||
if (current_cv_value.type() == colvarvalue::type_scalar) {
|
||||
tmp_left.frame_element_distances[i][j] = 0.5 * obj->cv[j]->dist2_lgrad(obj->cv[j]->sup_coeff * (cvm::pow(current_cv_value.real_value - eps, obj->cv[j]->sup_np)), ref_cv_value.real_value);
|
||||
tmp_right.frame_element_distances[i][j] = 0.5 * obj->cv[j]->dist2_lgrad(obj->cv[j]->sup_coeff * (cvm::pow(current_cv_value.real_value + eps, obj->cv[j]->sup_np)), ref_cv_value.real_value);
|
||||
} else {
|
||||
current_cv_value[k] -= eps;
|
||||
tmp_left.frame_element_distances[i][j] = 0.5 * obj->cv[j]->dist2_lgrad(obj->cv[j]->sup_coeff * current_cv_value, ref_cv_value);
|
||||
current_cv_value[k] += eps + eps;
|
||||
tmp_right.frame_element_distances[i][j] = 0.5 * obj->cv[j]->dist2_lgrad(obj->cv[j]->sup_coeff * current_cv_value, ref_cv_value);
|
||||
}
|
||||
const cvm::real s_left = tmp_left.compute_s();
|
||||
const cvm::real s_right = tmp_right.compute_s();
|
||||
result[k] = (s_right - s_left) / (2.0 * eps);
|
||||
tmp_left.frame_element_distances[i][j][k] = saved_left;
|
||||
tmp_right.frame_element_distances[i][j][k] = saved_right;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
template <typename T>
|
||||
colvarvalue compute_z_analytical_derivative_ij(size_t i, size_t j, cvm::real eps, T* obj) const {
|
||||
ArithmeticPathImpl tmp_left(*this), tmp_right(*this);
|
||||
const size_t value_size = frame_element_distances[i][j].size();
|
||||
colvarvalue result(frame_element_distances[i][j].type());
|
||||
colvarvalue ref_cv_value(obj->ref_cv[i][j]);
|
||||
for (size_t k = 0; k < value_size; ++k) {
|
||||
// get the current CV value
|
||||
colvarvalue current_cv_value(obj->cv[j]->value());
|
||||
// save the old values in frame element distance matrices
|
||||
const auto saved_left = tmp_left.frame_element_distances[i][j][k];
|
||||
const auto saved_right = tmp_right.frame_element_distances[i][j][k];
|
||||
// update frame element distance matrices
|
||||
if (current_cv_value.type() == colvarvalue::type_scalar) {
|
||||
tmp_left.frame_element_distances[i][j] = 0.5 * obj->cv[j]->dist2_lgrad(obj->cv[j]->sup_coeff * (cvm::pow(current_cv_value.real_value - eps, obj->cv[j]->sup_np)), ref_cv_value.real_value);
|
||||
tmp_right.frame_element_distances[i][j] = 0.5 * obj->cv[j]->dist2_lgrad(obj->cv[j]->sup_coeff * (cvm::pow(current_cv_value.real_value + eps, obj->cv[j]->sup_np)), ref_cv_value.real_value);
|
||||
} else {
|
||||
current_cv_value[k] -= eps;
|
||||
tmp_left.frame_element_distances[i][j] = 0.5 * obj->cv[j]->dist2_lgrad(obj->cv[j]->sup_coeff * current_cv_value, ref_cv_value);
|
||||
current_cv_value[k] += eps + eps;
|
||||
tmp_right.frame_element_distances[i][j] = 0.5 * obj->cv[j]->dist2_lgrad(obj->cv[j]->sup_coeff * current_cv_value, ref_cv_value);
|
||||
}
|
||||
const cvm::real z_left = tmp_left.compute_z();
|
||||
const cvm::real z_right = tmp_right.compute_z();
|
||||
result[k] = (z_right - z_left) / (2.0 * eps);
|
||||
tmp_left.frame_element_distances[i][j][k] = saved_left;
|
||||
tmp_right.frame_element_distances[i][j][k] = saved_right;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
colvar::aspath::aspath()
|
||||
{
|
||||
set_function_type("aspath");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
}
|
||||
|
||||
|
||||
int colvar::aspath::init(std::string const &conf)
|
||||
{
|
||||
int error_code = CartesianBasedPath::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
cvm::log(std::string("Total number of frames: ") + cvm::to_str(total_reference_frames) + std::string("\n"));
|
||||
cvm::real p_lambda;
|
||||
get_keyval(conf, "lambda", p_lambda, -1.0);
|
||||
const size_t num_atoms = atoms->size();
|
||||
std::vector<cvm::real> p_weights(num_atoms, std::sqrt(1.0 / num_atoms));
|
||||
// ArithmeticPathCV::ArithmeticPathBase<cvm::atom_pos, cvm::real, ArithmeticPathCV::path_sz::S>::initialize(num_atoms, total_reference_frames, p_lambda, reference_frames[0], p_weights);
|
||||
if (impl_) impl_.reset();
|
||||
impl_ = std::unique_ptr<ArithmeticPathImpl>(new ArithmeticPathImpl(num_atoms, total_reference_frames, p_lambda, p_weights));
|
||||
cvm::log(std::string("Lambda is ") + cvm::to_str(impl_->get_lambda()) + std::string("\n"));
|
||||
return error_code;
|
||||
}
|
||||
|
||||
colvar::aspath::~aspath() {}
|
||||
|
||||
void colvar::aspath::calc_value() {
|
||||
if (impl_->get_lambda() < 0) {
|
||||
// this implies that the user may not set a valid lambda value
|
||||
// so recompute it by the suggested value in Parrinello's paper
|
||||
cvm::log("A non-positive value of lambda is detected, which implies that it may not set in the configuration.\n");
|
||||
cvm::log("This component (aspath) will recompute a value for lambda following the suggestion in the origin paper.\n");
|
||||
std::vector<cvm::real> rmsd_between_refs(total_reference_frames - 1, 0.0);
|
||||
computeDistanceBetweenReferenceFrames(rmsd_between_refs);
|
||||
impl_->reComputeLambda(rmsd_between_refs);
|
||||
cvm::log("Ok, the value of lambda is updated to " + cvm::to_str(impl_->get_lambda()));
|
||||
}
|
||||
impl_->updateCartesianDistanceToReferenceFrames(this);
|
||||
x = impl_->compute_s();
|
||||
}
|
||||
|
||||
void colvar::aspath::calc_gradients() {
|
||||
impl_->compute_s_derivatives();
|
||||
for (size_t i_frame = 0; i_frame < reference_frames.size(); ++i_frame) {
|
||||
for (size_t i_atom = 0; i_atom < atoms->size(); ++i_atom) {
|
||||
(*(comp_atoms[i_frame]))[i_atom].grad += impl_->dsdx[i_frame][i_atom];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void colvar::aspath::apply_force(colvarvalue const &force) {
|
||||
cvm::real const &F = force.real_value;
|
||||
for (size_t i_frame = 0; i_frame < reference_frames.size(); ++i_frame) {
|
||||
(*(comp_atoms[i_frame])).apply_colvar_force(F);
|
||||
}
|
||||
}
|
||||
|
||||
colvar::azpath::azpath()
|
||||
{
|
||||
set_function_type("azpath");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
}
|
||||
|
||||
int colvar::azpath::init(std::string const &conf)
|
||||
{
|
||||
int error_code = CartesianBasedPath::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
cvm::log(std::string("Total number of frames: ") + cvm::to_str(total_reference_frames) + std::string("\n"));
|
||||
x.type(colvarvalue::type_scalar);
|
||||
cvm::real p_lambda;
|
||||
get_keyval(conf, "lambda", p_lambda, -1.0);
|
||||
const size_t num_atoms = atoms->size();
|
||||
std::vector<cvm::real> p_weights(num_atoms, std::sqrt(1.0 / num_atoms));
|
||||
if (impl_) impl_.reset();
|
||||
impl_ = std::unique_ptr<ArithmeticPathImpl>(new ArithmeticPathImpl(num_atoms, total_reference_frames, p_lambda, p_weights));
|
||||
cvm::log(std::string("Lambda is ") + cvm::to_str(impl_->get_lambda()) + std::string("\n"));
|
||||
return error_code;
|
||||
}
|
||||
|
||||
colvar::azpath::~azpath() {}
|
||||
|
||||
void colvar::azpath::calc_value() {
|
||||
if (impl_->get_lambda() < 0) {
|
||||
// this implies that the user may not set a valid lambda value
|
||||
// so recompute it by the suggested value in Parrinello's paper
|
||||
cvm::log("A non-positive value of lambda is detected, which implies that it may not set in the configuration.\n");
|
||||
cvm::log("This component (azpath) will recompute a value for lambda following the suggestion in the origin paper.\n");
|
||||
std::vector<cvm::real> rmsd_between_refs(total_reference_frames - 1, 0.0);
|
||||
computeDistanceBetweenReferenceFrames(rmsd_between_refs);
|
||||
impl_->reComputeLambda(rmsd_between_refs);
|
||||
cvm::log("Ok, the value of lambda is updated to " + cvm::to_str(impl_->get_lambda()));
|
||||
}
|
||||
impl_->updateCartesianDistanceToReferenceFrames(this);
|
||||
x = impl_->compute_z();
|
||||
}
|
||||
|
||||
void colvar::azpath::calc_gradients() {
|
||||
impl_->compute_z_derivatives();
|
||||
for (size_t i_frame = 0; i_frame < reference_frames.size(); ++i_frame) {
|
||||
for (size_t i_atom = 0; i_atom < atoms->size(); ++i_atom) {
|
||||
(*(comp_atoms[i_frame]))[i_atom].grad += impl_->dzdx[i_frame][i_atom];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void colvar::azpath::apply_force(colvarvalue const &force) {
|
||||
cvm::real const &F = force.real_value;
|
||||
for (size_t i_frame = 0; i_frame < reference_frames.size(); ++i_frame) {
|
||||
(*(comp_atoms[i_frame])).apply_colvar_force(F);
|
||||
}
|
||||
}
|
||||
|
||||
colvar::aspathCV::aspathCV()
|
||||
{
|
||||
set_function_type("aspathCV");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
}
|
||||
|
||||
int colvar::aspathCV::init(std::string const &conf)
|
||||
{
|
||||
int error_code = CVBasedPath::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
cvm::log(std::string("Total number of frames: ") + cvm::to_str(total_reference_frames) + std::string("\n"));
|
||||
std::vector<cvm::real> p_weights(cv.size(), 1.0);
|
||||
get_keyval(conf, "weights", p_weights, std::vector<cvm::real>(cv.size(), 1.0));
|
||||
x.type(colvarvalue::type_scalar);
|
||||
use_explicit_gradients = true;
|
||||
cvm::real p_lambda;
|
||||
get_keyval(conf, "lambda", p_lambda, -1.0);
|
||||
ArithmeticPathCV::ArithmeticPathBase<colvarvalue, cvm::real, ArithmeticPathCV::path_sz::S>::initialize(cv.size(), total_reference_frames, p_lambda, ref_cv[0], p_weights);
|
||||
cvm::log(std::string("Lambda is ") + cvm::to_str(lambda) + std::string("\n"));
|
||||
if (impl_) impl_.reset();
|
||||
impl_ = std::unique_ptr<ArithmeticPathImpl>(new ArithmeticPathImpl(cv.size(), total_reference_frames, p_lambda, p_weights));
|
||||
cvm::log(std::string("Lambda is ") + cvm::to_str(impl_->get_lambda()) + std::string("\n"));
|
||||
for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) {
|
||||
if (!cv[i_cv]->is_enabled(f_cvc_explicit_gradient)) {
|
||||
use_explicit_gradients = false;
|
||||
}
|
||||
cvm::log(std::string("The weight of CV ") + cvm::to_str(i_cv) + std::string(" is ") + cvm::to_str(weights[i_cv]) + std::string("\n"));
|
||||
cvm::log(std::string("The weight of CV ") + cvm::to_str(i_cv) + std::string(" is ") + cvm::to_str(p_weights[i_cv]) + std::string("\n"));
|
||||
}
|
||||
return error_code;
|
||||
}
|
||||
|
||||
void colvar::aspathCV::updateDistanceToReferenceFrames() {
|
||||
for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) {
|
||||
cv[i_cv]->calc_value();
|
||||
}
|
||||
for (size_t i_frame = 0; i_frame < ref_cv.size(); ++i_frame) {
|
||||
for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) {
|
||||
colvarvalue ref_cv_value(ref_cv[i_frame][i_cv]);
|
||||
colvarvalue current_cv_value(cv[i_cv]->value());
|
||||
if (current_cv_value.type() == colvarvalue::type_scalar) {
|
||||
frame_element_distances[i_frame][i_cv] = 0.5 * cv[i_cv]->dist2_lgrad(cv[i_cv]->sup_coeff * (cvm::pow(current_cv_value.real_value, cv[i_cv]->sup_np)), ref_cv_value.real_value);
|
||||
} else {
|
||||
frame_element_distances[i_frame][i_cv] = 0.5 * cv[i_cv]->dist2_lgrad(cv[i_cv]->sup_coeff * current_cv_value, ref_cv_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
colvar::aspathCV::~aspathCV() {}
|
||||
|
||||
void colvar::aspathCV::calc_value() {
|
||||
if (lambda < 0) {
|
||||
if (impl_->get_lambda() < 0) {
|
||||
// this implies that the user may not set a valid lambda value
|
||||
// so recompute it by the suggested value in Parrinello's paper
|
||||
cvm::log("A non-positive value of lambda is detected, which implies that it may not set in the configuration.\n");
|
||||
cvm::log("This component (aspathCV) will recompute a value for lambda following the suggestion in the origin paper.\n");
|
||||
std::vector<cvm::real> rmsd_between_refs(total_reference_frames - 1, 0.0);
|
||||
computeDistanceBetweenReferenceFrames(rmsd_between_refs);
|
||||
reComputeLambda(rmsd_between_refs);
|
||||
cvm::log("Ok, the value of lambda is updated to " + cvm::to_str(lambda));
|
||||
impl_->reComputeLambda(rmsd_between_refs);
|
||||
cvm::log("Ok, the value of lambda is updated to " + cvm::to_str(impl_->get_lambda()));
|
||||
}
|
||||
computeValue();
|
||||
x = s;
|
||||
impl_->updateCVDistanceToReferenceFrames(this);
|
||||
x = impl_->compute_s();
|
||||
}
|
||||
|
||||
void colvar::aspathCV::calc_gradients() {
|
||||
computeDerivatives();
|
||||
impl_->compute_s_derivatives();
|
||||
for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) {
|
||||
cv[i_cv]->calc_gradients();
|
||||
if (cv[i_cv]->is_enabled(f_cvc_explicit_gradient)) {
|
||||
cvm::real factor_polynomial = getPolynomialFactorOfCVGradient(i_cv);
|
||||
// compute the gradient (grad) with respect to the i-th CV
|
||||
colvarvalue grad(cv[i_cv]->value().type());
|
||||
// sum up derivatives with respect to all frames
|
||||
for (size_t m_frame = 0; m_frame < impl_->dsdx.size(); ++m_frame) {
|
||||
// dsdx is the derivative of s with respect to the m-th frame
|
||||
grad += impl_->dsdx[m_frame][i_cv];
|
||||
}
|
||||
for (size_t j_elem = 0; j_elem < cv[i_cv]->value().size(); ++j_elem) {
|
||||
for (size_t k_ag = 0 ; k_ag < cv[i_cv]->atom_groups.size(); ++k_ag) {
|
||||
for (size_t l_atom = 0; l_atom < (cv[i_cv]->atom_groups)[k_ag]->size(); ++l_atom) {
|
||||
(*(cv[i_cv]->atom_groups)[k_ag])[l_atom].grad = dsdx[i_cv][j_elem] * factor_polynomial * (*(cv[i_cv]->atom_groups)[k_ag])[l_atom].grad;
|
||||
(*(cv[i_cv]->atom_groups)[k_ag])[l_atom].grad = grad[j_elem] * factor_polynomial * (*(cv[i_cv]->atom_groups)[k_ag])[l_atom].grad;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -88,97 +322,137 @@ void colvar::aspathCV::apply_force(colvarvalue const &force) {
|
||||
}
|
||||
} else {
|
||||
cvm::real factor_polynomial = getPolynomialFactorOfCVGradient(i_cv);
|
||||
colvarvalue cv_force = dsdx[i_cv] * force.real_value * factor_polynomial;
|
||||
cv[i_cv]->apply_force(cv_force);
|
||||
// compute the gradient (grad) with respect to the i-th CV
|
||||
colvarvalue grad(cv[i_cv]->value().type());
|
||||
for (size_t m_frame = 0; m_frame < impl_->dsdx.size(); ++m_frame) {
|
||||
// dsdx is the derivative of s with respect to the m-th frame
|
||||
grad += impl_->dsdx[m_frame][i_cv];
|
||||
}
|
||||
grad *= factor_polynomial;
|
||||
cv[i_cv]->apply_force(force.real_value * grad);
|
||||
// try my best to debug gradients even if the sub-CVs do not have explicit gradients
|
||||
if (is_enabled(f_cvc_debug_gradient)) {
|
||||
cvm::log("Debugging gradients for " + description +
|
||||
" with respect to sub-CV " + cv[i_cv]->description +
|
||||
", which has no explicit gradient with respect to its own input(s)");
|
||||
colvarvalue analytical_grad(cv[i_cv]->value().type());
|
||||
for (size_t m_frame = 0; m_frame < impl_->dsdx.size(); ++m_frame) {
|
||||
analytical_grad += impl_->compute_s_analytical_derivative_ij(
|
||||
m_frame, i_cv, cvm::debug_gradients_step_size, this);
|
||||
}
|
||||
cvm::log("dx(actual) = "+cvm::to_str(analytical_grad, 21, 14)+"\n");
|
||||
cvm::log("dx(interp) = "+cvm::to_str(grad, 21, 14)+"\n");
|
||||
cvm::log("|dx(actual) - dx(interp)|/|dx(actual)| = "+
|
||||
cvm::to_str((analytical_grad - grad).norm() /
|
||||
(analytical_grad).norm(), 12, 5)+"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
colvar::aspathCV::~aspathCV() {}
|
||||
|
||||
colvar::azpathCV::azpathCV(std::string const &conf): CVBasedPath(conf) {
|
||||
colvar::azpathCV::azpathCV()
|
||||
{
|
||||
set_function_type("azpathCV");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
}
|
||||
|
||||
int colvar::azpathCV::init(std::string const &conf)
|
||||
{
|
||||
int error_code = CVBasedPath::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
cvm::log(std::string("Total number of frames: ") + cvm::to_str(total_reference_frames) + std::string("\n"));
|
||||
std::vector<cvm::real> p_weights(cv.size(), 1.0);
|
||||
get_keyval(conf, "weights", p_weights, std::vector<cvm::real>(cv.size(), 1.0));
|
||||
x.type(colvarvalue::type_scalar);
|
||||
use_explicit_gradients = true;
|
||||
cvm::real p_lambda;
|
||||
get_keyval(conf, "lambda", p_lambda, -1.0);
|
||||
ArithmeticPathCV::ArithmeticPathBase<colvarvalue, cvm::real, ArithmeticPathCV::path_sz::Z>::initialize(cv.size(), total_reference_frames, p_lambda, ref_cv[0], p_weights);
|
||||
cvm::log(std::string("Lambda is ") + cvm::to_str(lambda) + std::string("\n"));
|
||||
if (impl_) impl_.reset();
|
||||
impl_ = std::unique_ptr<ArithmeticPathImpl>(new ArithmeticPathImpl(cv.size(), total_reference_frames, p_lambda, p_weights));
|
||||
cvm::log(std::string("Lambda is ") + cvm::to_str(impl_->get_lambda()) + std::string("\n"));
|
||||
for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) {
|
||||
if (!cv[i_cv]->is_enabled(f_cvc_explicit_gradient)) {
|
||||
use_explicit_gradients = false;
|
||||
}
|
||||
cvm::log(std::string("The weight of CV ") + cvm::to_str(i_cv) + std::string(" is ") + cvm::to_str(weights[i_cv]) + std::string("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
void colvar::azpathCV::updateDistanceToReferenceFrames() {
|
||||
for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) {
|
||||
cv[i_cv]->calc_value();
|
||||
}
|
||||
for (size_t i_frame = 0; i_frame < ref_cv.size(); ++i_frame) {
|
||||
for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) {
|
||||
colvarvalue ref_cv_value(ref_cv[i_frame][i_cv]);
|
||||
colvarvalue current_cv_value(cv[i_cv]->value());
|
||||
if (current_cv_value.type() == colvarvalue::type_scalar) {
|
||||
frame_element_distances[i_frame][i_cv] = 0.5 * cv[i_cv]->dist2_lgrad(cv[i_cv]->sup_coeff * (cvm::pow(current_cv_value.real_value, cv[i_cv]->sup_np)), ref_cv_value.real_value);
|
||||
} else {
|
||||
frame_element_distances[i_frame][i_cv] = 0.5 * cv[i_cv]->dist2_lgrad(cv[i_cv]->sup_coeff * current_cv_value, ref_cv_value);
|
||||
}
|
||||
}
|
||||
cvm::log(std::string("The weight of CV ") + cvm::to_str(i_cv) + std::string(" is ") + cvm::to_str(p_weights[i_cv]) + std::string("\n"));
|
||||
}
|
||||
return error_code;
|
||||
}
|
||||
|
||||
void colvar::azpathCV::calc_value() {
|
||||
if (lambda < 0) {
|
||||
if (impl_->get_lambda() < 0) {
|
||||
// this implies that the user may not set a valid lambda value
|
||||
// so recompute it by the suggested value in Parrinello's paper
|
||||
cvm::log("A non-positive value of lambda is detected, which implies that it may not set in the configuration.\n");
|
||||
cvm::log("This component (azpathCV) will recompute a value for lambda following the suggestion in the origin paper.\n");
|
||||
std::vector<cvm::real> rmsd_between_refs(total_reference_frames - 1, 0.0);
|
||||
computeDistanceBetweenReferenceFrames(rmsd_between_refs);
|
||||
reComputeLambda(rmsd_between_refs);
|
||||
cvm::log("Ok, the value of lambda is updated to " + cvm::to_str(lambda));
|
||||
impl_->reComputeLambda(rmsd_between_refs);
|
||||
cvm::log("Ok, the value of lambda is updated to " + cvm::to_str(impl_->get_lambda()));
|
||||
}
|
||||
computeValue();
|
||||
x = z;
|
||||
impl_->updateCVDistanceToReferenceFrames(this);
|
||||
x = impl_->compute_z();
|
||||
}
|
||||
|
||||
void colvar::azpathCV::calc_gradients() {
|
||||
computeDerivatives();
|
||||
impl_->compute_z_derivatives();
|
||||
for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) {
|
||||
cv[i_cv]->calc_gradients();
|
||||
if (cv[i_cv]->is_enabled(f_cvc_explicit_gradient)) {
|
||||
cvm::real factor_polynomial = getPolynomialFactorOfCVGradient(i_cv);
|
||||
// compute the gradient (grad) with respect to the i-th CV
|
||||
colvarvalue grad(cv[i_cv]->value().type());
|
||||
// sum up derivatives with respect to all frames
|
||||
for (size_t m_frame = 0; m_frame < impl_->dzdx.size(); ++m_frame) {
|
||||
// dzdx is the derivative of z with respect to the m-th frame
|
||||
grad += impl_->dzdx[m_frame][i_cv];
|
||||
}
|
||||
for (size_t j_elem = 0; j_elem < cv[i_cv]->value().size(); ++j_elem) {
|
||||
for (size_t k_ag = 0 ; k_ag < cv[i_cv]->atom_groups.size(); ++k_ag) {
|
||||
for (size_t l_atom = 0; l_atom < (cv[i_cv]->atom_groups)[k_ag]->size(); ++l_atom) {
|
||||
(*(cv[i_cv]->atom_groups)[k_ag])[l_atom].grad = dzdx[i_cv][j_elem] * factor_polynomial * (*(cv[i_cv]->atom_groups)[k_ag])[l_atom].grad;
|
||||
(*(cv[i_cv]->atom_groups)[k_ag])[l_atom].grad = grad[j_elem] * factor_polynomial * (*(cv[i_cv]->atom_groups)[k_ag])[l_atom].grad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void colvar::azpathCV::apply_force(colvarvalue const &force) {
|
||||
// the PCV component itself is a scalar, so force should be scalar
|
||||
for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) {
|
||||
if (cv[i_cv]->is_enabled(f_cvc_explicit_gradient)) {
|
||||
for (size_t k_ag = 0 ; k_ag < cv[i_cv]->atom_groups.size(); ++k_ag) {
|
||||
(cv[i_cv]->atom_groups)[k_ag]->apply_colvar_force(force.real_value);
|
||||
}
|
||||
} else {
|
||||
cvm::real factor_polynomial = getPolynomialFactorOfCVGradient(i_cv);
|
||||
const colvarvalue cv_force = dzdx[i_cv] * force.real_value * factor_polynomial;
|
||||
cv[i_cv]->apply_force(cv_force);
|
||||
const cvm::real factor_polynomial = getPolynomialFactorOfCVGradient(i_cv);
|
||||
// compute the gradient (grad) with respect to the i-th CV
|
||||
colvarvalue grad(cv[i_cv]->value().type());
|
||||
for (size_t m_frame = 0; m_frame < impl_->dzdx.size(); ++m_frame) {
|
||||
// dzdx is the derivative of z with respect to the m-th frame
|
||||
grad += impl_->dzdx[m_frame][i_cv];
|
||||
}
|
||||
grad *= factor_polynomial;
|
||||
cv[i_cv]->apply_force(force.real_value * grad);
|
||||
// try my best to debug gradients even if the sub-CVs do not have explicit gradients
|
||||
if (is_enabled(f_cvc_debug_gradient)) {
|
||||
cvm::log("Debugging gradients for " + description +
|
||||
" with respect to sub-CV " + cv[i_cv]->description +
|
||||
", which has no explicit gradient with respect to its own input(s)");
|
||||
colvarvalue analytical_grad(cv[i_cv]->value().type());
|
||||
for (size_t m_frame = 0; m_frame < impl_->dzdx.size(); ++m_frame) {
|
||||
analytical_grad += impl_->compute_z_analytical_derivative_ij(
|
||||
m_frame, i_cv, cvm::debug_gradients_step_size, this);
|
||||
}
|
||||
cvm::log("dx(actual) = "+cvm::to_str(analytical_grad, 21, 14)+"\n");
|
||||
cvm::log("dx(interp) = "+cvm::to_str(grad, 21, 14)+"\n");
|
||||
cvm::log("|dx(actual) - dx(interp)|/|dx(actual)| = "+
|
||||
cvm::to_str((analytical_grad - grad).norm() /
|
||||
(analytical_grad).norm(), 12, 5)+"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
colvar::azpathCV::~azpathCV() {}
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#if (__cplusplus >= 201103L)
|
||||
// -*- c++ -*-
|
||||
|
||||
// This file is part of the Collective Variables module (Colvars).
|
||||
// The original version of Colvars and its updates are located at:
|
||||
@ -9,14 +9,26 @@
|
||||
|
||||
#include "colvarcomp.h"
|
||||
|
||||
colvar::linearCombination::linearCombination(std::string const &conf): cvc(conf) {
|
||||
|
||||
colvar::linearCombination::linearCombination()
|
||||
{
|
||||
set_function_type("linearCombination");
|
||||
}
|
||||
|
||||
|
||||
int colvar::linearCombination::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
|
||||
// Lookup all available sub-cvcs
|
||||
for (auto it_cv_map = colvar::get_global_cvc_map().begin(); it_cv_map != colvar::get_global_cvc_map().end(); ++it_cv_map) {
|
||||
if (key_lookup(conf, it_cv_map->first.c_str())) {
|
||||
std::vector<std::string> sub_cvc_confs;
|
||||
get_key_string_multi_value(conf, it_cv_map->first.c_str(), sub_cvc_confs);
|
||||
for (auto it_sub_cvc_conf = sub_cvc_confs.begin(); it_sub_cvc_conf != sub_cvc_confs.end(); ++it_sub_cvc_conf) {
|
||||
cv.push_back((it_cv_map->second)(*(it_sub_cvc_conf)));
|
||||
cv.push_back((it_cv_map->second)());
|
||||
cv.back()->init(*(it_sub_cvc_conf));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,26 +41,11 @@ colvar::linearCombination::linearCombination(std::string const &conf): cvc(conf)
|
||||
}
|
||||
// Show useful error messages and prevent crashes if no sub CVC is found
|
||||
if (cv.size() == 0) {
|
||||
cvm::error("Error: the CV " + name +
|
||||
" expects one or more nesting components.\n");
|
||||
return;
|
||||
return cvm::error("Error: the CV " + name + " expects one or more nesting components.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
} else {
|
||||
// TODO: Maybe we can add an option to allow mixing scalar and vector types,
|
||||
// but that's a bit complicated so we just require a consistent type
|
||||
// of nesting CVs.
|
||||
x.type(cv[0]->value());
|
||||
x.reset();
|
||||
for (size_t i_cv = 1; i_cv < cv.size(); ++i_cv) {
|
||||
const auto type_i = cv[i_cv]->value().type();
|
||||
if (type_i != x.type()) {
|
||||
cvm::error("Error: the type of sub-CVC " + cv[i_cv]->name +
|
||||
" is " + colvarvalue::type_desc(type_i) + ", which is "
|
||||
"different to the type of the first sub-CVC. Currently "
|
||||
"only sub-CVCs of the same type are supported to be "
|
||||
"nested.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
use_explicit_gradients = true;
|
||||
for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) {
|
||||
@ -59,6 +56,7 @@ colvar::linearCombination::linearCombination(std::string const &conf): cvc(conf)
|
||||
if (!use_explicit_gradients) {
|
||||
disable(f_cvc_explicit_gradient);
|
||||
}
|
||||
return error_code;
|
||||
}
|
||||
|
||||
cvm::real colvar::linearCombination::getPolynomialFactorOfCVGradient(size_t i_cv) const {
|
||||
@ -138,8 +136,42 @@ void colvar::linearCombination::apply_force(colvarvalue const &force) {
|
||||
}
|
||||
}
|
||||
|
||||
colvar::customColvar::customColvar(std::string const &conf): linearCombination(conf) {
|
||||
use_custom_function = false;
|
||||
|
||||
cvm::real colvar::linearCombination::dist2(colvarvalue const &x1, colvarvalue const &x2) const
|
||||
{
|
||||
return x1.dist2(x2);
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::linearCombination::dist2_lgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
return x1.dist2_grad(x2);
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::linearCombination::dist2_rgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
return x2.dist2_grad(x1);
|
||||
}
|
||||
|
||||
|
||||
void colvar::linearCombination::wrap(colvarvalue & /* x_unwrapped */) const {}
|
||||
|
||||
|
||||
|
||||
colvar::customColvar::customColvar()
|
||||
{
|
||||
set_function_type("customColvar");
|
||||
}
|
||||
|
||||
|
||||
int colvar::customColvar::init(std::string const &conf)
|
||||
{
|
||||
int error_code = linearCombination::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
|
||||
// code swipe from colvar::init_custom_function
|
||||
std::string expr_in, expr;
|
||||
size_t pos = 0; // current position in config string
|
||||
@ -160,7 +192,7 @@ colvar::customColvar::customColvar(std::string const &conf): linearCombination(c
|
||||
pexpr = Lepton::Parser::parse(expr);
|
||||
pexprs.push_back(pexpr);
|
||||
} catch (...) {
|
||||
cvm::error("Error parsing expression \"" + expr + "\".\n", COLVARS_INPUT_ERROR);
|
||||
return cvm::error("Error parsing expression \"" + expr + "\".\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
try {
|
||||
value_evaluators.push_back(new Lepton::CompiledExpression(pexpr.createCompiledExpression()));
|
||||
@ -178,7 +210,7 @@ colvar::customColvar::customColvar(std::string const &conf): linearCombination(c
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
cvm::error("Error compiling expression \"" + expr + "\".\n", COLVARS_INPUT_ERROR);
|
||||
return cvm::error("Error compiling expression \"" + expr + "\".\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
} while (key_lookup(conf, "customFunction", &expr_in, &pos));
|
||||
// Now define derivative with respect to each scalar sub-component
|
||||
@ -203,7 +235,7 @@ colvar::customColvar::customColvar(std::string const &conf): linearCombination(c
|
||||
}
|
||||
}
|
||||
if (value_evaluators.size() == 0) {
|
||||
cvm::error("Error: no custom function defined.\n", COLVARS_INPUT_ERROR);
|
||||
return cvm::error("Error: no custom function defined.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
if (value_evaluators.size() != 1) {
|
||||
x.type(colvarvalue::type_vector);
|
||||
@ -211,14 +243,17 @@ colvar::customColvar::customColvar(std::string const &conf): linearCombination(c
|
||||
x.type(colvarvalue::type_scalar);
|
||||
}
|
||||
#else
|
||||
cvm::error("customFunction requires the Lepton library, but it is not enabled during compilation.\n"
|
||||
"Please refer to the Compilation Notes section of the Colvars manual for more information.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return cvm::error(
|
||||
"customFunction requires the Lepton library, but it is not enabled during compilation.\n"
|
||||
"Please refer to the Compilation Notes section of the Colvars manual for more "
|
||||
"information.\n",
|
||||
COLVARS_NOT_IMPLEMENTED);
|
||||
#endif
|
||||
} else {
|
||||
cvm::log("Warning: no customFunction specified.\n");
|
||||
cvm::log("Warning: use linear combination instead.\n");
|
||||
}
|
||||
return error_code;
|
||||
}
|
||||
|
||||
colvar::customColvar::~customColvar() {
|
||||
@ -317,7 +352,8 @@ void colvar::customColvar::apply_force(colvarvalue const &force) {
|
||||
}
|
||||
} else {
|
||||
const colvarvalue& current_cv_value = cv[i_cv]->value();
|
||||
colvarvalue cv_force(current_cv_value.type());
|
||||
colvarvalue cv_force(current_cv_value);
|
||||
cv_force.reset();
|
||||
const cvm::real factor_polynomial = getPolynomialFactorOfCVGradient(i_cv);
|
||||
for (size_t j_elem = 0; j_elem < current_cv_value.size(); ++j_elem) {
|
||||
for (size_t c = 0; c < x.size(); ++c) {
|
||||
@ -340,5 +376,3 @@ void colvar::customColvar::apply_force(colvarvalue const &force) {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __cplusplus >= 201103L
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvaratoms.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvar.h"
|
||||
@ -90,48 +89,47 @@ cvm::real colvar::coordnum::switching_function(cvm::real const &r0,
|
||||
}
|
||||
|
||||
|
||||
colvar::coordnum::coordnum(std::string const &conf)
|
||||
: cvc(conf), b_anisotropic(false), pairlist(NULL)
|
||||
|
||||
colvar::coordnum::coordnum()
|
||||
{
|
||||
set_function_type("coordNum");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
|
||||
colvarproxy *proxy = cvm::main()->proxy;
|
||||
r0 = proxy->angstrom_to_internal(4.0);
|
||||
r0_vec = cvm::rvector(proxy->angstrom_to_internal(4.0),
|
||||
proxy->angstrom_to_internal(4.0),
|
||||
proxy->angstrom_to_internal(4.0));
|
||||
}
|
||||
|
||||
|
||||
int colvar::coordnum::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
|
||||
group1 = parse_group(conf, "group1");
|
||||
group2 = parse_group(conf, "group2");
|
||||
|
||||
if (group1 == NULL || group2 == NULL) {
|
||||
cvm::error("Error: failed to initialize atom groups.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return;
|
||||
if (!group1 || !group2) {
|
||||
return error_code | COLVARS_INPUT_ERROR;
|
||||
}
|
||||
|
||||
if (int atom_number = cvm::atom_group::overlap(*group1, *group2)) {
|
||||
cvm::error("Error: group1 and group2 share a common atom (number: " +
|
||||
cvm::to_str(atom_number) + ")\n", COLVARS_INPUT_ERROR);
|
||||
return;
|
||||
error_code |= cvm::error(
|
||||
"Error: group1 and group2 share a common atom (number: " + cvm::to_str(atom_number) + ")\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if (group1->b_dummy) {
|
||||
cvm::error("Error: only group2 is allowed to be a dummy atom\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return;
|
||||
error_code |=
|
||||
cvm::error("Error: only group2 is allowed to be a dummy atom\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
bool const b_isotropic = get_keyval(conf, "cutoff", r0,
|
||||
cvm::real(proxy->angstrom_to_internal(4.0)));
|
||||
bool const b_isotropic = get_keyval(conf, "cutoff", r0, r0);
|
||||
|
||||
if (get_keyval(conf, "cutoff3", r0_vec,
|
||||
cvm::rvector(proxy->angstrom_to_internal(4.0),
|
||||
proxy->angstrom_to_internal(4.0),
|
||||
proxy->angstrom_to_internal(4.0)))) {
|
||||
if (get_keyval(conf, "cutoff3", r0_vec, r0_vec)) {
|
||||
if (b_isotropic) {
|
||||
cvm::error("Error: cannot specify \"cutoff\" and \"cutoff3\" "
|
||||
error_code |= cvm::error("Error: cannot specify \"cutoff\" and \"cutoff3\" "
|
||||
"at the same time.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
b_anisotropic = true;
|
||||
@ -141,16 +139,16 @@ colvar::coordnum::coordnum(std::string const &conf)
|
||||
if (r0_vec.z < 0.0) r0_vec.z *= -1.0;
|
||||
}
|
||||
|
||||
get_keyval(conf, "expNumer", en, 6);
|
||||
get_keyval(conf, "expDenom", ed, 12);
|
||||
get_keyval(conf, "expNumer", en, en);
|
||||
get_keyval(conf, "expDenom", ed, ed);
|
||||
|
||||
if ( (en%2) || (ed%2) ) {
|
||||
cvm::error("Error: odd exponent(s) provided, can only use even ones.\n",
|
||||
error_code |= cvm::error("Error: odd exponent(s) provided, can only use even ones.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if ( (en <= 0) || (ed <= 0) ) {
|
||||
cvm::error("Error: negative exponent(s) provided.\n",
|
||||
error_code |= cvm::error("Error: negative exponent(s) provided.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
@ -160,14 +158,14 @@ colvar::coordnum::coordnum(std::string const &conf)
|
||||
|
||||
get_keyval(conf, "group2CenterOnly", b_group2_center_only, group2->b_dummy);
|
||||
|
||||
get_keyval(conf, "tolerance", tolerance, 0.0);
|
||||
get_keyval(conf, "tolerance", tolerance, tolerance);
|
||||
if (tolerance > 0) {
|
||||
cvm::main()->cite_feature("coordNum pairlist");
|
||||
get_keyval(conf, "pairListFrequency", pairlist_freq, 100);
|
||||
get_keyval(conf, "pairListFrequency", pairlist_freq, pairlist_freq);
|
||||
if ( ! (pairlist_freq > 0) ) {
|
||||
cvm::error("Error: non-positive pairlistfrequency provided.\n",
|
||||
return cvm::error("Error: non-positive pairlistfrequency provided.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return; // and do not allocate the pairlists below
|
||||
// return and do not allocate the pairlists below
|
||||
}
|
||||
if (b_group2_center_only) {
|
||||
pairlist = new bool[group1->size()];
|
||||
@ -181,12 +179,14 @@ colvar::coordnum::coordnum(std::string const &conf)
|
||||
static_cast<cvm::real>(group1->size()) :
|
||||
static_cast<cvm::real>(group1->size() *
|
||||
group2->size()));
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
colvar::coordnum::~coordnum()
|
||||
{
|
||||
if (pairlist != NULL) {
|
||||
if (pairlist) {
|
||||
delete [] pairlist;
|
||||
}
|
||||
}
|
||||
@ -285,25 +285,23 @@ void colvar::coordnum::calc_gradients()
|
||||
}
|
||||
|
||||
|
||||
void colvar::coordnum::apply_force(colvarvalue const &force)
|
||||
{
|
||||
if (!group1->noforce)
|
||||
group1->apply_colvar_force(force.real_value);
|
||||
|
||||
if (!group2->noforce)
|
||||
group2->apply_colvar_force(force.real_value);
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(coordnum)
|
||||
|
||||
|
||||
|
||||
// h_bond member functions
|
||||
|
||||
colvar::h_bond::h_bond(std::string const &conf)
|
||||
: cvc(conf)
|
||||
colvar::h_bond::h_bond()
|
||||
{
|
||||
colvarproxy *proxy = cvm::main()->proxy;
|
||||
r0 = proxy->angstrom_to_internal(3.3);
|
||||
set_function_type("hBond");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
init_scalar_boundaries(0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
int colvar::h_bond::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
|
||||
if (cvm::debug())
|
||||
cvm::log("Initializing h_bond object.\n");
|
||||
|
||||
@ -311,15 +309,12 @@ colvar::h_bond::h_bond(std::string const &conf)
|
||||
x.type(colvarvalue::type_scalar);
|
||||
init_scalar_boundaries(0.0, 1.0);
|
||||
|
||||
colvarproxy *proxy = cvm::main()->proxy;
|
||||
|
||||
int a_num = -1, d_num = -1;
|
||||
get_keyval(conf, "acceptor", a_num, a_num);
|
||||
get_keyval(conf, "donor", d_num, a_num);
|
||||
|
||||
if ( (a_num == -1) || (d_num == -1) ) {
|
||||
cvm::error("Error: either acceptor or donor undefined.\n");
|
||||
return;
|
||||
error_code |= cvm::error("Error: either acceptor or donor undefined.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
cvm::atom acceptor = cvm::atom(a_num);
|
||||
@ -328,34 +323,34 @@ colvar::h_bond::h_bond(std::string const &conf)
|
||||
atom_groups[0]->add_atom(acceptor);
|
||||
atom_groups[0]->add_atom(donor);
|
||||
|
||||
get_keyval(conf, "cutoff", r0, proxy->angstrom_to_internal(3.3));
|
||||
get_keyval(conf, "expNumer", en, 6);
|
||||
get_keyval(conf, "expDenom", ed, 8);
|
||||
get_keyval(conf, "cutoff", r0, r0);
|
||||
get_keyval(conf, "expNumer", en, en);
|
||||
get_keyval(conf, "expDenom", ed, ed);
|
||||
|
||||
if ( (en%2) || (ed%2) ) {
|
||||
cvm::error("Error: odd exponent(s) provided, can only use even ones.\n",
|
||||
if ((en % 2) || (ed % 2)) {
|
||||
error_code |= cvm::error("Error: odd exponent(s) provided, can only use even ones.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if ( (en <= 0) || (ed <= 0) ) {
|
||||
cvm::error("Error: negative exponent(s) provided.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
if ((en <= 0) || (ed <= 0)) {
|
||||
error_code |= cvm::error("Error: negative exponent(s) provided.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if (cvm::debug())
|
||||
cvm::log("Done initializing h_bond object.\n");
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
colvar::h_bond::h_bond(cvm::atom const &acceptor,
|
||||
cvm::atom const &donor,
|
||||
cvm::real r0_i, int en_i, int ed_i)
|
||||
: r0(r0_i), en(en_i), ed(ed_i)
|
||||
: h_bond()
|
||||
{
|
||||
set_function_type("hBond");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
init_scalar_boundaries(0.0, 1.0);
|
||||
|
||||
r0 = r0_i;
|
||||
en = en_i;
|
||||
ed = ed_i;
|
||||
register_atom_group(new cvm::atom_group);
|
||||
atom_groups[0]->add_atom(acceptor);
|
||||
atom_groups[0]->add_atom(donor);
|
||||
@ -385,64 +380,63 @@ void colvar::h_bond::calc_gradients()
|
||||
}
|
||||
|
||||
|
||||
void colvar::h_bond::apply_force(colvarvalue const &force)
|
||||
{
|
||||
(atom_groups[0])->apply_colvar_force(force);
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(h_bond)
|
||||
|
||||
|
||||
|
||||
colvar::selfcoordnum::selfcoordnum(std::string const &conf)
|
||||
: cvc(conf), pairlist(NULL)
|
||||
colvar::selfcoordnum::selfcoordnum()
|
||||
{
|
||||
set_function_type("selfCoordNum");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
r0 = cvm::main()->proxy->angstrom_to_internal(4.0);
|
||||
}
|
||||
|
||||
colvarproxy *proxy = cvm::main()->proxy;
|
||||
|
||||
int colvar::selfcoordnum::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
|
||||
group1 = parse_group(conf, "group1");
|
||||
|
||||
get_keyval(conf, "cutoff", r0, cvm::real(proxy->angstrom_to_internal(4.0)));
|
||||
get_keyval(conf, "expNumer", en, 6);
|
||||
get_keyval(conf, "expDenom", ed, 12);
|
||||
if (!group1 || group1->size() == 0) {
|
||||
return error_code | COLVARS_INPUT_ERROR;
|
||||
}
|
||||
|
||||
get_keyval(conf, "cutoff", r0, r0);
|
||||
get_keyval(conf, "expNumer", en, en);
|
||||
get_keyval(conf, "expDenom", ed, ed);
|
||||
|
||||
|
||||
if ( (en%2) || (ed%2) ) {
|
||||
cvm::error("Error: odd exponent(s) provided, can only use even ones.\n",
|
||||
if ((en % 2) || (ed % 2)) {
|
||||
error_code |= cvm::error("Error: odd exponent(s) provided, can only use even ones.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if ( (en <= 0) || (ed <= 0) ) {
|
||||
cvm::error("Error: negative exponent(s) provided.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
if ((en <= 0) || (ed <= 0)) {
|
||||
error_code |= cvm::error("Error: negative exponent(s) provided.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if (!is_enabled(f_cvc_pbc_minimum_image)) {
|
||||
cvm::log("Warning: only minimum-image distances are used by this variable.\n");
|
||||
}
|
||||
|
||||
get_keyval(conf, "tolerance", tolerance, 0.0);
|
||||
get_keyval(conf, "tolerance", tolerance, tolerance);
|
||||
if (tolerance > 0) {
|
||||
get_keyval(conf, "pairListFrequency", pairlist_freq, 100);
|
||||
get_keyval(conf, "pairListFrequency", pairlist_freq, pairlist_freq);
|
||||
if ( ! (pairlist_freq > 0) ) {
|
||||
cvm::error("Error: non-positive pairlistfrequency provided.\n",
|
||||
error_code |= cvm::error("Error: non-positive pairlistfrequency provided.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return;
|
||||
}
|
||||
pairlist = new bool[(group1->size()-1) * (group1->size()-1)];
|
||||
}
|
||||
|
||||
init_scalar_boundaries(0.0, static_cast<cvm::real>((group1->size()-1) *
|
||||
(group1->size()-1)));
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
colvar::selfcoordnum::~selfcoordnum()
|
||||
{
|
||||
if (pairlist != NULL) {
|
||||
if (pairlist) {
|
||||
delete [] pairlist;
|
||||
}
|
||||
}
|
||||
@ -527,44 +521,36 @@ void colvar::selfcoordnum::calc_gradients()
|
||||
}
|
||||
|
||||
|
||||
void colvar::selfcoordnum::apply_force(colvarvalue const &force)
|
||||
{
|
||||
if (!group1->noforce) {
|
||||
group1->apply_colvar_force(force.real_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(selfcoordnum)
|
||||
|
||||
|
||||
|
||||
// groupcoordnum member functions
|
||||
colvar::groupcoordnum::groupcoordnum(std::string const &conf)
|
||||
: distance(conf), b_anisotropic(false)
|
||||
colvar::groupcoordnum::groupcoordnum()
|
||||
{
|
||||
set_function_type("groupCoord");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
init_scalar_boundaries(0.0, 1.0);
|
||||
|
||||
colvarproxy *proxy = cvm::main()->proxy;
|
||||
r0 = proxy->angstrom_to_internal(4.0);
|
||||
r0_vec = cvm::rvector(proxy->angstrom_to_internal(4.0),
|
||||
proxy->angstrom_to_internal(4.0),
|
||||
proxy->angstrom_to_internal(4.0));
|
||||
}
|
||||
|
||||
|
||||
int colvar::groupcoordnum::init(std::string const &conf)
|
||||
{
|
||||
int error_code = distance::init(conf);
|
||||
|
||||
// group1 and group2 are already initialized by distance()
|
||||
if (group1->b_dummy || group2->b_dummy) {
|
||||
cvm::error("Error: neither group can be a dummy atom\n");
|
||||
return;
|
||||
return cvm::error("Error: neither group can be a dummy atom\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
bool const b_scale = get_keyval(conf, "cutoff", r0,
|
||||
cvm::real(proxy->angstrom_to_internal(4.0)));
|
||||
|
||||
if (get_keyval(conf, "cutoff3", r0_vec,
|
||||
cvm::rvector(4.0, 4.0, 4.0), parse_silent)) {
|
||||
bool const b_scale = get_keyval(conf, "cutoff", r0, r0);
|
||||
|
||||
if (get_keyval(conf, "cutoff3", r0_vec, r0_vec)) {
|
||||
if (b_scale) {
|
||||
cvm::error("Error: cannot specify \"scale\" and "
|
||||
"\"scale3\" at the same time.\n");
|
||||
return;
|
||||
error_code |=
|
||||
cvm::error("Error: cannot specify \"cutoff\" and \"cutoff3\" at the same time.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
b_anisotropic = true;
|
||||
// remove meaningless negative signs
|
||||
@ -573,23 +559,23 @@ colvar::groupcoordnum::groupcoordnum(std::string const &conf)
|
||||
if (r0_vec.z < 0.0) r0_vec.z *= -1.0;
|
||||
}
|
||||
|
||||
get_keyval(conf, "expNumer", en, 6);
|
||||
get_keyval(conf, "expDenom", ed, 12);
|
||||
get_keyval(conf, "expNumer", en, en);
|
||||
get_keyval(conf, "expDenom", ed, ed);
|
||||
|
||||
if ( (en%2) || (ed%2) ) {
|
||||
cvm::error("Error: odd exponent(s) provided, can only use even ones.\n",
|
||||
if ((en % 2) || (ed % 2)) {
|
||||
error_code |= cvm::error("Error: odd exponent(s) provided, can only use even ones.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if ( (en <= 0) || (ed <= 0) ) {
|
||||
cvm::error("Error: negative exponent(s) provided.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
if ((en <= 0) || (ed <= 0)) {
|
||||
error_code |= cvm::error("Error: negative exponent(s) provided.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if (!is_enabled(f_cvc_pbc_minimum_image)) {
|
||||
cvm::log("Warning: only minimum-image distances are used by this variable.\n");
|
||||
}
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
@ -640,16 +626,3 @@ void colvar::groupcoordnum::calc_gradients()
|
||||
group1->set_weighted_gradient(group1_com_atom.grad);
|
||||
group2->set_weighted_gradient(group2_com_atom.grad);
|
||||
}
|
||||
|
||||
|
||||
void colvar::groupcoordnum::apply_force(colvarvalue const &force)
|
||||
{
|
||||
if (!group1->noforce)
|
||||
group1->apply_colvar_force(force.real_value);
|
||||
|
||||
if (!group2->noforce)
|
||||
group2->apply_colvar_force(force.real_value);
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(groupcoordnum)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
#if (__cplusplus >= 201103L)
|
||||
// -*- c++ -*-
|
||||
|
||||
// This file is part of the Collective Variables module (Colvars).
|
||||
// The original version of Colvars and its updates are located at:
|
||||
@ -10,17 +10,29 @@
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <fstream>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarcomp.h"
|
||||
|
||||
colvar::CartesianBasedPath::CartesianBasedPath(std::string const &conf): cvc(conf), atoms(nullptr), reference_frames(0) {
|
||||
|
||||
|
||||
colvar::CartesianBasedPath::CartesianBasedPath()
|
||||
{
|
||||
x.type(colvarvalue::type_scalar);
|
||||
// Don't use implicit gradient
|
||||
enable(f_cvc_explicit_gradient);
|
||||
}
|
||||
|
||||
|
||||
int colvar::CartesianBasedPath::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
|
||||
// Parse selected atoms
|
||||
atoms = parse_group(conf, "atoms");
|
||||
has_user_defined_fitting = false;
|
||||
@ -31,13 +43,12 @@ colvar::CartesianBasedPath::CartesianBasedPath(std::string const &conf): cvc(con
|
||||
// Lookup reference column of PDB
|
||||
// Copied from the RMSD class
|
||||
std::string reference_column;
|
||||
double reference_column_value;
|
||||
double reference_column_value = 0.0;
|
||||
if (get_keyval(conf, "refPositionsCol", reference_column, std::string(""))) {
|
||||
bool found = get_keyval(conf, "refPositionsColValue", reference_column_value, 0.0);
|
||||
bool found = get_keyval(conf, "refPositionsColValue", reference_column_value, reference_column_value);
|
||||
if (found && reference_column_value == 0.0) {
|
||||
cvm::error("Error: refPositionsColValue, "
|
||||
"if provided, must be non-zero.\n");
|
||||
return;
|
||||
return cvm::error("Error: refPositionsColValue, if provided, must be non-zero.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
}
|
||||
// Lookup all reference frames
|
||||
@ -66,9 +77,6 @@ colvar::CartesianBasedPath::CartesianBasedPath(std::string const &conf): cvc(con
|
||||
tmp_atoms->ref_pos = reference_frames[i_frame];
|
||||
tmp_atoms->center_ref_pos();
|
||||
tmp_atoms->enable(f_ag_fit_gradients);
|
||||
tmp_atoms->rot.request_group1_gradients(tmp_atoms->size());
|
||||
tmp_atoms->rot.request_group2_gradients(tmp_atoms->size());
|
||||
comp_atoms.push_back(tmp_atoms);
|
||||
} else {
|
||||
// parse a group of atoms for fitting
|
||||
std::string fitting_group_name = std::string("fittingAtoms") + cvm::to_str(i_frame);
|
||||
@ -91,15 +99,13 @@ colvar::CartesianBasedPath::CartesianBasedPath(std::string const &conf): cvc(con
|
||||
tmp_atoms->enable(f_ag_fit_gradients);
|
||||
tmp_atoms->enable(f_ag_fitting_group);
|
||||
tmp_atoms->fitting_group = tmp_fitting_atoms;
|
||||
tmp_atoms->rot.request_group1_gradients(tmp_fitting_atoms->size());
|
||||
tmp_atoms->rot.request_group2_gradients(tmp_fitting_atoms->size());
|
||||
reference_fitting_frames.push_back(reference_fitting_position);
|
||||
}
|
||||
tmp_atoms->setup_rotation_derivative();
|
||||
comp_atoms.push_back(tmp_atoms);
|
||||
}
|
||||
}
|
||||
x.type(colvarvalue::type_scalar);
|
||||
// Don't use implicit gradient
|
||||
enable(f_cvc_explicit_gradient);
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
colvar::CartesianBasedPath::~CartesianBasedPath() {
|
||||
@ -125,8 +131,60 @@ void colvar::CartesianBasedPath::computeDistanceToReferenceFrames(std::vector<cv
|
||||
}
|
||||
}
|
||||
|
||||
colvar::gspath::gspath(std::string const &conf): CartesianBasedPath(conf) {
|
||||
// mainly used for determining the lambda value for arithmetic path
|
||||
void colvar::CartesianBasedPath::computeDistanceBetweenReferenceFrames(std::vector<cvm::real>& result) {
|
||||
for (size_t i_frame = 0; i_frame < reference_frames.size() - 1; ++i_frame) {
|
||||
std::vector<cvm::atom_pos> this_frame_atom_pos(reference_frames[i_frame].size());
|
||||
std::vector<cvm::atom_pos> next_frame_atom_pos(reference_frames[i_frame + 1].size());
|
||||
cvm::real frame_rmsd = 0.0;
|
||||
const size_t this_index = i_frame;
|
||||
const size_t next_index = i_frame + 1;
|
||||
// compute COM of two successive images, respectively
|
||||
cvm::atom_pos reference_cog_this, reference_cog_next;
|
||||
for (size_t i_atom = 0; i_atom < atoms->size(); ++i_atom) {
|
||||
reference_cog_this += reference_frames[this_index][i_atom];
|
||||
reference_cog_next += reference_frames[next_index][i_atom];
|
||||
}
|
||||
reference_cog_this /= reference_frames[this_index].size();
|
||||
reference_cog_next /= reference_frames[next_index].size();
|
||||
// move all atoms to COM
|
||||
for (size_t i_atom = 0; i_atom < atoms->size(); ++i_atom) {
|
||||
this_frame_atom_pos[i_atom] = reference_frames[this_index][i_atom] - reference_cog_this;
|
||||
next_frame_atom_pos[i_atom] = reference_frames[next_index][i_atom] - reference_cog_next;
|
||||
}
|
||||
cvm::rotation rot_this_to_next;
|
||||
// compute the optimal rotation
|
||||
rot_this_to_next.calc_optimal_rotation(this_frame_atom_pos, next_frame_atom_pos);
|
||||
// compute rmsd between reference frames
|
||||
for (size_t i_atom = 0; i_atom < atoms->size(); ++i_atom) {
|
||||
frame_rmsd += (rot_this_to_next.q.rotate(this_frame_atom_pos[i_atom]) - next_frame_atom_pos[i_atom]).norm2();
|
||||
}
|
||||
frame_rmsd /= cvm::real(atoms->size());
|
||||
frame_rmsd = cvm::sqrt(frame_rmsd);
|
||||
result[i_frame] = frame_rmsd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void colvar::CartesianBasedPath::apply_force(colvarvalue const &force)
|
||||
{
|
||||
cvm::error("Error: using apply_force() in a component of type CartesianBasedPath, which is abstract.\n",
|
||||
COLVARS_BUG_ERROR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
colvar::gspath::gspath()
|
||||
{
|
||||
set_function_type("gspath");
|
||||
}
|
||||
|
||||
|
||||
int colvar::gspath::init(std::string const &conf)
|
||||
{
|
||||
int error_code = CartesianBasedPath::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
|
||||
get_keyval(conf, "useSecondClosestFrame", use_second_closest_frame, true);
|
||||
if (use_second_closest_frame == true) {
|
||||
cvm::log(std::string("Geometric path s(σ) will use the second closest frame to compute s_(m-1)\n"));
|
||||
@ -140,12 +198,14 @@ colvar::gspath::gspath(std::string const &conf): CartesianBasedPath(conf) {
|
||||
cvm::log(std::string("Geometric path s(σ) will use the neighbouring frame to compute s_(m+1)\n"));
|
||||
}
|
||||
if (total_reference_frames < 2) {
|
||||
cvm::error("Error: you have specified " + cvm::to_str(total_reference_frames) + " reference frames, but gspath requires at least 2 frames.\n");
|
||||
return;
|
||||
return cvm::error("Error: you have specified " + cvm::to_str(total_reference_frames) +
|
||||
" reference frames, but gspath requires at least 2 frames.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
GeometricPathCV::GeometricPathBase<cvm::atom_pos, cvm::real, GeometricPathCV::path_sz::S>::initialize(atoms->size(), cvm::atom_pos(), total_reference_frames, use_second_closest_frame, use_third_closest_frame);
|
||||
cvm::log(std::string("Geometric pathCV(s) is initialized.\n"));
|
||||
cvm::log(std::string("Geometric pathCV(s) loaded ") + cvm::to_str(reference_frames.size()) + std::string(" frames.\n"));
|
||||
return error_code;
|
||||
}
|
||||
|
||||
void colvar::gspath::updateDistanceToReferenceFrames() {
|
||||
@ -192,8 +252,9 @@ void colvar::gspath::prepareVectors() {
|
||||
} else {
|
||||
rot_v3.calc_optimal_rotation(tmp_reference_frame_1, tmp_reference_frame_2);
|
||||
}
|
||||
const auto rot_mat_v3 = rot_v3.matrix();
|
||||
for (i_atom = 0; i_atom < atoms->size(); ++i_atom) {
|
||||
v3[i_atom] = rot_v3.q.rotate(tmp_reference_frame_1[i_atom]) - tmp_reference_frame_2[i_atom];
|
||||
v3[i_atom] = rot_mat_v3 * tmp_reference_frame_1[i_atom] - tmp_reference_frame_2[i_atom];
|
||||
}
|
||||
} else {
|
||||
cvm::atom_pos reference_cog_1, reference_cog_3;
|
||||
@ -227,9 +288,10 @@ void colvar::gspath::prepareVectors() {
|
||||
} else {
|
||||
rot_v3.calc_optimal_rotation(tmp_reference_frame_1, tmp_reference_frame_3);
|
||||
}
|
||||
const auto rot_mat_v3 = rot_v3.matrix();
|
||||
for (i_atom = 0; i_atom < atoms->size(); ++i_atom) {
|
||||
// v3 = s_(m+1) - s_m
|
||||
v3[i_atom] = tmp_reference_frame_3[i_atom] - rot_v3.q.rotate(tmp_reference_frame_1[i_atom]);
|
||||
v3[i_atom] = tmp_reference_frame_3[i_atom] - rot_mat_v3 * tmp_reference_frame_1[i_atom];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -267,8 +329,17 @@ void colvar::gspath::apply_force(colvarvalue const &force) {
|
||||
(*(comp_atoms[min_frame_index_2])).apply_colvar_force(F);
|
||||
}
|
||||
|
||||
colvar::gzpath::gzpath(std::string const &conf): CartesianBasedPath(conf) {
|
||||
|
||||
colvar::gzpath::gzpath()
|
||||
{
|
||||
set_function_type("gzpath");
|
||||
}
|
||||
|
||||
int colvar::gzpath::init(std::string const &conf)
|
||||
{
|
||||
int error_code = CartesianBasedPath::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
|
||||
get_keyval(conf, "useSecondClosestFrame", use_second_closest_frame, true);
|
||||
if (use_second_closest_frame == true) {
|
||||
cvm::log(std::string("Geometric path z(σ) will use the second closest frame to compute s_(m-1)\n"));
|
||||
@ -287,13 +358,15 @@ colvar::gzpath::gzpath(std::string const &conf): CartesianBasedPath(conf) {
|
||||
cvm::log(std::string("Geometric path z(σ) will use the square of distance from current frame to path compute z\n"));
|
||||
}
|
||||
if (total_reference_frames < 2) {
|
||||
cvm::error("Error: you have specified " + cvm::to_str(total_reference_frames) + " reference frames, but gzpath requires at least 2 frames.\n");
|
||||
return;
|
||||
return cvm::error("Error: you have specified " + cvm::to_str(total_reference_frames) +
|
||||
" reference frames, but gzpath requires at least 2 frames.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
GeometricPathCV::GeometricPathBase<cvm::atom_pos, cvm::real, GeometricPathCV::path_sz::Z>::initialize(atoms->size(), cvm::atom_pos(), total_reference_frames, use_second_closest_frame, use_third_closest_frame, b_use_z_square);
|
||||
// Logging
|
||||
cvm::log(std::string("Geometric pathCV(z) is initialized.\n"));
|
||||
cvm::log(std::string("Geometric pathCV(z) loaded ") + cvm::to_str(reference_frames.size()) + std::string(" frames.\n"));
|
||||
return error_code;
|
||||
}
|
||||
|
||||
void colvar::gzpath::updateDistanceToReferenceFrames() {
|
||||
@ -335,12 +408,13 @@ void colvar::gzpath::prepareVectors() {
|
||||
} else {
|
||||
rot_v4.calc_optimal_rotation(tmp_reference_frame_1, tmp_reference_frame_2);
|
||||
}
|
||||
const auto rot_mat_v4 = rot_v4.matrix();
|
||||
for (i_atom = 0; i_atom < atoms->size(); ++i_atom) {
|
||||
v1[i_atom] = reference_frames[min_frame_index_1][i_atom] - (*(comp_atoms[min_frame_index_1]))[i_atom].pos;
|
||||
v2[i_atom] = (*(comp_atoms[min_frame_index_2]))[i_atom].pos - reference_frames[min_frame_index_2][i_atom];
|
||||
// v4 only computes in gzpath
|
||||
// v4 = s_m - s_(m-1)
|
||||
v4[i_atom] = rot_v4.q.rotate(tmp_reference_frame_1[i_atom]) - tmp_reference_frame_2[i_atom];
|
||||
v4[i_atom] = rot_mat_v4 * tmp_reference_frame_1[i_atom] - tmp_reference_frame_2[i_atom];
|
||||
}
|
||||
if (min_frame_index_3 < 0 || min_frame_index_3 > M) {
|
||||
v3 = v4;
|
||||
@ -368,9 +442,10 @@ void colvar::gzpath::prepareVectors() {
|
||||
} else {
|
||||
rot_v3.calc_optimal_rotation(tmp_reference_frame_1, tmp_reference_frame_3);
|
||||
}
|
||||
const auto rot_mat_v3 = rot_v3.matrix();
|
||||
for (i_atom = 0; i_atom < atoms->size(); ++i_atom) {
|
||||
// v3 = s_(m+1) - s_m
|
||||
v3[i_atom] = tmp_reference_frame_3[i_atom] - rot_v3.q.rotate(tmp_reference_frame_1[i_atom]);
|
||||
v3[i_atom] = tmp_reference_frame_3[i_atom] - rot_mat_v3 * tmp_reference_frame_1[i_atom];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -399,14 +474,26 @@ void colvar::gzpath::apply_force(colvarvalue const &force) {
|
||||
}
|
||||
|
||||
|
||||
colvar::CVBasedPath::CVBasedPath(std::string const &conf): cvc(conf) {
|
||||
colvar::CVBasedPath::CVBasedPath()
|
||||
{
|
||||
set_function_type("gspathCV");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
}
|
||||
|
||||
|
||||
int colvar::CVBasedPath::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
|
||||
// Lookup all available sub-cvcs
|
||||
for (auto it_cv_map = colvar::get_global_cvc_map().begin(); it_cv_map != colvar::get_global_cvc_map().end(); ++it_cv_map) {
|
||||
if (key_lookup(conf, it_cv_map->first.c_str())) {
|
||||
std::vector<std::string> sub_cvc_confs;
|
||||
get_key_string_multi_value(conf, it_cv_map->first.c_str(), sub_cvc_confs);
|
||||
for (auto it_sub_cvc_conf = sub_cvc_confs.begin(); it_sub_cvc_conf != sub_cvc_confs.end(); ++it_sub_cvc_conf) {
|
||||
cv.push_back((it_cv_map->second)(*(it_sub_cvc_conf)));
|
||||
cv.push_back((it_cv_map->second)());
|
||||
cv.back()->init(*(it_sub_cvc_conf));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -429,7 +516,7 @@ colvar::CVBasedPath::CVBasedPath(std::string const &conf): cvc(conf) {
|
||||
cvm::log(std::string("Reading path file: ") + path_filename + std::string("\n"));
|
||||
auto &ifs_path = cvm::main()->proxy->input_stream(path_filename);
|
||||
if (!ifs_path) {
|
||||
return;
|
||||
return COLVARS_INPUT_ERROR;
|
||||
}
|
||||
std::string line;
|
||||
const std::string token(" ");
|
||||
@ -450,8 +537,8 @@ colvar::CVBasedPath::CVBasedPath(std::string const &conf): cvc(conf) {
|
||||
cvm::log(cvm::to_str(tmp_cv[i_cv][i - start_index]));
|
||||
}
|
||||
} else {
|
||||
cvm::error("Error: incorrect format of path file.\n");
|
||||
return;
|
||||
error_code = cvm::error("Error: incorrect format of path file.\n", COLVARS_INPUT_ERROR);
|
||||
return error_code;
|
||||
}
|
||||
}
|
||||
if (!fields.empty()) {
|
||||
@ -461,15 +548,18 @@ colvar::CVBasedPath::CVBasedPath(std::string const &conf): cvc(conf) {
|
||||
}
|
||||
cvm::main()->proxy->close_input_stream(path_filename);
|
||||
if (total_reference_frames <= 1) {
|
||||
cvm::error("Error: there is only 1 or 0 reference frame, which doesn't constitute a path.\n");
|
||||
return;
|
||||
error_code = cvm::error(
|
||||
"Error: there is only 1 or 0 reference frame, which doesn't constitute a path.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return error_code;
|
||||
}
|
||||
if (cv.size() == 0) {
|
||||
cvm::error("Error: the CV " + name +
|
||||
" expects one or more nesting components.\n");
|
||||
return;
|
||||
error_code =
|
||||
cvm::error("Error: the CV " + name + " expects one or more nesting components.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return error_code;
|
||||
}
|
||||
x.type(colvarvalue::type_scalar);
|
||||
|
||||
use_explicit_gradients = true;
|
||||
for (size_t i_cv = 0; i_cv < cv.size(); ++i_cv) {
|
||||
if (!cv[i_cv]->is_enabled(f_cvc_explicit_gradient)) {
|
||||
@ -479,6 +569,8 @@ colvar::CVBasedPath::CVBasedPath(std::string const &conf): cvc(conf) {
|
||||
if (!use_explicit_gradients) {
|
||||
disable(f_cvc_explicit_gradient);
|
||||
}
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
void colvar::CVBasedPath::computeDistanceToReferenceFrames(std::vector<cvm::real>& result) {
|
||||
@ -548,8 +640,47 @@ colvar::CVBasedPath::~CVBasedPath() {
|
||||
atom_groups.clear();
|
||||
}
|
||||
|
||||
colvar::gspathCV::gspathCV(std::string const &conf): CVBasedPath(conf) {
|
||||
|
||||
void colvar::CVBasedPath::apply_force(colvarvalue const &force)
|
||||
{
|
||||
cvm::error("Error: using apply_force() in a component of type CVBasedPath, which is abstract.\n",
|
||||
COLVARS_BUG_ERROR);
|
||||
}
|
||||
|
||||
|
||||
cvm::real colvar::CVBasedPath::dist2(colvarvalue const &x1, colvarvalue const &x2) const
|
||||
{
|
||||
return x1.dist2(x2);
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::CVBasedPath::dist2_lgrad(colvarvalue const &x1, colvarvalue const &x2) const
|
||||
{
|
||||
return x1.dist2_grad(x2);
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::CVBasedPath::dist2_rgrad(colvarvalue const &x1, colvarvalue const &x2) const
|
||||
{
|
||||
return x2.dist2_grad(x1);
|
||||
}
|
||||
|
||||
|
||||
void colvar::CVBasedPath::wrap(colvarvalue & /* x_unwrapped */) const {}
|
||||
|
||||
|
||||
|
||||
colvar::gspathCV::gspathCV()
|
||||
{
|
||||
set_function_type("gspathCV");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
}
|
||||
|
||||
int colvar::gspathCV::init(std::string const &conf)
|
||||
{
|
||||
int error_code = CVBasedPath::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
|
||||
cvm::log(std::string("Total number of frames: ") + cvm::to_str(total_reference_frames) + std::string("\n"));
|
||||
// Initialize variables for future calculation
|
||||
get_keyval(conf, "useSecondClosestFrame", use_second_closest_frame, true);
|
||||
@ -565,11 +696,10 @@ colvar::gspathCV::gspathCV(std::string const &conf): CVBasedPath(conf) {
|
||||
cvm::log(std::string("Geometric path s(σ) will use the neighbouring frame to compute s_(m+1)\n"));
|
||||
}
|
||||
if (total_reference_frames < 2) {
|
||||
cvm::error("Error: you have specified " + cvm::to_str(total_reference_frames) + " reference frames, but gspathCV requires at least 2 frames.\n");
|
||||
return;
|
||||
return cvm::error("Error: you have specified " + cvm::to_str(total_reference_frames) + " reference frames, but gspathCV requires at least 2 frames.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
GeometricPathCV::GeometricPathBase<colvarvalue, cvm::real, GeometricPathCV::path_sz::S>::initialize(cv.size(), ref_cv[0], total_reference_frames, use_second_closest_frame, use_third_closest_frame);
|
||||
x.type(colvarvalue::type_scalar);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
colvar::gspathCV::~gspathCV() {}
|
||||
@ -671,8 +801,16 @@ void colvar::gspathCV::apply_force(colvarvalue const &force) {
|
||||
}
|
||||
}
|
||||
|
||||
colvar::gzpathCV::gzpathCV(std::string const &conf): CVBasedPath(conf) {
|
||||
colvar::gzpathCV::gzpathCV()
|
||||
{
|
||||
set_function_type("gzpathCV");
|
||||
}
|
||||
|
||||
int colvar::gzpathCV::init(std::string const &conf) {
|
||||
|
||||
int error_code = CVBasedPath::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
|
||||
cvm::log(std::string("Total number of frames: ") + cvm::to_str(total_reference_frames) + std::string("\n"));
|
||||
// Initialize variables for future calculation
|
||||
M = cvm::real(total_reference_frames - 1);
|
||||
@ -695,11 +833,13 @@ colvar::gzpathCV::gzpathCV(std::string const &conf): CVBasedPath(conf) {
|
||||
cvm::log(std::string("Geometric path z(σ) will use the square of distance from current frame to path compute z\n"));
|
||||
}
|
||||
if (total_reference_frames < 2) {
|
||||
cvm::error("Error: you have specified " + cvm::to_str(total_reference_frames) + " reference frames, but gzpathCV requires at least 2 frames.\n");
|
||||
return;
|
||||
return cvm::error("Error: you have specified " + cvm::to_str(total_reference_frames) +
|
||||
" reference frames, but gzpathCV requires at least 2 frames.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
GeometricPathCV::GeometricPathBase<colvarvalue, cvm::real, GeometricPathCV::path_sz::Z>::initialize(cv.size(), ref_cv[0], total_reference_frames, use_second_closest_frame, use_third_closest_frame, b_use_z_square);
|
||||
x.type(colvarvalue::type_scalar);
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
colvar::gzpathCV::~gzpathCV() {
|
||||
@ -794,5 +934,3 @@ void colvar::gzpathCV::apply_force(colvarvalue const &force) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,16 +1,31 @@
|
||||
#if (__cplusplus >= 201103L)
|
||||
// -*- 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.
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarcomp.h"
|
||||
#include "colvar_neuralnetworkcompute.h"
|
||||
|
||||
using namespace neuralnetworkCV;
|
||||
|
||||
colvar::neuralNetwork::neuralNetwork(std::string const &conf): linearCombination(conf) {
|
||||
|
||||
colvar::neuralNetwork::neuralNetwork()
|
||||
{
|
||||
set_function_type("neuralNetwork");
|
||||
}
|
||||
|
||||
|
||||
int colvar::neuralNetwork::init(std::string const &conf)
|
||||
{
|
||||
int error_code = linearCombination::init(conf);
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
// the output of neural network consists of multiple values
|
||||
// read "output_component" key to determine it
|
||||
get_keyval(conf, "output_component", m_output_index);
|
||||
@ -59,8 +74,8 @@ colvar::neuralNetwork::neuralNetwork(std::string const &conf): linearCombination
|
||||
std::string function_name;
|
||||
get_keyval(conf, lookup_key.c_str(), function_name, std::string(""));
|
||||
if (activation_function_map.find(function_name) == activation_function_map.end()) {
|
||||
cvm::error("Unknown activation function name: \"" + function_name + "\".\n");
|
||||
return;
|
||||
return cvm::error("Unknown activation function name: \"" + function_name + "\".\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
activation_functions.push_back(std::make_pair(false, function_name));
|
||||
cvm::log(std::string{"The activation function for layer["} + cvm::to_str(num_activation_functions + 1) + std::string{"] is "} + function_name + '\n');
|
||||
@ -79,11 +94,13 @@ colvar::neuralNetwork::neuralNetwork(std::string const &conf): linearCombination
|
||||
}
|
||||
// expect the three numbers are equal
|
||||
if ((num_layers_weight != num_layers_bias) || (num_layers_bias != num_activation_functions)) {
|
||||
cvm::error("Error: the numbers of weights, biases and activation functions do not match.\n");
|
||||
return;
|
||||
return cvm::error(
|
||||
"Error: the numbers of weights, biases and activation functions do not match.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
// nn = std::make_unique<neuralnetworkCV::neuralNetworkCompute>();
|
||||
// std::make_unique is only available in C++14
|
||||
if (nn) nn.reset();
|
||||
nn = std::unique_ptr<neuralnetworkCV::neuralNetworkCompute>(new neuralnetworkCV::neuralNetworkCompute());
|
||||
for (size_t i_layer = 0; i_layer < num_layers_weight; ++i_layer) {
|
||||
denseLayer d;
|
||||
@ -93,8 +110,9 @@ colvar::neuralNetwork::neuralNetwork(std::string const &conf): linearCombination
|
||||
try {
|
||||
d = denseLayer(weight_files[i_layer], bias_files[i_layer], activation_functions[i_layer].second);
|
||||
} catch (std::exception &ex) {
|
||||
cvm::error("Error on initializing layer " + cvm::to_str(i_layer) + " (" + ex.what() + ")\n", COLVARS_INPUT_ERROR);
|
||||
return;
|
||||
return cvm::error("Error on initializing layer " + cvm::to_str(i_layer) +
|
||||
" (" + ex.what() + ")\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
@ -104,8 +122,9 @@ colvar::neuralNetwork::neuralNetwork(std::string const &conf): linearCombination
|
||||
try {
|
||||
d = denseLayer(weight_files[i_layer], bias_files[i_layer], f, df);
|
||||
} catch (std::exception &ex) {
|
||||
cvm::error("Error on initializing layer " + cvm::to_str(i_layer) + " (" + ex.what() + ")\n", COLVARS_INPUT_ERROR);
|
||||
return;
|
||||
return cvm::error("Error on initializing layer " + cvm::to_str(i_layer) +
|
||||
" (" + ex.what() + ")\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
#ifdef LEPTON
|
||||
}
|
||||
@ -123,11 +142,11 @@ colvar::neuralNetwork::neuralNetwork(std::string const &conf): linearCombination
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cvm::error("Error: error on adding a new dense layer.\n");
|
||||
return;
|
||||
return cvm::error("Error: error on adding a new dense layer.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
}
|
||||
nn->input().resize(cv.size());
|
||||
return error_code;
|
||||
}
|
||||
|
||||
colvar::neuralNetwork::~neuralNetwork() {
|
||||
@ -185,4 +204,24 @@ void colvar::neuralNetwork::apply_force(colvarvalue const &force) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
cvm::real colvar::neuralNetwork::dist2(colvarvalue const &x1, colvarvalue const &x2) const
|
||||
{
|
||||
return x1.dist2(x2);
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::neuralNetwork::dist2_lgrad(colvarvalue const &x1, colvarvalue const &x2) const
|
||||
{
|
||||
return x1.dist2_grad(x2);
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::neuralNetwork::dist2_rgrad(colvarvalue const &x1, colvarvalue const &x2) const
|
||||
{
|
||||
return x2.dist2_grad(x1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void colvar::neuralNetwork::wrap(colvarvalue & /* x_unwrapped */) const {}
|
||||
|
||||
@ -11,19 +11,23 @@
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarcomp.h"
|
||||
|
||||
|
||||
colvar::alpha_angles::alpha_angles(std::string const &conf)
|
||||
: cvc(conf)
|
||||
colvar::alpha_angles::alpha_angles()
|
||||
{
|
||||
set_function_type("alpha");
|
||||
enable(f_cvc_explicit_gradient);
|
||||
x.type(colvarvalue::type_scalar);
|
||||
|
||||
colvarproxy *proxy = cvm::main()->proxy;
|
||||
r0 = proxy->angstrom_to_internal(3.3);
|
||||
}
|
||||
|
||||
|
||||
int colvar::alpha_angles::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
|
||||
std::string segment_id;
|
||||
get_keyval(conf, "psfSegID", segment_id, std::string("MAIN"));
|
||||
@ -44,29 +48,29 @@ colvar::alpha_angles::alpha_angles(std::string const &conf)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cvm::error("Error: no residues defined in \"residueRange\".\n");
|
||||
return;
|
||||
error_code |=
|
||||
cvm::error("Error: no residues defined in \"residueRange\".\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (residues.size() < 5) {
|
||||
cvm::error("Error: not enough residues defined in \"residueRange\".\n");
|
||||
return;
|
||||
error_code |= cvm::error("Error: not enough residues defined in \"residueRange\".\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
std::string const &sid = segment_id;
|
||||
std::vector<int> const &r = residues;
|
||||
|
||||
|
||||
get_keyval(conf, "hBondCoeff", hb_coeff, 0.5);
|
||||
if ( (hb_coeff < 0.0) || (hb_coeff > 1.0) ) {
|
||||
cvm::error("Error: hBondCoeff must be defined between 0 and 1.\n");
|
||||
return;
|
||||
get_keyval(conf, "hBondCoeff", hb_coeff, hb_coeff);
|
||||
if ((hb_coeff < 0.0) || (hb_coeff > 1.0)) {
|
||||
error_code |=
|
||||
cvm::error("Error: hBondCoeff must be defined between 0 and 1.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
|
||||
get_keyval(conf, "angleRef", theta_ref, 88.0);
|
||||
get_keyval(conf, "angleTol", theta_tol, 15.0);
|
||||
get_keyval(conf, "angleRef", theta_ref, theta_ref);
|
||||
get_keyval(conf, "angleTol", theta_tol, theta_tol);
|
||||
|
||||
if (hb_coeff < 1.0) {
|
||||
|
||||
@ -84,11 +88,9 @@ colvar::alpha_angles::alpha_angles(std::string const &conf)
|
||||
}
|
||||
|
||||
{
|
||||
cvm::real r0;
|
||||
size_t en, ed;
|
||||
get_keyval(conf, "hBondCutoff", r0, proxy->angstrom_to_internal(3.3));
|
||||
get_keyval(conf, "hBondExpNumer", en, 6);
|
||||
get_keyval(conf, "hBondExpDenom", ed, 8);
|
||||
get_keyval(conf, "hBondCutoff", r0, r0);
|
||||
get_keyval(conf, "hBondExpNumer", en, en);
|
||||
get_keyval(conf, "hBondExpDenom", ed, ed);
|
||||
|
||||
if (hb_coeff > 0.0) {
|
||||
|
||||
@ -103,15 +105,8 @@ colvar::alpha_angles::alpha_angles(std::string const &conf)
|
||||
cvm::log("The hBondCoeff specified will disable the hydrogen bond terms.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
colvar::alpha_angles::alpha_angles()
|
||||
: cvc()
|
||||
{
|
||||
set_function_type("alphaAngles");
|
||||
enable(f_cvc_explicit_gradient);
|
||||
x.type(colvarvalue::type_scalar);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
@ -273,24 +268,27 @@ void colvar::alpha_angles::apply_force(colvarvalue const &force)
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(alpha_angles)
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// dihedral principal component
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
colvar::dihedPC::dihedPC(std::string const &conf)
|
||||
: cvc(conf)
|
||||
colvar::dihedPC::dihedPC()
|
||||
{
|
||||
if (cvm::debug())
|
||||
cvm::log("Initializing dihedral PC object.\n");
|
||||
|
||||
set_function_type("dihedPC");
|
||||
// Supported through references to atom groups of children cvcs
|
||||
enable(f_cvc_explicit_gradient);
|
||||
x.type(colvarvalue::type_scalar);
|
||||
}
|
||||
|
||||
|
||||
int colvar::dihedPC::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
|
||||
if (cvm::debug())
|
||||
cvm::log("Initializing dihedral PC object.\n");
|
||||
|
||||
std::string segment_id;
|
||||
get_keyval(conf, "psfSegID", segment_id, std::string("MAIN"));
|
||||
@ -311,14 +309,14 @@ colvar::dihedPC::dihedPC(std::string const &conf)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cvm::error("Error: no residues defined in \"residueRange\".\n");
|
||||
return;
|
||||
error_code |=
|
||||
cvm::error("Error: no residues defined in \"residueRange\".\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (residues.size() < 2) {
|
||||
cvm::error("Error: dihedralPC requires at least two residues.\n");
|
||||
return;
|
||||
error_code |=
|
||||
cvm::error("Error: dihedralPC requires at least two residues.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
std::string const &sid = segment_id;
|
||||
@ -329,15 +327,15 @@ colvar::dihedPC::dihedPC(std::string const &conf)
|
||||
if (get_keyval(conf, "vectorFile", vecFileName, vecFileName)) {
|
||||
get_keyval(conf, "vectorNumber", vecNumber, 0);
|
||||
if (vecNumber < 1) {
|
||||
cvm::error("A positive value of vectorNumber is required.");
|
||||
return;
|
||||
error_code |=
|
||||
cvm::error("A positive value of vectorNumber is required.", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
std::istream &vecFile =
|
||||
cvm::main()->proxy->input_stream(vecFileName,
|
||||
"dihedral PCA vector file");
|
||||
if (!vecFile) {
|
||||
return;
|
||||
return COLVARS_INPUT_ERROR;
|
||||
}
|
||||
|
||||
// TODO: adapt to different formats by setting this flag
|
||||
@ -383,11 +381,10 @@ colvar::dihedPC::dihedPC(std::string const &conf)
|
||||
}
|
||||
|
||||
if ( coeffs.size() != 4 * (residues.size() - 1)) {
|
||||
cvm::error("Error: wrong number of coefficients: " +
|
||||
cvm::to_str(coeffs.size()) + ". Expected " +
|
||||
cvm::to_str(4 * (residues.size() - 1)) +
|
||||
" (4 coeffs per residue, minus one residue).\n");
|
||||
return;
|
||||
error_code |= cvm::error("Error: wrong number of coefficients: " + cvm::to_str(coeffs.size()) +
|
||||
". Expected " + cvm::to_str(4 * (residues.size() - 1)) +
|
||||
" (4 coeffs per residue, minus one residue).\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < residues.size()-1; i++) {
|
||||
@ -413,16 +410,8 @@ colvar::dihedPC::dihedPC(std::string const &conf)
|
||||
|
||||
if (cvm::debug())
|
||||
cvm::log("Done initializing dihedPC object.\n");
|
||||
}
|
||||
|
||||
|
||||
colvar::dihedPC::dihedPC()
|
||||
: cvc()
|
||||
{
|
||||
set_function_type("dihedPC");
|
||||
// Supported through references to atom groups of children cvcs
|
||||
enable(f_cvc_explicit_gradient);
|
||||
x.type(colvarvalue::type_scalar);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
@ -491,6 +480,3 @@ void colvar::dihedPC::apply_force(colvarvalue const &force)
|
||||
coeffs[2*i+1] * dsindt) * force);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(dihedPC)
|
||||
|
||||
@ -9,27 +9,39 @@
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarcomp.h"
|
||||
#include "colvar_rotation_derivative.h"
|
||||
|
||||
|
||||
struct colvar::orientation::rotation_derivative_impl_: public rotation_derivative<cvm::atom_pos, cvm::atom_pos> {
|
||||
public:
|
||||
rotation_derivative_impl_(colvar::orientation* orientation_cvc):
|
||||
rotation_derivative<cvm::atom_pos, cvm::atom_pos>(
|
||||
orientation_cvc->rot, orientation_cvc->ref_pos, orientation_cvc->shifted_pos) {}
|
||||
};
|
||||
|
||||
colvar::orientation::orientation(std::string const &conf)
|
||||
: cvc()
|
||||
|
||||
colvar::orientation::orientation()
|
||||
{
|
||||
set_function_type("orientation");
|
||||
rot_deriv_impl = std::unique_ptr<rotation_derivative_impl_>(new rotation_derivative_impl_(this));
|
||||
disable(f_cvc_explicit_gradient);
|
||||
x.type(colvarvalue::type_quaternion);
|
||||
colvar::orientation::init(conf);
|
||||
}
|
||||
|
||||
|
||||
colvar::orientation::~orientation() {}
|
||||
|
||||
|
||||
int colvar::orientation::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
|
||||
atoms = parse_group(conf, "atoms");
|
||||
if (!atoms || atoms->size() == 0) {
|
||||
return error_code | COLVARS_INPUT_ERROR;
|
||||
}
|
||||
ref_pos.reserve(atoms->size());
|
||||
|
||||
if (get_keyval(conf, "refPositions", ref_pos, ref_pos)) {
|
||||
@ -56,17 +68,18 @@ int colvar::orientation::init(std::string const &conf)
|
||||
}
|
||||
|
||||
ref_pos.resize(atoms->size());
|
||||
cvm::load_coords(file_name.c_str(), &ref_pos, atoms,
|
||||
error_code |= cvm::load_coords(file_name.c_str(), &ref_pos, atoms,
|
||||
file_col, file_col_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
|
||||
if (!ref_pos.size()) {
|
||||
return cvm::error("Error: must define a set of "
|
||||
"reference coordinates.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
|
||||
cvm::rvector ref_cog(0.0, 0.0, 0.0);
|
||||
size_t i;
|
||||
for (i = 0; i < ref_pos.size(); i++) {
|
||||
@ -84,30 +97,21 @@ int colvar::orientation::init(std::string const &conf)
|
||||
|
||||
get_keyval(conf, "closestToQuaternion", ref_quat, cvm::quaternion(1.0, 0.0, 0.0, 0.0));
|
||||
|
||||
// initialize rot member data
|
||||
if (!atoms->noforce) {
|
||||
rot.request_group2_gradients(atoms->size());
|
||||
}
|
||||
// If the debug gradients feature is active, debug the rotation gradients
|
||||
// (note that this won't be active for the orientation CVC itself, because
|
||||
// colvardeps prevents the flag's activation)
|
||||
rot.b_debug_gradients = is_enabled(f_cvc_debug_gradient);
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
colvar::orientation::orientation()
|
||||
: cvc()
|
||||
{
|
||||
set_function_type("orientation");
|
||||
disable(f_cvc_explicit_gradient);
|
||||
x.type(colvarvalue::type_quaternion);
|
||||
}
|
||||
|
||||
|
||||
void colvar::orientation::calc_value()
|
||||
{
|
||||
rot.b_debug_gradients = is_enabled(f_cvc_debug_gradient);
|
||||
atoms_cog = atoms->center_of_geometry();
|
||||
|
||||
rot.calc_optimal_rotation(ref_pos, atoms->positions_shifted(-1.0 * atoms_cog));
|
||||
shifted_pos = atoms->positions_shifted(-1.0 * atoms_cog);
|
||||
rot.calc_optimal_rotation(ref_pos, shifted_pos);
|
||||
|
||||
if ((rot.q).inner(ref_quat) >= 0.0) {
|
||||
x.quaternion_value = rot.q;
|
||||
@ -131,9 +135,12 @@ void colvar::orientation::apply_force(colvarvalue const &force)
|
||||
cvm::quaternion const &FQ = force.quaternion_value;
|
||||
|
||||
if (!atoms->noforce) {
|
||||
rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq);
|
||||
cvm::vector1d<cvm::rvector> dq0_2;
|
||||
for (size_t ia = 0; ia < atoms->size(); ia++) {
|
||||
rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2);
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
(*atoms)[ia].apply_force(FQ[i] * rot.dQ0_2[ia][i]);
|
||||
(*atoms)[ia].apply_force(FQ[i] * dq0_2[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -161,20 +168,15 @@ colvarvalue colvar::orientation::dist2_rgrad(colvarvalue const &x1,
|
||||
}
|
||||
|
||||
|
||||
void colvar::orientation::wrap(colvarvalue & /* x_unwrapped */) const {}
|
||||
|
||||
colvar::orientation_angle::orientation_angle(std::string const &conf)
|
||||
: orientation()
|
||||
|
||||
|
||||
colvar::orientation_angle::orientation_angle()
|
||||
{
|
||||
set_function_type("orientationAngle");
|
||||
init_as_angle();
|
||||
enable(f_cvc_explicit_gradient);
|
||||
orientation_angle::init(conf);
|
||||
}
|
||||
|
||||
|
||||
int colvar::orientation_angle::init(std::string const &conf)
|
||||
{
|
||||
return orientation::init(conf);
|
||||
}
|
||||
|
||||
|
||||
@ -182,7 +184,8 @@ void colvar::orientation_angle::calc_value()
|
||||
{
|
||||
atoms_cog = atoms->center_of_geometry();
|
||||
|
||||
rot.calc_optimal_rotation(ref_pos, atoms->positions_shifted(-1.0 * atoms_cog));
|
||||
shifted_pos = atoms->positions_shifted(-1.0 * atoms_cog);
|
||||
rot.calc_optimal_rotation(ref_pos, shifted_pos);
|
||||
|
||||
if ((rot.q).q0 >= 0.0) {
|
||||
x.real_value = (180.0/PI) * 2.0 * cvm::acos((rot.q).q0);
|
||||
@ -199,46 +202,59 @@ void colvar::orientation_angle::calc_gradients()
|
||||
((180.0 / PI) * (-2.0) / cvm::sqrt(1.0 - ((rot.q).q0 * (rot.q).q0))) :
|
||||
0.0 );
|
||||
|
||||
rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq);
|
||||
cvm::vector1d<cvm::rvector> dq0_2;
|
||||
for (size_t ia = 0; ia < atoms->size(); ia++) {
|
||||
(*atoms)[ia].grad = (dxdq0 * (rot.dQ0_2[ia])[0]);
|
||||
rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2);
|
||||
(*atoms)[ia].grad = (dxdq0 * dq0_2[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void colvar::orientation_angle::apply_force(colvarvalue const &force)
|
||||
{
|
||||
cvm::real const &fw = force.real_value;
|
||||
if (!atoms->noforce) {
|
||||
atoms->apply_colvar_force(fw);
|
||||
}
|
||||
cvc::apply_force(force);
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(orientation_angle)
|
||||
cvm::real colvar::orientation_angle::dist2(colvarvalue const &x1, colvarvalue const &x2) const
|
||||
{
|
||||
return cvc::dist2(x1, x2);
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::orientation_angle::dist2_lgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
return cvc::dist2_lgrad(x1, x2);
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::orientation_angle::dist2_rgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
return cvc::dist2_rgrad(x1, x2);
|
||||
}
|
||||
|
||||
|
||||
void colvar::orientation_angle::wrap(colvarvalue & /* x_unwrapped */) const {}
|
||||
|
||||
|
||||
|
||||
colvar::orientation_proj::orientation_proj(std::string const &conf)
|
||||
: orientation()
|
||||
colvar::orientation_proj::orientation_proj()
|
||||
{
|
||||
set_function_type("orientationProj");
|
||||
enable(f_cvc_explicit_gradient);
|
||||
x.type(colvarvalue::type_scalar);
|
||||
init_scalar_boundaries(0.0, 1.0);
|
||||
orientation_proj::init(conf);
|
||||
}
|
||||
|
||||
|
||||
int colvar::orientation_proj::init(std::string const &conf)
|
||||
{
|
||||
return orientation::init(conf);
|
||||
}
|
||||
|
||||
|
||||
void colvar::orientation_proj::calc_value()
|
||||
{
|
||||
atoms_cog = atoms->center_of_geometry();
|
||||
rot.calc_optimal_rotation(ref_pos, atoms->positions_shifted(-1.0 * atoms_cog));
|
||||
shifted_pos = atoms->positions_shifted(-1.0 * atoms_cog);
|
||||
rot.calc_optimal_rotation(ref_pos, shifted_pos);
|
||||
x.real_value = 2.0 * (rot.q).q0 * (rot.q).q0 - 1.0;
|
||||
}
|
||||
|
||||
@ -246,42 +262,28 @@ void colvar::orientation_proj::calc_value()
|
||||
void colvar::orientation_proj::calc_gradients()
|
||||
{
|
||||
cvm::real const dxdq0 = 2.0 * 2.0 * (rot.q).q0;
|
||||
rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq);
|
||||
cvm::vector1d<cvm::rvector> dq0_2;
|
||||
for (size_t ia = 0; ia < atoms->size(); ia++) {
|
||||
(*atoms)[ia].grad = (dxdq0 * (rot.dQ0_2[ia])[0]);
|
||||
rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2);
|
||||
(*atoms)[ia].grad = (dxdq0 * dq0_2[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void colvar::orientation_proj::apply_force(colvarvalue const &force)
|
||||
{
|
||||
cvm::real const &fw = force.real_value;
|
||||
|
||||
if (!atoms->noforce) {
|
||||
atoms->apply_colvar_force(fw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(orientation_proj)
|
||||
|
||||
|
||||
|
||||
colvar::tilt::tilt(std::string const &conf)
|
||||
: orientation()
|
||||
colvar::tilt::tilt()
|
||||
{
|
||||
set_function_type("tilt");
|
||||
x.type(colvarvalue::type_scalar);
|
||||
enable(f_cvc_explicit_gradient);
|
||||
init_scalar_boundaries(-1.0, 1.0);
|
||||
tilt::init(conf);
|
||||
}
|
||||
|
||||
|
||||
int colvar::tilt::init(std::string const &conf)
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
|
||||
error_code |= orientation::init(conf);
|
||||
int error_code = orientation_proj::init(conf);
|
||||
|
||||
get_keyval(conf, "axis", axis, cvm::rvector(0.0, 0.0, 1.0));
|
||||
if (axis.norm2() != 1.0) {
|
||||
@ -297,7 +299,8 @@ void colvar::tilt::calc_value()
|
||||
{
|
||||
atoms_cog = atoms->center_of_geometry();
|
||||
|
||||
rot.calc_optimal_rotation(ref_pos, atoms->positions_shifted(-1.0 * atoms_cog));
|
||||
shifted_pos = atoms->positions_shifted(-1.0 * atoms_cog);
|
||||
rot.calc_optimal_rotation(ref_pos, shifted_pos);
|
||||
|
||||
x.real_value = rot.cos_theta(axis);
|
||||
}
|
||||
@ -307,64 +310,24 @@ void colvar::tilt::calc_gradients()
|
||||
{
|
||||
cvm::quaternion const dxdq = rot.dcos_theta_dq(axis);
|
||||
|
||||
rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq);
|
||||
cvm::vector1d<cvm::rvector> dq0_2;
|
||||
for (size_t ia = 0; ia < atoms->size(); ia++) {
|
||||
(*atoms)[ia].grad = cvm::rvector(0.0, 0.0, 0.0);
|
||||
rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2);
|
||||
for (size_t iq = 0; iq < 4; iq++) {
|
||||
(*atoms)[ia].grad += (dxdq[iq] * (rot.dQ0_2[ia])[iq]);
|
||||
(*atoms)[ia].grad += (dxdq[iq] * dq0_2[iq]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void colvar::tilt::apply_force(colvarvalue const &force)
|
||||
{
|
||||
cvm::real const &fw = force.real_value;
|
||||
|
||||
if (!atoms->noforce) {
|
||||
atoms->apply_colvar_force(fw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
simple_scalar_dist_functions(tilt)
|
||||
|
||||
|
||||
|
||||
colvar::spin_angle::spin_angle(std::string const &conf)
|
||||
: orientation()
|
||||
{
|
||||
set_function_type("spinAngle");
|
||||
init_as_periodic_angle();
|
||||
enable(f_cvc_periodic);
|
||||
enable(f_cvc_explicit_gradient);
|
||||
spin_angle::init(conf);
|
||||
}
|
||||
|
||||
|
||||
int colvar::spin_angle::init(std::string const &conf)
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
|
||||
error_code |= orientation::init(conf);
|
||||
|
||||
get_keyval(conf, "axis", axis, cvm::rvector(0.0, 0.0, 1.0));
|
||||
if (axis.norm2() != 1.0) {
|
||||
axis /= axis.norm();
|
||||
cvm::log("Normalizing rotation axis to "+cvm::to_str(axis)+".\n");
|
||||
}
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
colvar::spin_angle::spin_angle()
|
||||
: orientation()
|
||||
{
|
||||
set_function_type("spinAngle");
|
||||
period = 360.0;
|
||||
enable(f_cvc_periodic);
|
||||
init_as_periodic_angle();
|
||||
enable(f_cvc_explicit_gradient);
|
||||
x.type(colvarvalue::type_scalar);
|
||||
}
|
||||
|
||||
|
||||
@ -372,10 +335,11 @@ void colvar::spin_angle::calc_value()
|
||||
{
|
||||
atoms_cog = atoms->center_of_geometry();
|
||||
|
||||
rot.calc_optimal_rotation(ref_pos, atoms->positions_shifted(-1.0 * atoms_cog));
|
||||
shifted_pos = atoms->positions_shifted(-1.0 * atoms_cog);
|
||||
rot.calc_optimal_rotation(ref_pos, shifted_pos);
|
||||
|
||||
x.real_value = rot.spin_angle(axis);
|
||||
this->wrap(x);
|
||||
wrap(x);
|
||||
}
|
||||
|
||||
|
||||
@ -383,80 +347,20 @@ void colvar::spin_angle::calc_gradients()
|
||||
{
|
||||
cvm::quaternion const dxdq = rot.dspin_angle_dq(axis);
|
||||
|
||||
rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq);
|
||||
cvm::vector1d<cvm::rvector> dq0_2;
|
||||
for (size_t ia = 0; ia < atoms->size(); ia++) {
|
||||
(*atoms)[ia].grad = cvm::rvector(0.0, 0.0, 0.0);
|
||||
rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2);
|
||||
for (size_t iq = 0; iq < 4; iq++) {
|
||||
(*atoms)[ia].grad += (dxdq[iq] * (rot.dQ0_2[ia])[iq]);
|
||||
(*atoms)[ia].grad += (dxdq[iq] * dq0_2[iq]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void colvar::spin_angle::apply_force(colvarvalue const &force)
|
||||
{
|
||||
cvm::real const &fw = force.real_value;
|
||||
|
||||
if (!atoms->noforce) {
|
||||
atoms->apply_colvar_force(fw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cvm::real colvar::spin_angle::dist2(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return diff * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::spin_angle::dist2_lgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return 2.0 * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::spin_angle::dist2_rgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return (-2.0) * diff;
|
||||
}
|
||||
|
||||
|
||||
void colvar::spin_angle::wrap(colvarvalue &x_unwrapped) const
|
||||
{
|
||||
if ((x_unwrapped.real_value - wrap_center) >= 180.0) {
|
||||
x_unwrapped.real_value -= 360.0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((x_unwrapped.real_value - wrap_center) < -180.0) {
|
||||
x_unwrapped.real_value += 360.0;
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
colvar::euler_phi::euler_phi(std::string const &conf)
|
||||
: orientation()
|
||||
{
|
||||
set_function_type("eulerPhi");
|
||||
init_as_periodic_angle();
|
||||
enable(f_cvc_explicit_gradient);
|
||||
euler_phi::init(conf);
|
||||
}
|
||||
|
||||
|
||||
colvar::euler_phi::euler_phi()
|
||||
: orientation()
|
||||
{
|
||||
set_function_type("eulerPhi");
|
||||
init_as_periodic_angle();
|
||||
@ -464,19 +368,12 @@ colvar::euler_phi::euler_phi()
|
||||
}
|
||||
|
||||
|
||||
int colvar::euler_phi::init(std::string const &conf)
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
error_code |= orientation::init(conf);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
void colvar::euler_phi::calc_value()
|
||||
{
|
||||
atoms_cog = atoms->center_of_geometry();
|
||||
|
||||
rot.calc_optimal_rotation(ref_pos, atoms->positions_shifted(-1.0 * atoms_cog));
|
||||
shifted_pos = atoms->positions_shifted(-1.0 * atoms_cog);
|
||||
rot.calc_optimal_rotation(ref_pos, shifted_pos);
|
||||
|
||||
const cvm::real& q0 = rot.q.q0;
|
||||
const cvm::real& q1 = rot.q.q1;
|
||||
@ -499,79 +396,20 @@ void colvar::euler_phi::calc_gradients()
|
||||
const cvm::real dxdq1 = (180.0/PI) * (2 * q0 * (-2 * q1 * q1 - 2 * q2 * q2 + 1) - 4 * q1 * (-2 * q0 * q1 - 2 * q2 * q3)) / denominator;
|
||||
const cvm::real dxdq2 = (180.0/PI) * (-4 * q2 * (-2 * q0 * q1 - 2 * q2 * q3) + 2 * q3 * (-2 * q1 * q1 - 2 * q2 * q2 + 1)) / denominator;
|
||||
const cvm::real dxdq3 = (180.0/PI) * 2 * q2 * (-2 * q1 * q1 - 2 * q2 * q2 + 1) / denominator;
|
||||
rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq);
|
||||
cvm::vector1d<cvm::rvector> dq0_2;
|
||||
for (size_t ia = 0; ia < atoms->size(); ia++) {
|
||||
(*atoms)[ia].grad = (dxdq0 * (rot.dQ0_2[ia])[0]) +
|
||||
(dxdq1 * (rot.dQ0_2[ia])[1]) +
|
||||
(dxdq2 * (rot.dQ0_2[ia])[2]) +
|
||||
(dxdq3 * (rot.dQ0_2[ia])[3]);
|
||||
rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2);
|
||||
(*atoms)[ia].grad = (dxdq0 * dq0_2[0]) +
|
||||
(dxdq1 * dq0_2[1]) +
|
||||
(dxdq2 * dq0_2[2]) +
|
||||
(dxdq3 * dq0_2[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void colvar::euler_phi::apply_force(colvarvalue const &force)
|
||||
{
|
||||
cvm::real const &fw = force.real_value;
|
||||
if (!atoms->noforce) {
|
||||
atoms->apply_colvar_force(fw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cvm::real colvar::euler_phi::dist2(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return diff * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::euler_phi::dist2_lgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return 2.0 * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::euler_phi::dist2_rgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return (-2.0) * diff;
|
||||
}
|
||||
|
||||
|
||||
void colvar::euler_phi::wrap(colvarvalue &x_unwrapped) const
|
||||
{
|
||||
if ((x_unwrapped.real_value - wrap_center) >= 180.0) {
|
||||
x_unwrapped.real_value -= 360.0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((x_unwrapped.real_value - wrap_center) < -180.0) {
|
||||
x_unwrapped.real_value += 360.0;
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
colvar::euler_psi::euler_psi(std::string const &conf)
|
||||
: orientation()
|
||||
{
|
||||
set_function_type("eulerPsi");
|
||||
init_as_periodic_angle();
|
||||
enable(f_cvc_explicit_gradient);
|
||||
euler_psi::init(conf);
|
||||
}
|
||||
|
||||
|
||||
colvar::euler_psi::euler_psi()
|
||||
: orientation()
|
||||
{
|
||||
set_function_type("eulerPsi");
|
||||
init_as_periodic_angle();
|
||||
@ -579,19 +417,12 @@ colvar::euler_psi::euler_psi()
|
||||
}
|
||||
|
||||
|
||||
int colvar::euler_psi::init(std::string const &conf)
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
error_code |= orientation::init(conf);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
void colvar::euler_psi::calc_value()
|
||||
{
|
||||
atoms_cog = atoms->center_of_geometry();
|
||||
|
||||
rot.calc_optimal_rotation(ref_pos, atoms->positions_shifted(-1.0 * atoms_cog));
|
||||
shifted_pos = atoms->positions_shifted(-1.0 * atoms_cog);
|
||||
rot.calc_optimal_rotation(ref_pos, shifted_pos);
|
||||
|
||||
const cvm::real& q0 = rot.q.q0;
|
||||
const cvm::real& q1 = rot.q.q1;
|
||||
@ -614,79 +445,20 @@ void colvar::euler_psi::calc_gradients()
|
||||
const cvm::real dxdq1 = (180.0/PI) * 2 * q2 * (-2 * q2 * q2 - 2 * q3 * q3 + 1) / denominator;
|
||||
const cvm::real dxdq2 = (180.0/PI) * (2 * q1 * (-2 * q2 * q2 - 2 * q3 * q3 + 1) - 4 * q2 * (-2 * q0 * q3 - 2 * q1 * q2)) / denominator;
|
||||
const cvm::real dxdq3 = (180.0/PI) * (2 * q0 * (-2 * q2 * q2 - 2 * q3 * q3 + 1) - 4 * q3 * (-2 * q0 * q3 - 2 * q1 * q2)) / denominator;
|
||||
rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq);
|
||||
cvm::vector1d<cvm::rvector> dq0_2;
|
||||
for (size_t ia = 0; ia < atoms->size(); ia++) {
|
||||
(*atoms)[ia].grad = (dxdq0 * (rot.dQ0_2[ia])[0]) +
|
||||
(dxdq1 * (rot.dQ0_2[ia])[1]) +
|
||||
(dxdq2 * (rot.dQ0_2[ia])[2]) +
|
||||
(dxdq3 * (rot.dQ0_2[ia])[3]);
|
||||
rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2);
|
||||
(*atoms)[ia].grad = (dxdq0 * dq0_2[0]) +
|
||||
(dxdq1 * dq0_2[1]) +
|
||||
(dxdq2 * dq0_2[2]) +
|
||||
(dxdq3 * dq0_2[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void colvar::euler_psi::apply_force(colvarvalue const &force)
|
||||
{
|
||||
cvm::real const &fw = force.real_value;
|
||||
if (!atoms->noforce) {
|
||||
atoms->apply_colvar_force(fw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cvm::real colvar::euler_psi::dist2(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return diff * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::euler_psi::dist2_lgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return 2.0 * diff;
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::euler_psi::dist2_rgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
cvm::real diff = x1.real_value - x2.real_value;
|
||||
diff = (diff < -180.0 ? diff + 360.0 : (diff > 180.0 ? diff - 360.0 : diff));
|
||||
return (-2.0) * diff;
|
||||
}
|
||||
|
||||
|
||||
void colvar::euler_psi::wrap(colvarvalue &x_unwrapped) const
|
||||
{
|
||||
if ((x_unwrapped.real_value - wrap_center) >= 180.0) {
|
||||
x_unwrapped.real_value -= 360.0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((x_unwrapped.real_value - wrap_center) < -180.0) {
|
||||
x_unwrapped.real_value += 360.0;
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
colvar::euler_theta::euler_theta(std::string const &conf)
|
||||
: orientation()
|
||||
{
|
||||
set_function_type("eulerTheta");
|
||||
init_as_angle();
|
||||
enable(f_cvc_explicit_gradient);
|
||||
euler_theta::init(conf);
|
||||
}
|
||||
|
||||
|
||||
colvar::euler_theta::euler_theta()
|
||||
: orientation()
|
||||
{
|
||||
set_function_type("eulerTheta");
|
||||
init_as_angle();
|
||||
@ -694,19 +466,12 @@ colvar::euler_theta::euler_theta()
|
||||
}
|
||||
|
||||
|
||||
int colvar::euler_theta::init(std::string const &conf)
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
error_code |= orientation::init(conf);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
void colvar::euler_theta::calc_value()
|
||||
{
|
||||
atoms_cog = atoms->center_of_geometry();
|
||||
|
||||
rot.calc_optimal_rotation(ref_pos, atoms->positions_shifted(-1.0 * atoms_cog));
|
||||
shifted_pos = atoms->positions_shifted(-1.0 * atoms_cog);
|
||||
rot.calc_optimal_rotation(ref_pos, shifted_pos);
|
||||
|
||||
const cvm::real& q0 = rot.q.q0;
|
||||
const cvm::real& q1 = rot.q.q1;
|
||||
@ -727,43 +492,13 @@ void colvar::euler_theta::calc_gradients()
|
||||
const cvm::real dxdq1 = (180.0/PI) * -2 * q3 / denominator;
|
||||
const cvm::real dxdq2 = (180.0/PI) * 2 * q0 / denominator;
|
||||
const cvm::real dxdq3 = (180.0/PI) * -2 * q1 / denominator;
|
||||
rot_deriv_impl->prepare_derivative(rotation_derivative_dldq::use_dq);
|
||||
cvm::vector1d<cvm::rvector> dq0_2;
|
||||
for (size_t ia = 0; ia < atoms->size(); ia++) {
|
||||
(*atoms)[ia].grad = (dxdq0 * (rot.dQ0_2[ia])[0]) +
|
||||
(dxdq1 * (rot.dQ0_2[ia])[1]) +
|
||||
(dxdq2 * (rot.dQ0_2[ia])[2]) +
|
||||
(dxdq3 * (rot.dQ0_2[ia])[3]);
|
||||
rot_deriv_impl->calc_derivative_wrt_group2(ia, nullptr, &dq0_2);
|
||||
(*atoms)[ia].grad = (dxdq0 * dq0_2[0]) +
|
||||
(dxdq1 * dq0_2[1]) +
|
||||
(dxdq2 * dq0_2[2]) +
|
||||
(dxdq3 * dq0_2[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void colvar::euler_theta::apply_force(colvarvalue const &force)
|
||||
{
|
||||
cvm::real const &fw = force.real_value;
|
||||
if (!atoms->noforce) {
|
||||
atoms->apply_colvar_force(fw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cvm::real colvar::euler_theta::dist2(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
// theta angle is not periodic
|
||||
return cvc::dist2(x1, x2);
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::euler_theta::dist2_lgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
// theta angle is not periodic
|
||||
return cvc::dist2_lgrad(x1, x2);
|
||||
}
|
||||
|
||||
|
||||
colvarvalue colvar::euler_theta::dist2_rgrad(colvarvalue const &x1,
|
||||
colvarvalue const &x2) const
|
||||
{
|
||||
// theta angle is not periodic
|
||||
return cvc::dist2_rgrad(x1, x2);
|
||||
}
|
||||
|
||||
@ -9,35 +9,18 @@
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarcomp.h"
|
||||
|
||||
|
||||
|
||||
colvar::map_total::map_total()
|
||||
: cvc()
|
||||
{
|
||||
set_function_type("mapTotal");
|
||||
volmap_id = -1;
|
||||
volmap_index = -1;
|
||||
atoms = NULL;
|
||||
x.type(colvarvalue::type_scalar);
|
||||
}
|
||||
|
||||
|
||||
colvar::map_total::map_total(std::string const &conf)
|
||||
: cvc() // init() will take care of this
|
||||
{
|
||||
set_function_type("mapTotal");
|
||||
volmap_id = -1;
|
||||
volmap_index = -1;
|
||||
atoms = NULL;
|
||||
x.type(colvarvalue::type_scalar);
|
||||
map_total::init(conf);
|
||||
}
|
||||
|
||||
|
||||
int colvar::map_total::init(std::string const &conf)
|
||||
{
|
||||
int error_code = cvc::init(conf);
|
||||
@ -50,12 +33,12 @@ int colvar::map_total::init(std::string const &conf)
|
||||
|
||||
if ((volmap_name.size() > 0) && (volmap_id >= 0)) {
|
||||
error_code |=
|
||||
cvm::error("Error: mapName and mapID are mutually exclusive.\n");
|
||||
cvm::error("Error: mapName and mapID are mutually exclusive.\n", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
// Parse optional group
|
||||
atoms = parse_group(conf, "atoms", true);
|
||||
if (atoms != NULL) {
|
||||
if (atoms) {
|
||||
|
||||
// Using internal selection
|
||||
if (volmap_name.size()) {
|
||||
@ -74,11 +57,11 @@ int colvar::map_total::init(std::string const &conf)
|
||||
if (volmap_id >= 0) {
|
||||
volmap_index = proxy->init_volmap_by_id(volmap_id);
|
||||
}
|
||||
error_code |= volmap_index > 0 ? COLVARS_OK : COLVARS_INPUT_ERROR;
|
||||
error_code |= (volmap_index >= 0) ? COLVARS_OK : COLVARS_INPUT_ERROR;
|
||||
}
|
||||
|
||||
if (get_keyval(conf, "atomWeights", atom_weights, atom_weights)) {
|
||||
if (atoms == NULL) {
|
||||
if (!atoms) {
|
||||
error_code |= cvm::error("Error: weights can only be assigned when atoms "
|
||||
"are selected explicitly in Colvars.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
@ -133,11 +116,10 @@ void colvar::map_total::calc_gradients()
|
||||
|
||||
void colvar::map_total::apply_force(colvarvalue const &force)
|
||||
{
|
||||
colvarproxy *proxy = cvm::main()->proxy;
|
||||
if (atoms) {
|
||||
if (!atoms->noforce)
|
||||
atoms->apply_colvar_force(force.real_value);
|
||||
cvc::apply_force(force);
|
||||
} else {
|
||||
colvarproxy *proxy = cvm::main()->proxy;
|
||||
proxy->apply_volmap_force(volmap_index, force.real_value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,6 +129,11 @@ int colvardeps::enable(int feature_id,
|
||||
int res;
|
||||
size_t i, j;
|
||||
bool ok;
|
||||
|
||||
if (feature_id < 0 || feature_id >= int(features().size())) {
|
||||
cvm::error("Error: colvardeps::enable() called with invalid feature_id " + cvm::to_str(feature_id) + "\n");
|
||||
return COLVARS_ERROR;
|
||||
}
|
||||
feature *f = features()[feature_id];
|
||||
feature_state *fs = &feature_states[feature_id];
|
||||
|
||||
|
||||
@ -253,6 +253,8 @@ public:
|
||||
f_cvb_write_ti_pmf,
|
||||
/// \brief whether this bias uses an external grid to scale the biasing forces
|
||||
f_cvb_scale_biasing_force,
|
||||
/// \brief whether this bias is applied to one or more ext-Lagrangian colvars
|
||||
f_cvb_extended,
|
||||
f_cvb_ntot
|
||||
};
|
||||
|
||||
@ -355,6 +357,8 @@ public:
|
||||
f_cvc_lower_boundary,
|
||||
/// This CVC provides a default value for the colvar's upper boundary
|
||||
f_cvc_upper_boundary,
|
||||
/// CVC accesses atom groups directly (as opposed to going throuh other objects)
|
||||
f_cvc_explicit_atom_groups,
|
||||
/// CVC calculates atom gradients
|
||||
f_cvc_gradient,
|
||||
/// CVC calculates and stores explicit atom gradients on rank 0
|
||||
|
||||
@ -8,13 +8,11 @@
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarcomp.h"
|
||||
#include "colvargrid.h"
|
||||
#include "colvargrid_def.h"
|
||||
|
||||
@ -37,6 +35,58 @@ colvar_grid_count::colvar_grid_count(std::vector<colvar *> &colvars,
|
||||
: colvar_grid<size_t>(colvars, def_count, 1, margin)
|
||||
{}
|
||||
|
||||
std::string colvar_grid_count::get_state_params() const
|
||||
{
|
||||
return colvar_grid<size_t>::get_state_params();
|
||||
}
|
||||
|
||||
int colvar_grid_count::parse_params(std::string const &conf,
|
||||
colvarparse::Parse_Mode const parse_mode)
|
||||
{
|
||||
return colvar_grid<size_t>::parse_params(conf, parse_mode);
|
||||
}
|
||||
|
||||
std::istream & colvar_grid_count::read_restart(std::istream &is)
|
||||
{
|
||||
return colvar_grid<size_t>::read_restart(is);
|
||||
}
|
||||
|
||||
cvm::memory_stream & colvar_grid_count::read_restart(cvm::memory_stream &is)
|
||||
{
|
||||
return colvar_grid<size_t>::read_restart(is);
|
||||
}
|
||||
|
||||
std::ostream & colvar_grid_count::write_restart(std::ostream &os)
|
||||
{
|
||||
return colvar_grid<size_t>::write_restart(os);
|
||||
}
|
||||
|
||||
cvm::memory_stream & colvar_grid_count::write_restart(cvm::memory_stream &os)
|
||||
{
|
||||
return colvar_grid<size_t>::write_restart(os);
|
||||
}
|
||||
|
||||
std::istream &colvar_grid_count::read_raw(std::istream &is)
|
||||
{
|
||||
return colvar_grid<size_t>::read_raw(is);
|
||||
}
|
||||
|
||||
cvm::memory_stream &colvar_grid_count::read_raw(cvm::memory_stream &is)
|
||||
{
|
||||
return colvar_grid<size_t>::read_raw(is);
|
||||
}
|
||||
|
||||
std::ostream &colvar_grid_count::write_raw(std::ostream &os, size_t const buf_size) const
|
||||
{
|
||||
return colvar_grid<size_t>::write_raw(os, buf_size);
|
||||
}
|
||||
|
||||
cvm::memory_stream &colvar_grid_count::write_raw(cvm::memory_stream &os,
|
||||
size_t const buf_size) const
|
||||
{
|
||||
return colvar_grid<size_t>::write_raw(os, buf_size);
|
||||
}
|
||||
|
||||
std::istream & colvar_grid_count::read_multicol(std::istream &is, bool add)
|
||||
{
|
||||
return colvar_grid<size_t>::read_multicol(is, add);
|
||||
@ -96,6 +146,58 @@ colvar_grid_scalar::~colvar_grid_scalar()
|
||||
{
|
||||
}
|
||||
|
||||
std::string colvar_grid_scalar::get_state_params() const
|
||||
{
|
||||
return colvar_grid<cvm::real>::get_state_params();
|
||||
}
|
||||
|
||||
int colvar_grid_scalar::parse_params(std::string const &conf,
|
||||
colvarparse::Parse_Mode const parse_mode)
|
||||
{
|
||||
return colvar_grid<cvm::real>::parse_params(conf, parse_mode);
|
||||
}
|
||||
|
||||
std::istream &colvar_grid_scalar::read_restart(std::istream &is)
|
||||
{
|
||||
return colvar_grid<cvm::real>::read_restart(is);
|
||||
}
|
||||
|
||||
cvm::memory_stream &colvar_grid_scalar::read_restart(cvm::memory_stream &is)
|
||||
{
|
||||
return colvar_grid<cvm::real>::read_restart(is);
|
||||
}
|
||||
|
||||
std::ostream &colvar_grid_scalar::write_restart(std::ostream &os)
|
||||
{
|
||||
return colvar_grid<cvm::real>::write_restart(os);
|
||||
}
|
||||
|
||||
cvm::memory_stream &colvar_grid_scalar::write_restart(cvm::memory_stream &os)
|
||||
{
|
||||
return colvar_grid<cvm::real>::write_restart(os);
|
||||
}
|
||||
|
||||
std::istream &colvar_grid_scalar::read_raw(std::istream &is)
|
||||
{
|
||||
return colvar_grid<cvm::real>::read_raw(is);
|
||||
}
|
||||
|
||||
cvm::memory_stream &colvar_grid_scalar::read_raw(cvm::memory_stream &is)
|
||||
{
|
||||
return colvar_grid<cvm::real>::read_raw(is);
|
||||
}
|
||||
|
||||
std::ostream &colvar_grid_scalar::write_raw(std::ostream &os, size_t const buf_size) const
|
||||
{
|
||||
return colvar_grid<cvm::real>::write_raw(os, buf_size);
|
||||
}
|
||||
|
||||
cvm::memory_stream &colvar_grid_scalar::write_raw(cvm::memory_stream &os,
|
||||
size_t const buf_size) const
|
||||
{
|
||||
return colvar_grid<cvm::real>::write_raw(os, buf_size);
|
||||
}
|
||||
|
||||
std::istream & colvar_grid_scalar::read_multicol(std::istream &is, bool add)
|
||||
{
|
||||
return colvar_grid<cvm::real>::read_multicol(is, add);
|
||||
@ -195,30 +297,63 @@ cvm::real colvar_grid_scalar::entropy() const
|
||||
return bin_volume * sum;
|
||||
}
|
||||
|
||||
/// \brief Return the RMSD between this grid's data and another one
|
||||
/// Grids must have the same dimensions.
|
||||
cvm::real colvar_grid_scalar::grid_rmsd(colvar_grid_scalar const &other_grid) const
|
||||
{
|
||||
if (other_grid.data.size() != this->data.size()) {
|
||||
cvm::error("Error: trying to subtract two grids with "
|
||||
"different size.\n");
|
||||
return -1.;
|
||||
}
|
||||
|
||||
cvm::real sum2 = 0.0;
|
||||
|
||||
if (samples && other_grid.samples) {
|
||||
for (size_t i = 0; i < data.size(); i++) {
|
||||
size_t n = samples->get_value(i);
|
||||
cvm::real us = n ? data[i] / n : 0.0;
|
||||
n = other_grid.samples->get_value(i);
|
||||
cvm::real them = n ? other_grid.data[i ] / n : 0.0;
|
||||
cvm::real d = us - them;
|
||||
sum2 += d*d;
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < data.size(); i++) {
|
||||
cvm::real d = other_grid.data[i] - data[i];
|
||||
sum2 += d*d;
|
||||
}
|
||||
}
|
||||
|
||||
return sqrt(sum2/this->data.size());
|
||||
}
|
||||
|
||||
|
||||
colvar_grid_gradient::colvar_grid_gradient()
|
||||
: colvar_grid<cvm::real>(),
|
||||
samples(NULL),
|
||||
weights(NULL)
|
||||
: colvar_grid<cvm::real>(), samples(NULL), full_samples(0), min_samples(0)
|
||||
{}
|
||||
|
||||
|
||||
colvar_grid_gradient::colvar_grid_gradient(std::vector<int> const &nx_i)
|
||||
: colvar_grid<cvm::real>(nx_i, 0.0, nx_i.size()),
|
||||
samples(NULL),
|
||||
weights(NULL)
|
||||
: colvar_grid<cvm::real>(nx_i, 0.0, nx_i.size()), samples(NULL), full_samples(0), min_samples(0)
|
||||
{}
|
||||
|
||||
|
||||
colvar_grid_gradient::colvar_grid_gradient(std::vector<colvar *> &colvars)
|
||||
: colvar_grid<cvm::real>(colvars, 0.0, colvars.size()),
|
||||
samples(NULL),
|
||||
weights(NULL)
|
||||
: colvar_grid<cvm::real>(colvars, 0.0, colvars.size()), samples(NULL), full_samples(0), min_samples(0)
|
||||
{}
|
||||
|
||||
|
||||
colvar_grid_gradient::colvar_grid_gradient(std::vector<colvar *> &colvars, std::shared_ptr<colvar_grid_count> samples_in)
|
||||
: colvar_grid<cvm::real>(colvars, 0.0, colvars.size()), samples(samples_in), full_samples(0), min_samples(0)
|
||||
{
|
||||
samples_in->has_parent_data = true;
|
||||
}
|
||||
|
||||
|
||||
colvar_grid_gradient::colvar_grid_gradient(std::string &filename)
|
||||
: colvar_grid<cvm::real>(),
|
||||
samples(NULL),
|
||||
weights(NULL)
|
||||
samples(NULL)
|
||||
{
|
||||
std::istream &is = cvm::main()->proxy->input_stream(filename,
|
||||
"gradient file");
|
||||
@ -280,6 +415,57 @@ colvar_grid_gradient::colvar_grid_gradient(std::string &filename)
|
||||
cvm::main()->proxy->close_input_stream(filename);
|
||||
}
|
||||
|
||||
std::string colvar_grid_gradient::get_state_params() const
|
||||
{
|
||||
return colvar_grid<cvm::real>::get_state_params();
|
||||
}
|
||||
|
||||
int colvar_grid_gradient::parse_params(std::string const &conf,
|
||||
colvarparse::Parse_Mode const parse_mode)
|
||||
{
|
||||
return colvar_grid<cvm::real>::parse_params(conf, parse_mode);
|
||||
}
|
||||
|
||||
std::istream &colvar_grid_gradient::read_restart(std::istream &is)
|
||||
{
|
||||
return colvar_grid<cvm::real>::read_restart(is);
|
||||
}
|
||||
|
||||
cvm::memory_stream &colvar_grid_gradient::read_restart(cvm::memory_stream &is)
|
||||
{
|
||||
return colvar_grid<cvm::real>::read_restart(is);
|
||||
}
|
||||
|
||||
std::ostream &colvar_grid_gradient::write_restart(std::ostream &os)
|
||||
{
|
||||
return colvar_grid<cvm::real>::write_restart(os);
|
||||
}
|
||||
|
||||
cvm::memory_stream &colvar_grid_gradient::write_restart(cvm::memory_stream &os)
|
||||
{
|
||||
return colvar_grid<cvm::real>::write_restart(os);
|
||||
}
|
||||
|
||||
std::istream &colvar_grid_gradient::read_raw(std::istream &is)
|
||||
{
|
||||
return colvar_grid<cvm::real>::read_raw(is);
|
||||
}
|
||||
|
||||
cvm::memory_stream &colvar_grid_gradient::read_raw(cvm::memory_stream &is)
|
||||
{
|
||||
return colvar_grid<cvm::real>::read_raw(is);
|
||||
}
|
||||
|
||||
std::ostream &colvar_grid_gradient::write_raw(std::ostream &os, size_t const buf_size) const
|
||||
{
|
||||
return colvar_grid<cvm::real>::write_raw(os, buf_size);
|
||||
}
|
||||
|
||||
cvm::memory_stream &colvar_grid_gradient::write_raw(cvm::memory_stream &os,
|
||||
size_t const buf_size) const
|
||||
{
|
||||
return colvar_grid<cvm::real>::write_raw(os, buf_size);
|
||||
}
|
||||
|
||||
std::istream & colvar_grid_gradient::read_multicol(std::istream &is, bool add)
|
||||
{
|
||||
@ -371,9 +557,38 @@ void colvar_grid_gradient::write_1D_integral(std::ostream &os)
|
||||
}
|
||||
|
||||
|
||||
/// \brief Return the RMSD between this grid's data and another one
|
||||
/// Grids must have the same dimensions.
|
||||
cvm::real colvar_grid_gradient::grid_rmsd(colvar_grid_gradient const &other_grid) const
|
||||
{
|
||||
if (other_grid.multiplicity() != this->multiplicity()) {
|
||||
cvm::error("Error: trying to subtract two grids with "
|
||||
"different multiplicity.\n");
|
||||
return -1.;
|
||||
}
|
||||
|
||||
integrate_potential::integrate_potential(std::vector<colvar *> &colvars, colvar_grid_gradient * gradients)
|
||||
if (other_grid.data.size() != this->data.size()) {
|
||||
cvm::error("Error: trying to subtract two grids with "
|
||||
"different size.\n");
|
||||
return -1.;
|
||||
}
|
||||
|
||||
cvm::real sum2 = 0.0;
|
||||
std::vector<int> ix;
|
||||
size_t imult;
|
||||
for (ix = new_index(); index_ok(ix); incr(ix)) {
|
||||
for (imult = 0; imult < this->multiplicity(); imult++) {
|
||||
cvm::real d = this->value_output(ix, imult) - other_grid.value_output(ix, imult);
|
||||
sum2 += d*d;
|
||||
}
|
||||
}
|
||||
return sqrt(sum2/this->data.size());
|
||||
}
|
||||
|
||||
|
||||
integrate_potential::integrate_potential(std::vector<colvar *> &colvars, std::shared_ptr<colvar_grid_gradient> gradients)
|
||||
: colvar_grid_scalar(colvars, true),
|
||||
b_smoothed(false),
|
||||
gradients(gradients)
|
||||
{
|
||||
// parent class colvar_grid_scalar is constructed with margin option set to true
|
||||
@ -402,8 +617,9 @@ integrate_potential::integrate_potential(std::vector<colvar *> &colvars, colvar_
|
||||
}
|
||||
|
||||
|
||||
integrate_potential::integrate_potential(colvar_grid_gradient * gradients)
|
||||
: gradients(gradients)
|
||||
integrate_potential::integrate_potential(std::shared_ptr<colvar_grid_gradient> gradients)
|
||||
: b_smoothed(false),
|
||||
gradients(gradients)
|
||||
{
|
||||
nd = gradients->num_variables();
|
||||
nx = gradients->number_of_points_vec();
|
||||
@ -425,7 +641,7 @@ integrate_potential::integrate_potential(colvar_grid_gradient * gradients)
|
||||
}
|
||||
|
||||
|
||||
int integrate_potential::integrate(const int itmax, const cvm::real &tol, cvm::real & err)
|
||||
int integrate_potential::integrate(const int itmax, const cvm::real &tol, cvm::real & err, bool verbose)
|
||||
{
|
||||
int iter = 0;
|
||||
|
||||
@ -438,22 +654,24 @@ int integrate_potential::integrate(const int itmax, const cvm::real &tol, cvm::r
|
||||
} else {
|
||||
corr = 0.0;
|
||||
}
|
||||
|
||||
std::vector<int> ix;
|
||||
// Iterate over valid indices in gradient grid
|
||||
for (ix = new_index(); gradients->index_ok(ix); incr(ix)) {
|
||||
set_value(ix, sum);
|
||||
sum += (gradients->value_output(ix) - corr) * widths[0];
|
||||
cvm::real val = gradients->value_output_smoothed(ix, b_smoothed);
|
||||
sum += (val - corr) * widths[0];
|
||||
}
|
||||
if (index_ok(ix)) {
|
||||
// This will happen if non-periodic: then PMF grid has one extra bin wrt gradient grid
|
||||
// If not, sum should be zero
|
||||
set_value(ix, sum);
|
||||
}
|
||||
|
||||
} else if (nd <= 3) {
|
||||
|
||||
nr_linbcg_sym(divergence, data, tol, itmax, iter, err);
|
||||
cvm::log("Integrated in " + cvm::to_str(iter) + " steps, error: " + cvm::to_str(err) + "\n");
|
||||
if (verbose)
|
||||
cvm::log("Integrated in " + cvm::to_str(iter) + " steps, error: " + cvm::to_str(err));
|
||||
|
||||
} else {
|
||||
cvm::error("Cannot integrate PMF in dimension > 3\n");
|
||||
@ -477,7 +695,7 @@ void integrate_potential::update_div_neighbors(const std::vector<int> &ix0)
|
||||
std::vector<int> ix(ix0);
|
||||
int i, j, k;
|
||||
|
||||
// If not periodic, expanded grid ensures that neighbors of ix0 are valid grid points
|
||||
// If not periodic, expanded grid ensures that upper neighbors of ix0 are valid grid points
|
||||
if (nd == 1) {
|
||||
return;
|
||||
|
||||
@ -509,30 +727,23 @@ void integrate_potential::update_div_neighbors(const std::vector<int> &ix0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void integrate_potential::get_grad(cvm::real * g, std::vector<int> &ix)
|
||||
{
|
||||
size_t count, i;
|
||||
bool edge = gradients->wrap_edge(ix); // Detect edge if non-PBC
|
||||
size_t i;
|
||||
bool edge = gradients->wrap_detect_edge(ix); // Detect edge if non-PBC
|
||||
|
||||
if (gradients->samples) {
|
||||
count = gradients->samples->value(ix);
|
||||
} else {
|
||||
count = 1;
|
||||
}
|
||||
|
||||
if (!edge && count) {
|
||||
cvm::real const *grad = &(gradients->value(ix));
|
||||
cvm::real const fact = 1.0 / count;
|
||||
for ( i = 0; i<nd; i++ ) {
|
||||
g[i] = fact * grad[i];
|
||||
}
|
||||
} else {
|
||||
if (edge) {
|
||||
for ( i = 0; i<nd; i++ ) {
|
||||
g[i] = 0.0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
gradients->vector_value_smoothed(ix, g, b_smoothed);
|
||||
}
|
||||
|
||||
|
||||
void integrate_potential::update_div_local(const std::vector<int> &ix0)
|
||||
{
|
||||
const size_t linear_index = address(ix0);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,233 @@
|
||||
#include "colvarproxy.h"
|
||||
#include "colvar.h"
|
||||
#include "colvargrid.h"
|
||||
#include "colvars_memstream.h"
|
||||
|
||||
|
||||
template <class T, class IST> IST &read_restart_template_(colvar_grid<T> &g, IST &is)
|
||||
{
|
||||
auto const start_pos = is.tellg();
|
||||
std::string conf;
|
||||
if ((is >> colvarparse::read_block("grid_parameters", &conf)) &&
|
||||
(g.parse_params(conf, colvarparse::parse_restart) == COLVARS_OK) && g.read_raw(is)) {
|
||||
return is;
|
||||
}
|
||||
auto const error_pos = is.tellg();
|
||||
is.clear();
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
cvm::error("Error: in reading grid state from stream at position " + cvm::to_str(error_pos) +
|
||||
"\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
template <class T> std::istream &colvar_grid<T>::read_restart(std::istream &is)
|
||||
{
|
||||
return read_restart_template_<T, std::istream>(*this, is);
|
||||
}
|
||||
|
||||
|
||||
template <class T> cvm::memory_stream &colvar_grid<T>::read_restart(cvm::memory_stream &is)
|
||||
{
|
||||
return read_restart_template_<T, cvm::memory_stream>(*this, is);
|
||||
}
|
||||
|
||||
|
||||
template <class T> std::ostream &colvar_grid<T>::write_restart(std::ostream &os)
|
||||
{
|
||||
os << "grid_parameters {\n" << get_state_params() << "}\n";
|
||||
write_raw(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template <class T> cvm::memory_stream &colvar_grid<T>::write_restart(cvm::memory_stream &os)
|
||||
{
|
||||
os << std::string("grid_parameters") << get_state_params();
|
||||
write_raw(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template <class T, class IST> IST &read_raw_template_(colvar_grid<T> &g, IST &is)
|
||||
{
|
||||
auto const start_pos = is.tellg();
|
||||
|
||||
for (std::vector<int> ix = g.new_index(); g.index_ok(ix); g.incr(ix)) {
|
||||
for (size_t imult = 0; imult < g.mult; imult++) {
|
||||
T new_value;
|
||||
if (is >> new_value) {
|
||||
g.value_input(ix, new_value, imult);
|
||||
} else {
|
||||
is.clear();
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
cvm::error(
|
||||
"Error: failed to read all of the grid points from file. Possible explanations: grid "
|
||||
"parameters in the configuration (lowerBoundary, upperBoundary, width) are different "
|
||||
"from those in the file, or the file is corrupt/incomplete.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
return is;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g.has_data = true;
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
template <class T> std::istream &colvar_grid<T>::read_raw(std::istream &is)
|
||||
{
|
||||
return read_raw_template_<T, std::istream>(*this, is);
|
||||
}
|
||||
|
||||
|
||||
template <class T> cvm::memory_stream &colvar_grid<T>::read_raw(cvm::memory_stream &is)
|
||||
{
|
||||
return read_raw_template_<T, cvm::memory_stream>(*this, is);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
std::ostream &colvar_grid<T>::write_raw(std::ostream &os, size_t const buf_size) const
|
||||
{
|
||||
auto const w = os.width();
|
||||
auto const p = os.precision();
|
||||
|
||||
size_t count = 0;
|
||||
for (auto ix = new_index(); index_ok(ix); incr(ix)) {
|
||||
for (size_t imult = 0; imult < mult; imult++) {
|
||||
os << " " << std::setw(w) << std::setprecision(p) << value_output(ix, imult);
|
||||
if (((++count) % buf_size) == 0)
|
||||
os << "\n";
|
||||
}
|
||||
}
|
||||
// write a final newline only if buffer is not empty
|
||||
if ((count % buf_size) != 0)
|
||||
os << "\n";
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
cvm::memory_stream &colvar_grid<T>::write_raw(cvm::memory_stream &os, size_t const buf_size) const
|
||||
{
|
||||
for (auto ix = new_index(); index_ok(ix); incr(ix)) {
|
||||
for (size_t imult = 0; imult < mult; imult++) {
|
||||
os << value_output(ix, imult);
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template <class T> std::string colvar_grid<T>::get_state_params() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
size_t i;
|
||||
os << " n_colvars " << nd << "\n";
|
||||
|
||||
os << " lower_boundaries ";
|
||||
for (i = 0; i < nd; i++)
|
||||
os << " " << lower_boundaries[i];
|
||||
os << "\n";
|
||||
|
||||
os << " upper_boundaries ";
|
||||
for (i = 0; i < nd; i++)
|
||||
os << " " << upper_boundaries[i];
|
||||
os << "\n";
|
||||
|
||||
os << " widths ";
|
||||
for (i = 0; i < nd; i++)
|
||||
os << " " << widths[i];
|
||||
os << "\n";
|
||||
|
||||
os << " sizes ";
|
||||
for (i = 0; i < nd; i++)
|
||||
os << " " << nx[i];
|
||||
os << "\n";
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
template <class T> int colvar_grid<T>::parse_params(std::string const &conf,
|
||||
colvarparse::Parse_Mode const parse_mode)
|
||||
{
|
||||
if (cvm::debug())
|
||||
cvm::log("Reading grid configuration from string.\n");
|
||||
|
||||
std::vector<int> old_nx = nx;
|
||||
std::vector<colvarvalue> old_lb = lower_boundaries;
|
||||
std::vector<colvarvalue> old_ub = upper_boundaries;
|
||||
std::vector<cvm::real> old_w = widths;
|
||||
|
||||
{
|
||||
size_t nd_in = 0;
|
||||
// this is only used in state files
|
||||
colvarparse::get_keyval(conf, "n_colvars", nd_in, nd, colvarparse::parse_silent);
|
||||
if (nd_in != nd) {
|
||||
cvm::error("Error: trying to read data for a grid "
|
||||
"that contains a different number of colvars ("+
|
||||
cvm::to_str(nd_in)+") than the grid defined "
|
||||
"in the configuration file("+cvm::to_str(nd)+
|
||||
").\n");
|
||||
return COLVARS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// underscore keywords are used in state file
|
||||
colvarparse::get_keyval(conf, "lower_boundaries",
|
||||
lower_boundaries, lower_boundaries, colvarparse::parse_silent);
|
||||
colvarparse::get_keyval(conf, "upper_boundaries",
|
||||
upper_boundaries, upper_boundaries, colvarparse::parse_silent);
|
||||
|
||||
// camel case keywords are used in config file
|
||||
colvarparse::get_keyval(conf, "lowerBoundaries",
|
||||
lower_boundaries, lower_boundaries, parse_mode);
|
||||
colvarparse::get_keyval(conf, "upperBoundaries",
|
||||
upper_boundaries, upper_boundaries, parse_mode);
|
||||
|
||||
colvarparse::get_keyval(conf, "widths", widths, widths, parse_mode);
|
||||
|
||||
// only used in state file
|
||||
colvarparse::get_keyval(conf, "sizes", nx, nx, colvarparse::parse_silent);
|
||||
|
||||
if (nd < lower_boundaries.size()) nd = lower_boundaries.size();
|
||||
|
||||
if (! use_actual_value.size()) use_actual_value.assign(nd, false);
|
||||
if (! periodic.size()) periodic.assign(nd, false);
|
||||
if (! widths.size()) widths.assign(nd, 1.0);
|
||||
|
||||
cvm::real eps = 1.e-10;
|
||||
|
||||
bool new_params = false;
|
||||
if (old_nx.size()) {
|
||||
for (size_t i = 0; i < nd; i++) {
|
||||
if (old_nx[i] != nx[i] ||
|
||||
cvm::sqrt(cv[i]->dist2(old_lb[i], lower_boundaries[i])) > eps ||
|
||||
cvm::sqrt(cv[i]->dist2(old_ub[i], upper_boundaries[i])) > eps ||
|
||||
cvm::fabs(old_w[i] - widths[i]) > eps) {
|
||||
new_params = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
new_params = true;
|
||||
}
|
||||
|
||||
// reallocate the array in case the grid params have just changed
|
||||
if (new_params) {
|
||||
init_from_boundaries();
|
||||
// data.clear(); // no longer needed: setup calls clear()
|
||||
return this->setup(nx, T(), mult);
|
||||
}
|
||||
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
@ -90,6 +317,9 @@ std::istream & colvar_grid<T>::read_multicol(std::istream &is, bool add)
|
||||
for (size_t i = 0; i < nd; i++ ) {
|
||||
if ( !(is >> x) ) end_of_file = true;
|
||||
bin[i] = value_to_bin_scalar(x, i);
|
||||
// if x is out of bounds and we are using PBC, wrap it
|
||||
// Ignore out of bounds points in non-PBC
|
||||
wrap_detect_edge(bin);
|
||||
}
|
||||
if (end_of_file) break;
|
||||
|
||||
|
||||
@ -7,13 +7,10 @@
|
||||
// If you wish to distribute your changes, please submit them to the
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarparse.h"
|
||||
@ -21,6 +18,7 @@
|
||||
#include "colvar.h"
|
||||
#include "colvarbias.h"
|
||||
#include "colvarbias_abf.h"
|
||||
#include "colvarbias_abmd.h"
|
||||
#include "colvarbias_alb.h"
|
||||
#include "colvarbias_histogram.h"
|
||||
#include "colvarbias_histogram_reweight_amd.h"
|
||||
@ -29,7 +27,7 @@
|
||||
#include "colvarscript.h"
|
||||
#include "colvaratoms.h"
|
||||
#include "colvarcomp.h"
|
||||
|
||||
#include "colvars_memstream.h"
|
||||
|
||||
|
||||
/// Track usage of Colvars features
|
||||
@ -69,6 +67,11 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
namespace {
|
||||
constexpr uint32_t colvars_magic_number = 2013813594;
|
||||
}
|
||||
|
||||
|
||||
colvarmodule::colvarmodule(colvarproxy *proxy_in)
|
||||
{
|
||||
depth_s = 0;
|
||||
@ -98,16 +101,14 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in)
|
||||
version_int = proxy->get_version_from_string(COLVARS_VERSION);
|
||||
|
||||
cvm::log(cvm::line_marker);
|
||||
cvm::log("Initializing the collective variables module, version "+
|
||||
version()+".\n");
|
||||
cvm::log(
|
||||
"Initializing the collective variables module, version " + version() +
|
||||
(patch_version_number() ? (" (patch " + cvm::to_str(patch_version_number()) + ")") : "") +
|
||||
".\n");
|
||||
cvm::log("Please cite Fiorin et al, Mol Phys 2013:\n"
|
||||
" https://doi.org/10.1080/00268976.2013.813594\n"
|
||||
"as well as all other papers listed below for individual features used.\n");
|
||||
|
||||
if (proxy->smp_enabled() == COLVARS_OK) {
|
||||
cvm::log("SMP parallelism is enabled; if needed, use \"smp off\" to override this.\n");
|
||||
}
|
||||
|
||||
#if (__cplusplus >= 201103L)
|
||||
cvm::log("This version was built with the C++11 standard or higher.\n");
|
||||
#else
|
||||
@ -116,8 +117,38 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in)
|
||||
" https://colvars.github.io/README-c++11.html\n");
|
||||
#endif
|
||||
|
||||
cvm::log("Summary of compile-time features available in this build:\n");
|
||||
|
||||
if (proxy->check_smp_enabled() == COLVARS_NOT_IMPLEMENTED) {
|
||||
cvm::log(" - SMP parallelism: not available\n");
|
||||
} else {
|
||||
if (proxy->check_smp_enabled() == COLVARS_OK) {
|
||||
cvm::log(" - SMP parallelism: enabled (num. threads = " + to_str(proxy->smp_num_threads()) + ")\n");
|
||||
} else {
|
||||
cvm::log(" - SMP parallelism: available, but not enabled\n");
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(LEPTON)
|
||||
cvm::log(" - Lepton custom functions: available\n");
|
||||
#else
|
||||
cvm::log(" - Lepton custom functions: not available\n");
|
||||
#endif
|
||||
|
||||
#if defined(COLVARS_TCL)
|
||||
cvm::log(" - Tcl interpreter: available\n");
|
||||
#else
|
||||
cvm::log(" - Tcl interpreter: not available\n");
|
||||
#endif
|
||||
|
||||
// set initial default values
|
||||
|
||||
binary_restart = false;
|
||||
char const *env_var = getenv("COLVARS_BINARY_RESTART");
|
||||
if (env_var && atoi(env_var)) {
|
||||
binary_restart = true;
|
||||
}
|
||||
|
||||
// "it_restart" will be set by the input state file, if any;
|
||||
// "it" should be updated by the proxy
|
||||
colvarmodule::it = colvarmodule::it_restart = 0;
|
||||
@ -182,6 +213,13 @@ size_t colvarmodule::size() const
|
||||
}
|
||||
|
||||
|
||||
void colvarmodule::set_initial_step(step_number it_in)
|
||||
{
|
||||
cvm::log("Setting initial step number from MD engine: " + cvm::to_str(it_in) + "\n");
|
||||
it = it_restart = it_in;
|
||||
}
|
||||
|
||||
|
||||
int colvarmodule::read_config_file(char const *config_filename)
|
||||
{
|
||||
cvm::log(cvm::line_marker);
|
||||
@ -327,6 +365,7 @@ void colvarmodule::config_changed()
|
||||
|
||||
int colvarmodule::parse_global_params(std::string const &conf)
|
||||
{
|
||||
int error_code = COLVARS_OK;
|
||||
// TODO document and then echo this keyword
|
||||
parse->get_keyval(conf, "logLevel", log_level_, log_level_,
|
||||
colvarparse::parse_silent);
|
||||
@ -334,10 +373,7 @@ int colvarmodule::parse_global_params(std::string const &conf)
|
||||
std::string units;
|
||||
if (parse->get_keyval(conf, "units", units)) {
|
||||
units = colvarparse::to_lower_cppstr(units);
|
||||
int error_code = proxy->set_unit_system(units, (colvars.size() != 0));
|
||||
if (error_code != COLVARS_OK) {
|
||||
return error_code;
|
||||
}
|
||||
error_code |= proxy->set_unit_system(units, (colvars.size() != 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,7 +382,7 @@ int colvarmodule::parse_global_params(std::string const &conf)
|
||||
size_t pos = 0;
|
||||
while (parse->key_lookup(conf, "indexFile", &index_file_name, &pos)) {
|
||||
cvm::log("# indexFile = \""+index_file_name+"\"\n");
|
||||
read_index_file(index_file_name.c_str());
|
||||
error_code |= read_index_file(index_file_name.c_str());
|
||||
index_file_name.clear();
|
||||
}
|
||||
}
|
||||
@ -358,9 +394,8 @@ int colvarmodule::parse_global_params(std::string const &conf)
|
||||
}
|
||||
|
||||
bool b_analysis = true;
|
||||
if (parse->get_keyval(conf, "analysis", b_analysis, true,
|
||||
colvarparse::parse_silent)) {
|
||||
cvm::log("Warning: keyword \"analysis\" is deprecated: it is now set "
|
||||
if (parse->get_keyval(conf, "analysis", b_analysis, true, colvarparse::parse_silent)) {
|
||||
cvm::log("Warning: keyword \"analysis\" is deprecated: it is now always set "
|
||||
"to true; individual analyses are performed only if requested.");
|
||||
}
|
||||
|
||||
@ -391,7 +426,12 @@ int colvarmodule::parse_global_params(std::string const &conf)
|
||||
parse->get_keyval(conf, "sourceTclFile", source_Tcl_script);
|
||||
#endif
|
||||
|
||||
return cvm::get_error();
|
||||
if (proxy->engine_name() == "GROMACS" && proxy->version_number() >= 20231003) {
|
||||
parse->get_keyval(conf, "defaultInputStateFile", default_input_state_file_,
|
||||
default_input_state_file_);
|
||||
}
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
@ -522,6 +562,9 @@ int colvarmodule::parse_biases(std::string const &conf)
|
||||
/// initialize ABF instances
|
||||
parse_biases_type<colvarbias_abf>(conf, "abf");
|
||||
|
||||
/// initialize ABMD instances
|
||||
parse_biases_type<colvarbias_abmd>(conf, "abmd");
|
||||
|
||||
/// initialize adaptive linear biases
|
||||
parse_biases_type<colvarbias_alb>(conf, "ALB");
|
||||
|
||||
@ -791,29 +834,27 @@ int colvarmodule::calc()
|
||||
|
||||
// write restart files and similar data
|
||||
if (restart_out_freq && (cvm::step_relative() > 0) &&
|
||||
((cvm::step_absolute() % restart_out_freq) == 0) ) {
|
||||
((cvm::step_absolute() % restart_out_freq) == 0)) {
|
||||
|
||||
if (restart_out_name.size()) {
|
||||
// Write restart file, if different from main output
|
||||
error_code |= write_restart_file(restart_out_name);
|
||||
} else {
|
||||
error_code |= write_restart_file(output_prefix()+".colvars.state");
|
||||
} else if (output_prefix().size()) {
|
||||
error_code |= write_restart_file(output_prefix() + ".colvars.state");
|
||||
}
|
||||
|
||||
if (output_prefix().size()) {
|
||||
cvm::increase_depth();
|
||||
for (std::vector<colvar *>::iterator cvi = colvars.begin();
|
||||
cvi != colvars.end();
|
||||
cvi++) {
|
||||
for (std::vector<colvar *>::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) {
|
||||
// TODO remove this when corrFunc becomes a bias
|
||||
error_code |= (*cvi)->write_output_files();
|
||||
}
|
||||
for (std::vector<colvarbias *>::iterator bi = biases.begin();
|
||||
bi != biases.end();
|
||||
bi++) {
|
||||
for (std::vector<colvarbias *>::iterator bi = biases.begin(); bi != biases.end(); bi++) {
|
||||
error_code |= (*bi)->write_state_to_replicas();
|
||||
}
|
||||
cvm::decrease_depth();
|
||||
}
|
||||
}
|
||||
|
||||
// Write output files for biases, at the specified frequency for each
|
||||
cvm::increase_depth();
|
||||
@ -881,7 +922,7 @@ int colvarmodule::calc_colvars()
|
||||
}
|
||||
|
||||
// if SMP support is available, split up the work
|
||||
if (proxy->smp_enabled() == COLVARS_OK) {
|
||||
if (proxy->check_smp_enabled() == COLVARS_OK) {
|
||||
|
||||
// first, calculate how much work (currently, how many active CVCs) each colvar has
|
||||
|
||||
@ -963,8 +1004,16 @@ int colvarmodule::calc_biases()
|
||||
}
|
||||
}
|
||||
|
||||
// if SMP support is available, split up the work
|
||||
if (proxy->smp_enabled() == COLVARS_OK) {
|
||||
bool biases_need_main_thread = false;
|
||||
for (bi = biases_active()->begin(); bi != biases_active()->end(); bi++) {
|
||||
if ((*bi)->replica_share_freq() > 0) {
|
||||
// Biases that share data with replicas need read/write access to I/O or MPI
|
||||
biases_need_main_thread = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If SMP support is available, split up the work (unless biases need to use main thread's memory)
|
||||
if (proxy->check_smp_enabled() == COLVARS_OK && !biases_need_main_thread) {
|
||||
|
||||
if (use_scripted_forces && !scripting_after_biases) {
|
||||
// calculate biases and scripted forces in parallel
|
||||
@ -980,10 +1029,12 @@ int colvarmodule::calc_biases()
|
||||
error_code |= calc_scripted_forces();
|
||||
}
|
||||
|
||||
// Straight loop over biases on a single thread
|
||||
cvm::increase_depth();
|
||||
for (bi = biases_active()->begin(); bi != biases_active()->end(); bi++) {
|
||||
error_code |= (*bi)->update();
|
||||
if (cvm::get_error()) {
|
||||
cvm::decrease_depth();
|
||||
return error_code;
|
||||
}
|
||||
}
|
||||
@ -994,7 +1045,7 @@ int colvarmodule::calc_biases()
|
||||
total_bias_energy += (*bi)->get_energy();
|
||||
}
|
||||
|
||||
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
@ -1082,9 +1133,22 @@ int colvarmodule::write_restart_file(std::string const &out_name)
|
||||
cvm::log("Saving collective variables state to \""+out_name+"\".\n");
|
||||
std::ostream &restart_out_os = proxy->output_stream(out_name, "state file");
|
||||
if (!restart_out_os) return COLVARS_FILE_ERROR;
|
||||
if (!write_restart(restart_out_os)) {
|
||||
|
||||
if (binary_restart) {
|
||||
cvm::memory_stream mem_os;
|
||||
if (!write_state(mem_os)) {
|
||||
return cvm::error("Error: in writing binary state information to file.\n", COLVARS_ERROR);
|
||||
}
|
||||
if (!restart_out_os.write(reinterpret_cast<char *>(mem_os.output_buffer()),
|
||||
mem_os.length())) {
|
||||
return cvm::error("Error: in writing restart file.\n", COLVARS_FILE_ERROR);
|
||||
}
|
||||
} else {
|
||||
if (!write_state(restart_out_os)) {
|
||||
return cvm::error("Error: in writing restart file.\n", COLVARS_FILE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
proxy->close_output_stream(out_name);
|
||||
|
||||
// Take the opportunity to flush colvars.traj
|
||||
@ -1097,7 +1161,7 @@ int colvarmodule::write_restart_string(std::string &output)
|
||||
{
|
||||
cvm::log("Saving state to output buffer.\n");
|
||||
std::ostringstream os;
|
||||
if (!write_restart(os)) {
|
||||
if (!write_state(os)) {
|
||||
return cvm::error("Error: in writing restart to buffer.\n", COLVARS_FILE_ERROR);
|
||||
}
|
||||
output = os.str();
|
||||
@ -1207,9 +1271,17 @@ int colvarmodule::end_of_step()
|
||||
|
||||
int colvarmodule::update_engine_parameters()
|
||||
{
|
||||
if (this->size() == 0) return cvm::get_error();
|
||||
for (std::vector<colvar *>::iterator cvi = variables()->begin();
|
||||
cvi != variables()->end(); cvi++) {
|
||||
if (size() == 0) {
|
||||
// No-op if no variables or biases are defined
|
||||
return cvm::get_error();
|
||||
}
|
||||
if (proxy->simulation_running()) {
|
||||
cvm::log("Current simulation parameters: initial step = " + cvm::to_str(it) +
|
||||
", integration timestep = " + cvm::to_str(dt()) + "\n");
|
||||
}
|
||||
cvm::log("Updating atomic parameters (masses, charges, etc).\n");
|
||||
for (std::vector<colvar *>::iterator cvi = variables()->begin(); cvi != variables()->end();
|
||||
cvi++) {
|
||||
(*cvi)->setup();
|
||||
}
|
||||
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
|
||||
@ -1250,10 +1322,10 @@ int colvarmodule::reset()
|
||||
parse->clear();
|
||||
|
||||
// Iterate backwards because we are deleting the elements as we go
|
||||
for (std::vector<colvarbias *>::reverse_iterator bi = biases.rbegin();
|
||||
bi != biases.rend();
|
||||
bi++) {
|
||||
delete *bi; // the bias destructor updates the biases array
|
||||
while (!biases.empty()) {
|
||||
colvarbias* tail = biases.back();
|
||||
biases.pop_back();
|
||||
delete tail; // the bias destructor updates the biases array
|
||||
}
|
||||
biases.clear();
|
||||
biases_active_.clear();
|
||||
@ -1262,11 +1334,11 @@ int colvarmodule::reset()
|
||||
reinterpret_cast<std::map<std::string, int> *>(num_biases_types_used_)->clear();
|
||||
|
||||
// Iterate backwards because we are deleting the elements as we go
|
||||
for (std::vector<colvar *>::reverse_iterator cvi = colvars.rbegin();
|
||||
cvi != colvars.rend();
|
||||
cvi++) {
|
||||
delete *cvi; // the colvar destructor updates the colvars array
|
||||
}
|
||||
while (!colvars.empty()) {
|
||||
colvar* cvi = colvars.back();
|
||||
colvars.pop_back();
|
||||
delete cvi; // the colvar destructor updates the colvars array
|
||||
};
|
||||
colvars.clear();
|
||||
|
||||
reset_index_groups();
|
||||
@ -1274,64 +1346,119 @@ int colvarmodule::reset()
|
||||
proxy->flush_output_streams();
|
||||
proxy->reset();
|
||||
|
||||
return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
|
||||
clear_error();
|
||||
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
int colvarmodule::setup_input()
|
||||
{
|
||||
if (proxy->input_prefix().size()) {
|
||||
// Read a state file
|
||||
std::string restart_in_name(proxy->input_prefix()+
|
||||
std::string(".colvars.state"));
|
||||
std::istream *input_is = &(proxy->input_stream(restart_in_name,
|
||||
"restart file/channel",
|
||||
false));
|
||||
if (proxy->input_prefix().empty() && (!proxy->input_stream_exists("input state string")) &&
|
||||
input_state_buffer_.empty()) {
|
||||
// If no input sources have been defined up to this point, use defaultInputStateFile
|
||||
proxy->set_input_prefix(default_input_state_file_);
|
||||
}
|
||||
|
||||
if (!proxy->input_prefix().empty()) {
|
||||
|
||||
// Read state from a file
|
||||
|
||||
std::string restart_in_name(proxy->input_prefix() + std::string(".colvars.state"));
|
||||
std::istream *input_is = &(proxy->input_stream(restart_in_name, "restart file/channel", false));
|
||||
if (!*input_is) {
|
||||
// Try without the suffix ".colvars.state"
|
||||
restart_in_name = proxy->input_prefix();
|
||||
input_is = &(proxy->input_stream(restart_in_name,
|
||||
"restart file/channel"));
|
||||
input_is = &(proxy->input_stream(restart_in_name, "restart file/channel"));
|
||||
if (!*input_is) {
|
||||
// Error message has already been printed, return now
|
||||
return COLVARS_FILE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Now that the file has been opened, clear this field so that this
|
||||
// function will not be called twice
|
||||
proxy->input_prefix().clear();
|
||||
// Now that the file has been opened, clear this field so that this block
|
||||
// will not be executed twice
|
||||
proxy->set_input_prefix("");
|
||||
|
||||
cvm::log(cvm::line_marker);
|
||||
cvm::log("Loading state from file \""+restart_in_name+"\".\n");
|
||||
read_restart(*input_is);
|
||||
cvm::log(cvm::line_marker);
|
||||
|
||||
proxy->close_input_stream(restart_in_name);
|
||||
input_is->seekg(0, std::ios::end);
|
||||
size_t const file_size = input_is->tellg();
|
||||
input_is->seekg(0, std::ios::beg);
|
||||
|
||||
return cvm::get_error();
|
||||
bool binary_state_file = false;
|
||||
|
||||
uint32_t file_magic_number = 0;
|
||||
if (file_size > sizeof(uint32_t)) {
|
||||
if (input_is->read(reinterpret_cast<char *>(&file_magic_number), sizeof(uint32_t))) {
|
||||
if (file_magic_number == colvars_magic_number) {
|
||||
binary_state_file = true;
|
||||
}
|
||||
|
||||
// TODO This could soon be redundant
|
||||
if (proxy->input_buffer() != NULL) {
|
||||
// Read a string buffer
|
||||
char const *buffer = proxy->input_buffer();
|
||||
size_t const buffer_size = strlen(proxy->input_buffer());
|
||||
// Clear proxy pointer for the next round
|
||||
proxy->input_buffer() = NULL;
|
||||
if (buffer_size > 0) {
|
||||
std::istringstream input_is;
|
||||
// Replace the buffer of input_is; work around the lack of const in
|
||||
// pubsetbuf's prototype (which also needs to support output streams)
|
||||
input_is.rdbuf()->pubsetbuf(const_cast<char *>(buffer), buffer_size);
|
||||
cvm::log(cvm::line_marker);
|
||||
cvm::log("Loading state from input buffer.\n");
|
||||
read_restart(input_is);
|
||||
cvm::log(cvm::line_marker);
|
||||
return cvm::get_error();
|
||||
input_is->seekg(0, std::ios::beg);
|
||||
}
|
||||
}
|
||||
|
||||
return COLVARS_OK;
|
||||
if (binary_state_file) {
|
||||
cvm::log("Loading state from binary file \"" + restart_in_name + "\".\n");
|
||||
// TODO integrate istream.read() into memory_stream to avoid copying
|
||||
auto *buf = new unsigned char[file_size];
|
||||
if (input_is->read(reinterpret_cast<char *>(buf), file_size)) {
|
||||
cvm::memory_stream mem_is(file_size, buf);
|
||||
if (!read_state(mem_is)) {
|
||||
input_is->setstate(std::ios::failbit);
|
||||
cvm::error("Error: cannot interpret contents of binary file \"" + restart_in_name +
|
||||
"\".\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
} else {
|
||||
cvm::error("Error: cannot read from binary file \"" + restart_in_name + "\".\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
delete[] buf;
|
||||
} else {
|
||||
cvm::log("Loading state from text file \"" + restart_in_name + "\".\n");
|
||||
read_state(*input_is);
|
||||
}
|
||||
cvm::log(cvm::line_marker);
|
||||
|
||||
// Now that an explicit state file was read, we shall ignore any other restart info
|
||||
if (proxy->input_stream_exists("input state string")) {
|
||||
proxy->delete_input_stream("input state string");
|
||||
}
|
||||
input_state_buffer_.clear();
|
||||
|
||||
proxy->delete_input_stream(restart_in_name);
|
||||
}
|
||||
|
||||
if (proxy->input_stream_exists("input state string")) {
|
||||
|
||||
if (!input_state_buffer_.empty()) {
|
||||
return cvm::error("Error: formatted/text and unformatted/binary input state buffers are "
|
||||
"defined at the same time.\n",
|
||||
COLVARS_BUG_ERROR);
|
||||
}
|
||||
|
||||
cvm::log(cvm::line_marker);
|
||||
cvm::log("Loading state from formatted string.\n");
|
||||
read_state(proxy->input_stream("input state string"));
|
||||
cvm::log(cvm::line_marker);
|
||||
|
||||
proxy->delete_input_stream("input state string");
|
||||
}
|
||||
|
||||
if (!input_state_buffer_.empty()) {
|
||||
cvm::log(cvm::line_marker);
|
||||
cvm::log("Loading state from unformatted memory.\n");
|
||||
cvm::memory_stream ms(input_state_buffer_.size(), input_state_buffer_.data());
|
||||
read_state(ms);
|
||||
cvm::log(cvm::line_marker);
|
||||
|
||||
input_state_buffer_.clear();
|
||||
}
|
||||
|
||||
default_input_state_file_.clear();
|
||||
|
||||
return get_error();
|
||||
}
|
||||
|
||||
|
||||
@ -1344,36 +1471,39 @@ int colvarmodule::setup_output()
|
||||
std::string(proxy->restart_output_prefix()+".colvars.state") :
|
||||
std::string("");
|
||||
|
||||
std::string const state_file_format(binary_restart ? " (binary format)" : "");
|
||||
|
||||
if (restart_out_name.size()) {
|
||||
cvm::log("The restart output state file will be \""+
|
||||
cvm::log("The restart output state file" + state_file_format + " will be \""+
|
||||
restart_out_name+"\".\n");
|
||||
}
|
||||
|
||||
if (output_prefix() != proxy->output_prefix()) {
|
||||
output_prefix() = proxy->output_prefix();
|
||||
if (output_prefix().size()) {
|
||||
cvm::log("The final output state file will be \""+
|
||||
(output_prefix().size() ?
|
||||
std::string(output_prefix()+".colvars.state") :
|
||||
std::string("colvars.state"))+"\".\n");
|
||||
// cvm::log (cvm::line_marker);
|
||||
cvm::log("The final output state file will be \"" +
|
||||
(output_prefix().size() ? std::string(output_prefix() + ".colvars.state")
|
||||
: std::string("colvars.state")) +
|
||||
"\".\n");
|
||||
}
|
||||
|
||||
if (proxy->output_stream_exists(cv_traj_name)) {
|
||||
// Close old file
|
||||
proxy->close_output_stream(cv_traj_name);
|
||||
cv_traj_write_labels = true;
|
||||
}
|
||||
|
||||
cv_traj_name =
|
||||
(output_prefix().size() ?
|
||||
std::string(output_prefix()+".colvars.traj") :
|
||||
std::string(""));
|
||||
(output_prefix().size() ? std::string(output_prefix() + ".colvars.traj") : std::string(""));
|
||||
|
||||
for (std::vector<colvarbias *>::iterator bi = biases.begin();
|
||||
bi != biases.end();
|
||||
bi++) {
|
||||
error_code |= (*bi)->setup_output();
|
||||
}
|
||||
|
||||
if (error_code != COLVARS_OK || cvm::get_error()) {
|
||||
set_error_bits(COLVARS_FILE_ERROR);
|
||||
}
|
||||
|
||||
return cvm::get_error();
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
||||
@ -1390,8 +1520,7 @@ std::string colvarmodule::state_file_prefix(char const *filename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::istream & colvarmodule::read_restart(std::istream &is)
|
||||
template <typename IST> IST & colvarmodule::read_state_template_(IST &is)
|
||||
{
|
||||
bool warn_total_forces = false;
|
||||
|
||||
@ -1417,8 +1546,11 @@ std::istream & colvarmodule::read_restart(std::istream &is)
|
||||
}
|
||||
|
||||
if (restart_version() != version()) {
|
||||
cvm::log("This state file was generated with version "+
|
||||
restart_version()+"\n");
|
||||
cvm::log("This state file was generated with version " + restart_version() + "\n");
|
||||
if (std::is_same<IST, cvm::memory_stream>::value) {
|
||||
cvm::log("Warning: compatibility between differetn Colvars versions is not "
|
||||
"guaranteed for unformatted (binary) state files.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (restart_version_number() < 20160810) {
|
||||
@ -1453,35 +1585,73 @@ std::istream & colvarmodule::read_restart(std::istream &is)
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarmodule::read_state(std::istream &is)
|
||||
{
|
||||
return read_state_template_<std::istream>(is);
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream &colvarmodule::read_state(cvm::memory_stream &is)
|
||||
{
|
||||
uint32_t file_magic_number = 0;
|
||||
if (!(is >> file_magic_number)) {
|
||||
return is;
|
||||
}
|
||||
if (file_magic_number == colvars_magic_number) {
|
||||
return read_state_template_<cvm::memory_stream>(is);
|
||||
} else {
|
||||
is.setstate(std::ios::failbit);
|
||||
cvm::error("Error: magic number of binary file (" +
|
||||
cvm::to_str(static_cast<size_t>(file_magic_number)) +
|
||||
") does not match the expected magic number for a Colvars state file (" +
|
||||
cvm::to_str(static_cast<size_t>(colvars_magic_number)) + ").\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
int colvarmodule::set_input_state_buffer(size_t n, unsigned char *buf)
|
||||
{
|
||||
input_state_buffer_.clear();
|
||||
std::copy(buf, buf + n, std::back_inserter(input_state_buffer_));
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
int colvarmodule::set_input_state_buffer(std::vector<unsigned char> &buf)
|
||||
{
|
||||
input_state_buffer_ = std::move(buf);
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
std::istream & colvarmodule::read_objects_state(std::istream &is)
|
||||
{
|
||||
std::streampos pos = 0;
|
||||
auto pos = is.tellg();
|
||||
std::string word;
|
||||
|
||||
while (is.good()) {
|
||||
while (is) {
|
||||
pos = is.tellg();
|
||||
word.clear();
|
||||
is >> word;
|
||||
|
||||
if (word.size()) {
|
||||
if (is >> word) {
|
||||
|
||||
is.seekg(pos, std::ios::beg);
|
||||
is.seekg(pos);
|
||||
|
||||
if (word == "colvar") {
|
||||
|
||||
cvm::increase_depth();
|
||||
for (std::vector<colvar *>::iterator cvi = colvars.begin();
|
||||
cvi != colvars.end();
|
||||
cvi++) {
|
||||
if ( !((*cvi)->read_state(is)) ) {
|
||||
for (std::vector<colvar *>::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) {
|
||||
if (!((*cvi)->read_state(is))) {
|
||||
// Here an error signals that the variable is a match, but the
|
||||
// state is corrupt; otherwise, the variable rewinds is silently
|
||||
cvm::error("Error: in reading restart configuration for "
|
||||
"collective variable \""+(*cvi)->name+"\".\n",
|
||||
cvm::error("Error: in reading state for collective variable \"" +
|
||||
(*cvi)->name + "\" at position " + cvm::to_str(is.tellg()) +
|
||||
" in stream.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
if (is.tellg() > pos) break; // found it
|
||||
if (is.tellg() > pos)
|
||||
break; // found it
|
||||
}
|
||||
cvm::decrease_depth();
|
||||
|
||||
@ -1498,11 +1668,12 @@ std::istream & colvarmodule::read_objects_state(std::istream &is)
|
||||
}
|
||||
if (!((*bi)->read_state(is))) {
|
||||
// Same as above, an error means a match but the state is incorrect
|
||||
cvm::error("Error: in reading restart configuration for bias \""+
|
||||
(*bi)->name+"\".\n",
|
||||
cvm::error("Error: in reading state for bias \"" + (*bi)->name + "\" at position " +
|
||||
cvm::to_str(is.tellg()) + " in stream.\n",
|
||||
COLVARS_INPUT_ERROR);
|
||||
}
|
||||
if (is.tellg() > pos) break; // found it
|
||||
if (is.tellg() > pos)
|
||||
break; // found it
|
||||
}
|
||||
cvm::decrease_depth();
|
||||
}
|
||||
@ -1521,6 +1692,25 @@ std::istream & colvarmodule::read_objects_state(std::istream &is)
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream &colvarmodule::read_objects_state(cvm::memory_stream &is)
|
||||
{
|
||||
// An unformatted stream must match the objects' exact configuration
|
||||
cvm::increase_depth();
|
||||
for (std::vector<colvar *>::iterator cvi = colvars.begin(); cvi != colvars.end(); cvi++) {
|
||||
if (!(*cvi)->read_state(is)) {
|
||||
return is;
|
||||
}
|
||||
}
|
||||
for (std::vector<colvarbias *>::iterator bi = biases.begin(); bi != biases.end(); bi++) {
|
||||
if (!(*bi)->read_state(is)) {
|
||||
return is;
|
||||
}
|
||||
}
|
||||
cvm::decrease_depth();
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
int colvarmodule::print_total_forces_errning(bool warn_total_forces)
|
||||
{
|
||||
if (warn_total_forces) {
|
||||
@ -1643,18 +1833,24 @@ int colvarmodule::read_traj(char const *traj_filename,
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarmodule::write_restart(std::ostream &os)
|
||||
template <typename OST> OST &colvarmodule::write_state_template_(OST &os)
|
||||
{
|
||||
os.setf(std::ios::scientific, std::ios::floatfield);
|
||||
os << "configuration {\n"
|
||||
<< " step " << std::setw(it_width)
|
||||
bool const formatted = !std::is_same<OST, cvm::memory_stream>::value;
|
||||
|
||||
std::ostringstream oss;
|
||||
oss.setf(std::ios::scientific, std::ios::floatfield);
|
||||
oss << " step " << std::setw(it_width)
|
||||
<< it << "\n"
|
||||
<< " dt " << dt() << "\n"
|
||||
<< " version " << std::string(COLVARS_VERSION) << "\n";
|
||||
if (proxy->units.size() > 0) {
|
||||
os << " units " << proxy->units << "\n";
|
||||
oss << " units " << proxy->units << "\n";
|
||||
}
|
||||
os << "}\n\n";
|
||||
|
||||
os << std::string("configuration");
|
||||
if (formatted) os << " {\n";
|
||||
os << oss.str();
|
||||
if (formatted) os << "}\n\n";
|
||||
|
||||
int error_code = COLVARS_OK;
|
||||
|
||||
@ -1681,7 +1877,32 @@ std::ostream & colvarmodule::write_restart(std::ostream &os)
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarmodule::write_traj_label(std::ostream &os)
|
||||
std::ostream &colvarmodule::write_state(std::ostream &os)
|
||||
{
|
||||
return write_state_template_<std::ostream>(os);
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream &colvarmodule::write_state(cvm::memory_stream &os)
|
||||
{
|
||||
if (os << colvars_magic_number) {
|
||||
write_state_template_<cvm::memory_stream>(os);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
int colvarmodule::write_state_buffer(std::vector<unsigned char> &buffer)
|
||||
{
|
||||
cvm::memory_stream os(buffer);
|
||||
if (os << colvars_magic_number) {
|
||||
write_state_template_<cvm::memory_stream>(os);
|
||||
}
|
||||
return os ? COLVARS_OK : COLVARS_ERROR;
|
||||
}
|
||||
|
||||
|
||||
std::ostream &colvarmodule::write_traj_label(std::ostream &os)
|
||||
{
|
||||
os.setf(std::ios::scientific, std::ios::floatfield);
|
||||
|
||||
@ -1765,7 +1986,7 @@ size_t & colvarmodule::depth()
|
||||
{
|
||||
// NOTE: do not call log() or error() here, to avoid recursion
|
||||
colvarmodule *cv = cvm::main();
|
||||
if (proxy->smp_enabled() == COLVARS_OK) {
|
||||
if (proxy->check_smp_enabled() == COLVARS_OK) {
|
||||
int const nt = proxy->smp_num_threads();
|
||||
if (int(cv->depth_v.size()) != nt) {
|
||||
proxy->smp_lock();
|
||||
@ -1810,7 +2031,7 @@ void colvarmodule::clear_error()
|
||||
|
||||
int colvarmodule::error(std::string const &message, int code)
|
||||
{
|
||||
set_error_bits(code);
|
||||
set_error_bits(code >= 0 ? code : COLVARS_ERROR);
|
||||
|
||||
std::string const trailing_newline = (message.size() > 0) ?
|
||||
(message[message.size()-1] == '\n' ? "" : "\n") : "";
|
||||
@ -1930,15 +2151,6 @@ int colvarmodule::reset_index_groups()
|
||||
}
|
||||
|
||||
|
||||
int cvm::load_atoms(char const *file_name,
|
||||
cvm::atom_group &atoms,
|
||||
std::string const &pdb_field,
|
||||
double pdb_field_value)
|
||||
{
|
||||
return proxy->load_atoms(file_name, atoms, pdb_field, pdb_field_value);
|
||||
}
|
||||
|
||||
|
||||
int cvm::load_coords(char const *file_name,
|
||||
std::vector<cvm::rvector> *pos,
|
||||
cvm::atom_group *atoms,
|
||||
@ -1953,7 +2165,7 @@ int cvm::load_coords(char const *file_name,
|
||||
|
||||
atoms->create_sorted_ids();
|
||||
|
||||
std::vector<cvm::rvector> sorted_pos(atoms->size(), cvm::rvector(0.0));
|
||||
std::vector<cvm::atom_pos> sorted_pos(atoms->size(), cvm::rvector(0.0));
|
||||
|
||||
// Differentiate between PDB and XYZ files
|
||||
if (colvarparse::to_lower_cppstr(ext) == std::string(".xyz")) {
|
||||
@ -1965,11 +2177,12 @@ int cvm::load_coords(char const *file_name,
|
||||
error_code |= cvm::main()->load_coords_xyz(file_name, &sorted_pos, atoms);
|
||||
} else {
|
||||
// Otherwise, call proxy function for PDB
|
||||
error_code |= proxy->load_coords(file_name,
|
||||
sorted_pos, atoms->sorted_ids(),
|
||||
pdb_field, pdb_field_value);
|
||||
error_code |= proxy->load_coords_pdb(file_name, sorted_pos, atoms->sorted_ids(), pdb_field,
|
||||
pdb_field_value);
|
||||
}
|
||||
|
||||
if (error_code != COLVARS_OK) return error_code;
|
||||
|
||||
std::vector<int> const &map = atoms->sorted_ids_map();
|
||||
for (size_t i = 0; i < atoms->size(); i++) {
|
||||
(*pos)[map[i]] = sorted_pos[i];
|
||||
@ -1985,7 +2198,7 @@ int cvm::load_coords_xyz(char const *filename,
|
||||
bool keep_open)
|
||||
{
|
||||
std::istream &xyz_is = proxy->input_stream(filename, "XYZ file");
|
||||
unsigned int natoms;
|
||||
size_t natoms;
|
||||
char symbol[256];
|
||||
std::string line;
|
||||
cvm::real x = 0.0, y = 0.0, z = 0.0;
|
||||
@ -2009,12 +2222,19 @@ int cvm::load_coords_xyz(char const *filename,
|
||||
cvm::getline(xyz_is, line);
|
||||
xyz_is.width(255);
|
||||
} else {
|
||||
proxy->close_input_stream(filename);
|
||||
return cvm::error(error_msg, COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
if (pos->size() > natoms) {
|
||||
proxy->close_input_stream(filename);
|
||||
return cvm::error("File \"" + std::string(filename) + "\" contains fewer atoms (" + cvm::to_str(natoms)
|
||||
+ ") than expected (" + cvm::to_str(pos->size()) + ").", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
std::vector<atom_pos>::iterator pos_i = pos->begin();
|
||||
size_t xyz_natoms = 0;
|
||||
if (pos->size() != natoms) { // Use specified indices
|
||||
if (pos->size() < natoms) { // Use specified indices
|
||||
int next = 0; // indices are zero-based
|
||||
if (!atoms) {
|
||||
// In the other branch of this test, reading all positions from the file,
|
||||
@ -2022,6 +2242,13 @@ int cvm::load_coords_xyz(char const *filename,
|
||||
return cvm::error("Trying to read partial positions with invalid atom group pointer",
|
||||
COLVARS_BUG_ERROR);
|
||||
}
|
||||
|
||||
if (static_cast<unsigned int>(atoms->sorted_ids().back()) > natoms) {
|
||||
proxy->close_input_stream(filename);
|
||||
return cvm::error("File \"" + std::string(filename) + "\" contains fewer atoms (" + cvm::to_str(natoms)
|
||||
+ ") than expected (" + cvm::to_str(atoms->sorted_ids().back()) + ").", COLVARS_INPUT_ERROR);
|
||||
}
|
||||
|
||||
std::vector<int>::const_iterator index = atoms->sorted_ids().begin();
|
||||
|
||||
for ( ; pos_i != pos->end() ; pos_i++, index++) {
|
||||
@ -2038,6 +2265,7 @@ int cvm::load_coords_xyz(char const *filename,
|
||||
(*pos_i)[2] = proxy->angstrom_to_internal(z);
|
||||
xyz_natoms++;
|
||||
} else {
|
||||
proxy->close_input_stream(filename);
|
||||
return cvm::error(error_msg, COLVARS_INPUT_ERROR);
|
||||
}
|
||||
}
|
||||
@ -2053,12 +2281,14 @@ int cvm::load_coords_xyz(char const *filename,
|
||||
(*pos_i)[2] = proxy->angstrom_to_internal(z);
|
||||
xyz_natoms++;
|
||||
} else {
|
||||
proxy->close_input_stream(filename);
|
||||
return cvm::error(error_msg, COLVARS_INPUT_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xyz_natoms != pos->size()) {
|
||||
proxy->close_input_stream(filename);
|
||||
return cvm::error("Error: The number of positions read from file \""+
|
||||
std::string(filename)+"\" does not match the number of "+
|
||||
"positions required: "+cvm::to_str(xyz_natoms)+" vs. "+
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#ifndef COLVARMODULE_H
|
||||
#define COLVARMODULE_H
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
#include "colvars_version.h"
|
||||
|
||||
@ -19,9 +19,11 @@
|
||||
#endif
|
||||
|
||||
/*! \mainpage Main page
|
||||
This is the Developer's documentation for the Collective Variables Module.
|
||||
This is the Developer's documentation for the Collective Variables module (Colvars).
|
||||
|
||||
You can browse the class hierarchy or the list of source files.
|
||||
|
||||
Please note that this documentation is only supported for the master branch, and its features may differ from those in a given release of a simulation package.
|
||||
*/
|
||||
|
||||
/// \file colvarmodule.h
|
||||
@ -33,26 +35,15 @@ You can browse the class hierarchy or the list of source files.
|
||||
/// shared between all object instances) to be accessed from other
|
||||
/// objects.
|
||||
|
||||
#define COLVARS_OK 0
|
||||
#define COLVARS_ERROR 1
|
||||
#define COLVARS_NOT_IMPLEMENTED (1<<1)
|
||||
#define COLVARS_INPUT_ERROR (1<<2) // out of bounds or inconsistent input
|
||||
#define COLVARS_BUG_ERROR (1<<3) // Inconsistent state indicating bug
|
||||
#define COLVARS_FILE_ERROR (1<<4)
|
||||
#define COLVARS_MEMORY_ERROR (1<<5)
|
||||
#define COLVARS_NO_SUCH_FRAME (1<<6) // Cannot load the requested frame
|
||||
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <iosfwd>
|
||||
|
||||
class colvarparse;
|
||||
class colvar;
|
||||
class colvarbias;
|
||||
class colvarproxy;
|
||||
class colvarscript;
|
||||
class colvarvalue;
|
||||
|
||||
|
||||
@ -67,14 +58,6 @@ class colvarvalue;
|
||||
/// child objects
|
||||
class colvarmodule {
|
||||
|
||||
private:
|
||||
|
||||
/// Impossible to initialize the main object without arguments
|
||||
colvarmodule();
|
||||
|
||||
/// Integer representing the version string (allows comparisons)
|
||||
int version_int;
|
||||
|
||||
public:
|
||||
|
||||
/// Get the version string (YYYY-MM-DD format)
|
||||
@ -89,9 +72,21 @@ public:
|
||||
return version_int;
|
||||
}
|
||||
|
||||
friend class colvarproxy;
|
||||
// TODO colvarscript should be unaware of colvarmodule's internals
|
||||
friend class colvarscript;
|
||||
/// Get the patch version number (non-zero in patch releases of other packages)
|
||||
int patch_version_number() const
|
||||
{
|
||||
return patch_version_int;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Integer representing the version string (allows comparisons)
|
||||
int version_int = 0;
|
||||
|
||||
/// Patch version number (non-zero in patch releases of other packages)
|
||||
int patch_version_int = 0;
|
||||
|
||||
public:
|
||||
|
||||
/// Use a 64-bit integer to store the step number
|
||||
typedef long long step_number;
|
||||
@ -190,7 +185,9 @@ public:
|
||||
template <class T> class matrix2d;
|
||||
class quaternion;
|
||||
class rotation;
|
||||
|
||||
class usage;
|
||||
class memory_stream;
|
||||
|
||||
/// Residue identifier
|
||||
typedef int residue_id;
|
||||
@ -205,8 +202,6 @@ public:
|
||||
// allow these classes to access protected data
|
||||
class atom;
|
||||
class atom_group;
|
||||
friend class atom;
|
||||
friend class atom_group;
|
||||
typedef std::vector<atom>::iterator atom_iter;
|
||||
typedef std::vector<atom>::const_iterator atom_const_iter;
|
||||
|
||||
@ -247,6 +242,8 @@ public:
|
||||
return it;
|
||||
}
|
||||
|
||||
bool binary_restart;
|
||||
|
||||
/// \brief Finite difference step size (if there is no dynamics, or
|
||||
/// if gradients need to be tested independently from the size of
|
||||
/// dt)
|
||||
@ -342,9 +339,19 @@ public:
|
||||
/// \param Pointer to instance of the proxy class (communicate with engine)
|
||||
colvarmodule(colvarproxy *proxy);
|
||||
|
||||
private:
|
||||
|
||||
/// Cannot initialize the main object without a proxy
|
||||
colvarmodule();
|
||||
|
||||
public:
|
||||
|
||||
/// Destructor
|
||||
~colvarmodule();
|
||||
|
||||
/// Set the initial step number (it is 0 otherwise); may be overridden when reading a state
|
||||
void set_initial_step(step_number it);
|
||||
|
||||
/// Actual function called by the destructor
|
||||
int reset();
|
||||
|
||||
@ -449,17 +456,52 @@ public:
|
||||
/// (Re)initialize the output trajectory and state file (does not write it yet)
|
||||
int setup_output();
|
||||
|
||||
/// Read a restart file
|
||||
std::istream & read_restart(std::istream &is);
|
||||
private:
|
||||
|
||||
template <typename IST> IST & read_state_template_(IST &is);
|
||||
|
||||
/// Default input state file; if given, it is read unless the MD engine provides it
|
||||
std::string default_input_state_file_;
|
||||
|
||||
/// Internal state buffer, to be read as an unformatted stream
|
||||
std::vector<unsigned char> input_state_buffer_;
|
||||
|
||||
public:
|
||||
|
||||
/// Read all objects' state fron a formatted (text) stream
|
||||
std::istream & read_state(std::istream &is);
|
||||
|
||||
/// Read all objects' state fron an unformatted (binary) stream
|
||||
memory_stream & read_state(memory_stream &is);
|
||||
|
||||
/// Set an internal state buffer, to be read later as an unformatted stream when ready
|
||||
int set_input_state_buffer(size_t n, unsigned char *buf);
|
||||
|
||||
/// Same as set_input_state_buffer() for C array, but uses std::move
|
||||
int set_input_state_buffer(std::vector<unsigned char> &buf);
|
||||
|
||||
/// Read the states of individual objects; allows for changes
|
||||
std::istream & read_objects_state(std::istream &is);
|
||||
|
||||
/// Read the states of individual objects; allows for changes
|
||||
memory_stream & read_objects_state(memory_stream &is);
|
||||
|
||||
/// If needed (old restart file), print the warning that cannot be ignored
|
||||
int print_total_forces_errning(bool warn_total_forces);
|
||||
|
||||
/// Write the output restart file
|
||||
std::ostream & write_restart(std::ostream &os);
|
||||
private:
|
||||
template <typename OST> OST &write_state_template_(OST &os);
|
||||
|
||||
public:
|
||||
|
||||
/// Write the state of the module to a formatted (text) file
|
||||
std::ostream & write_state(std::ostream &os);
|
||||
|
||||
/// Write the state of the module to an unformatted (binary) file
|
||||
memory_stream & write_state(memory_stream &os);
|
||||
|
||||
/// Write the state of the module to an array of bytes (wrapped as a memory_stream object)
|
||||
int write_state_buffer(std::vector<unsigned char> &buffer);
|
||||
|
||||
/// Strips .colvars.state from filename and checks that it is not empty
|
||||
static std::string state_file_prefix(char const *filename);
|
||||
@ -650,7 +692,7 @@ public:
|
||||
static void log(std::string const &message, int min_log_level = 10);
|
||||
|
||||
/// Print a message to the main log and set global error code
|
||||
static int error(std::string const &message, int code = COLVARS_ERROR);
|
||||
static int error(std::string const &message, int code = -1);
|
||||
|
||||
private:
|
||||
|
||||
@ -715,17 +757,6 @@ public:
|
||||
/// Clear the index groups loaded so far
|
||||
int reset_index_groups();
|
||||
|
||||
/// \brief Select atom IDs from a file (usually PDB) \param filename name of
|
||||
/// the file \param atoms array into which atoms read from "filename" will be
|
||||
/// appended \param pdb_field (optional) if the file is a PDB and this
|
||||
/// string is non-empty, select atoms for which this field is non-zero
|
||||
/// \param pdb_field_value (optional) if non-zero, select only atoms whose
|
||||
/// pdb_field equals this
|
||||
static int load_atoms(char const *filename,
|
||||
atom_group &atoms,
|
||||
std::string const &pdb_field,
|
||||
double pdb_field_value = 0.0);
|
||||
|
||||
/// \brief Load coordinates for a group of atoms from a file (PDB or XYZ);
|
||||
/// if "pos" is already allocated, the number of its elements must match the
|
||||
/// number of entries in "filename" \param filename name of the file \param
|
||||
@ -755,7 +786,7 @@ public:
|
||||
std::string restart_out_name;
|
||||
|
||||
/// Pseudo-random number with Gaussian distribution
|
||||
static real rand_gaussian(void);
|
||||
static real rand_gaussian();
|
||||
|
||||
protected:
|
||||
|
||||
@ -838,9 +869,20 @@ public:
|
||||
typedef colvarmodule cvm;
|
||||
|
||||
|
||||
|
||||
std::ostream & operator << (std::ostream &os, cvm::rvector const &v);
|
||||
std::istream & operator >> (std::istream &is, cvm::rvector &v);
|
||||
|
||||
|
||||
namespace {
|
||||
constexpr int32_t COLVARS_OK = 0;
|
||||
constexpr int32_t COLVARS_ERROR = 1;
|
||||
constexpr int32_t COLVARS_NOT_IMPLEMENTED = (1<<1);
|
||||
constexpr int32_t COLVARS_INPUT_ERROR = (1<<2); // out of bounds or inconsistent input
|
||||
constexpr int32_t COLVARS_BUG_ERROR = (1<<3); // Inconsistent state indicating bug
|
||||
constexpr int32_t COLVARS_FILE_ERROR = (1<<4);
|
||||
constexpr int32_t COLVARS_MEMORY_ERROR = (1<<5);
|
||||
constexpr int32_t COLVARS_NO_SUCH_FRAME = (1<<6); // Cannot load the requested frame
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -14,6 +14,22 @@
|
||||
" url = {https://doi.org/10.1016/j.softx.2015.06.001}\n"
|
||||
"}\n";
|
||||
|
||||
paper_count_[std::string("BouRabee2010")] = 0;
|
||||
paper_url_[std::string("BouRabee2010")] = "https://doi.org/10.1137/090758842";
|
||||
paper_bibtex_[std::string("BouRabee2010")] =
|
||||
"\n"
|
||||
"@article{BouRabee2010,\n"
|
||||
" doi = {10.1137/090758842},\n"
|
||||
" url = {https://doi.org/10.1137/090758842},\n"
|
||||
" year = {2010},\n"
|
||||
" volume = {48},\n"
|
||||
" number = {1},\n"
|
||||
" pages = {278--297},\n"
|
||||
" author = {Nawaf Bou-Rabee and Houman Owhadi},\n"
|
||||
" title = {Long-Run Accuracy of Variational Integrators in the Stochastic Context},\n"
|
||||
" journal = {{SIAM} Journal on Numerical Analysis}\n"
|
||||
"}\n";
|
||||
|
||||
paper_count_[std::string("Chen2021")] = 0;
|
||||
paper_url_[std::string("Chen2021")] = "https://doi.org/10.1021/acs.jctc.1c00103";
|
||||
paper_bibtex_[std::string("Chen2021")] =
|
||||
@ -182,6 +198,19 @@
|
||||
" url = {https://doi.org/10.1021/ct9004432}\n"
|
||||
"}\n";
|
||||
|
||||
paper_count_[std::string("Henin2021")] = 0;
|
||||
paper_url_[std::string("Henin2021")] = "https://doi.org/10.1021/acs.jctc.1c00593";
|
||||
paper_bibtex_[std::string("Henin2021")] =
|
||||
"\n"
|
||||
"@Article{Henin2021,\n"
|
||||
" author = {H\\'enin, J.},\n"
|
||||
" journal = {J. Chem. Theory Comput.},\n"
|
||||
" title = {Fast and accurate multidimensional free energy integration},\n"
|
||||
" year = {2021},\n"
|
||||
" doi = {10.1021/acs.jctc.1c00593},\n"
|
||||
" url = {https://doi.org/10.1021/acs.jctc.1c00593},\n"
|
||||
"}\n";
|
||||
|
||||
paper_count_[std::string("Humphrey1996")] = 0;
|
||||
paper_url_[std::string("Humphrey1996")] = "https://doi.org/10.1016/0263-7855(96)00018-5";
|
||||
paper_bibtex_[std::string("Humphrey1996")] =
|
||||
@ -215,19 +244,6 @@
|
||||
" url = {https://doi.org/10.1021/acs.jpcb.6b10055}\n"
|
||||
"}\n";
|
||||
|
||||
paper_count_[std::string("Henin2021")] = 0;
|
||||
paper_url_[std::string("Henin2021")] = "https://doi.org/10.1021/acs.jctc.1c00593";
|
||||
paper_bibtex_[std::string("Henin2021")] =
|
||||
"\n"
|
||||
"@Article{Henin2021,\n"
|
||||
" author = {H\\'enin, J.},\n"
|
||||
" journal = {J. Chem. Theory Comput.},\n"
|
||||
" title = {Fast and accurate multidimensional free energy integration},\n"
|
||||
" year = {2021},\n"
|
||||
" doi = {10.1021/acs.jctc.1c00593},\n"
|
||||
" url = {https://doi.org/10.1021/acs.jctc.1c00593},\n"
|
||||
"}\n";
|
||||
|
||||
paper_count_[std::string("Marinelli2015")] = 0;
|
||||
paper_url_[std::string("Marinelli2015")] = "https://doi.org/10.1016/j.bpj.2015.05.024";
|
||||
paper_bibtex_[std::string("Marinelli2015")] =
|
||||
@ -335,6 +351,9 @@
|
||||
feature_count_[std::string("GROMACS engine")] = 0;
|
||||
feature_paper_map_[std::string("GROMACS engine")] = "Abraham2015";
|
||||
|
||||
feature_count_[std::string("BAOA integrator")] = 0;
|
||||
feature_paper_map_[std::string("BAOA integrator")] = "BouRabee2010";
|
||||
|
||||
feature_count_[std::string("reweightaMD colvar bias implementation (NAMD)")] = 0;
|
||||
feature_paper_map_[std::string("reweightaMD colvar bias implementation (NAMD)")] = "Chen2021";
|
||||
|
||||
@ -422,14 +441,14 @@
|
||||
feature_count_[std::string("orientationAngle colvar component (derived from orientation)")] = 0;
|
||||
feature_paper_map_[std::string("orientationAngle colvar component (derived from orientation)")] = "Fiorin2013";
|
||||
|
||||
feature_count_[std::string("orientationProj colvar component (derived from orientation)")] = 0;
|
||||
feature_paper_map_[std::string("orientationProj colvar component (derived from orientation)")] = "Fiorin2013";
|
||||
feature_count_[std::string("orientationProj colvar component (derived from orientationAngle)")] = 0;
|
||||
feature_paper_map_[std::string("orientationProj colvar component (derived from orientationAngle)")] = "Fiorin2013";
|
||||
|
||||
feature_count_[std::string("spinAngle colvar component (derived from orientation)")] = 0;
|
||||
feature_paper_map_[std::string("spinAngle colvar component (derived from orientation)")] = "Fiorin2013";
|
||||
feature_count_[std::string("spinAngle colvar component (derived from tilt)")] = 0;
|
||||
feature_paper_map_[std::string("spinAngle colvar component (derived from tilt)")] = "Fiorin2013";
|
||||
|
||||
feature_count_[std::string("tilt colvar component (derived from orientation)")] = 0;
|
||||
feature_paper_map_[std::string("tilt colvar component (derived from orientation)")] = "Fiorin2013";
|
||||
feature_count_[std::string("tilt colvar component (derived from orientationProj)")] = 0;
|
||||
feature_paper_map_[std::string("tilt colvar component (derived from orientationProj)")] = "Fiorin2013";
|
||||
|
||||
feature_count_[std::string("alpha colvar component")] = 0;
|
||||
feature_paper_map_[std::string("alpha colvar component")] = "Fiorin2013";
|
||||
@ -479,14 +498,14 @@
|
||||
feature_count_[std::string("polarPhi colvar component")] = 0;
|
||||
feature_paper_map_[std::string("polarPhi colvar component")] = "Fu2017";
|
||||
|
||||
feature_count_[std::string("eulerPhi colvar component (derived from orientation)")] = 0;
|
||||
feature_paper_map_[std::string("eulerPhi colvar component (derived from orientation)")] = "Fu2017";
|
||||
feature_count_[std::string("eulerPhi colvar component (derived from orientation_angle)")] = 0;
|
||||
feature_paper_map_[std::string("eulerPhi colvar component (derived from orientation_angle)")] = "Fu2017";
|
||||
|
||||
feature_count_[std::string("eulerTheta colvar component (derived from orientation)")] = 0;
|
||||
feature_paper_map_[std::string("eulerTheta colvar component (derived from orientation)")] = "Fu2017";
|
||||
feature_count_[std::string("eulerTheta colvar component (derived from orientation_angle)")] = 0;
|
||||
feature_paper_map_[std::string("eulerTheta colvar component (derived from orientation_angle)")] = "Fu2017";
|
||||
|
||||
feature_count_[std::string("eulerPsi colvar component (derived from orientation)")] = 0;
|
||||
feature_paper_map_[std::string("eulerPsi colvar component (derived from orientation)")] = "Fu2017";
|
||||
feature_count_[std::string("eulerPsi colvar component (derived from orientation_angle)")] = 0;
|
||||
feature_paper_map_[std::string("eulerPsi colvar component (derived from orientation_angle)")] = "Fu2017";
|
||||
|
||||
feature_count_[std::string("dipoleAngle colvar component")] = 0;
|
||||
feature_paper_map_[std::string("dipoleAngle colvar component")] = "Garate2019";
|
||||
@ -500,6 +519,9 @@
|
||||
feature_count_[std::string("Internal-forces free energy estimator")] = 0;
|
||||
feature_paper_map_[std::string("Internal-forces free energy estimator")] = "Henin2010";
|
||||
|
||||
feature_count_[std::string("Poisson integration of 2D/3D free energy surfaces")] = 0;
|
||||
feature_paper_map_[std::string("Poisson integration of 2D/3D free energy surfaces")] = "Henin2021";
|
||||
|
||||
feature_count_[std::string("VMD engine")] = 0;
|
||||
feature_paper_map_[std::string("VMD engine")] = "Humphrey1996";
|
||||
|
||||
@ -509,9 +531,6 @@
|
||||
feature_count_[std::string("CZAR eABF estimator")] = 0;
|
||||
feature_paper_map_[std::string("CZAR eABF estimator")] = "Lesage2017";
|
||||
|
||||
feature_count_[std::string("Poisson integration of 2D/3D free energy surfaces")] = 0;
|
||||
feature_paper_map_[std::string("Poisson integration of 2D/3D free energy surfaces")] = "Henin2021";
|
||||
|
||||
feature_count_[std::string("Ensemble-biased metadynamics (ebMetaD)")] = 0;
|
||||
feature_paper_map_[std::string("Ensemble-biased metadynamics (ebMetaD)")] = "Marinelli2015";
|
||||
|
||||
@ -539,9 +558,6 @@
|
||||
feature_count_[std::string("Colvars-GROMACS interface")] = 0;
|
||||
feature_paper_map_[std::string("Colvars-GROMACS interface")] = "n/a";
|
||||
|
||||
feature_count_[std::string("Colvars Dashboard (Colvars-VMD graphical user interface)")] = 0;
|
||||
feature_paper_map_[std::string("Colvars Dashboard (Colvars-VMD graphical user interface)")] = "n/a";
|
||||
|
||||
feature_count_[std::string("gspath colvar component")] = 0;
|
||||
feature_paper_map_[std::string("gspath colvar component")] = "n/a";
|
||||
|
||||
@ -571,3 +587,6 @@
|
||||
|
||||
feature_count_[std::string("Scripted functions (Tcl)")] = 0;
|
||||
feature_paper_map_[std::string("Scripted functions (Tcl)")] = "n/a";
|
||||
|
||||
feature_count_[std::string("ABMD bias")] = 0;
|
||||
feature_paper_map_[std::string("ABMD bias")] = "n/a";
|
||||
|
||||
@ -8,12 +8,12 @@
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvars_memstream.h"
|
||||
|
||||
|
||||
// space & tab
|
||||
@ -100,7 +100,7 @@ bool colvarparse::get_key_string_multi_value(std::string const &conf,
|
||||
char const *key, std::vector<std::string>& data)
|
||||
{
|
||||
bool b_found = false, b_found_any = false;
|
||||
size_t save_pos = 0, found_count = 0;
|
||||
size_t save_pos = 0;
|
||||
|
||||
data.clear();
|
||||
|
||||
@ -110,7 +110,6 @@ bool colvarparse::get_key_string_multi_value(std::string const &conf,
|
||||
if (b_found) {
|
||||
if (!b_found_any)
|
||||
b_found_any = true;
|
||||
found_count++;
|
||||
data.push_back(data_this);
|
||||
}
|
||||
} while (b_found);
|
||||
@ -786,14 +785,12 @@ bool colvarparse::key_lookup(std::string const &conf,
|
||||
if (line[brace] == '{') brace_count++;
|
||||
if (line[brace] == '}') brace_count--;
|
||||
if (brace_count == 0) {
|
||||
data_end = brace+1;
|
||||
break;
|
||||
}
|
||||
brace = line.find_first_of("{}", brace+1);
|
||||
}
|
||||
|
||||
if (brace_count == 0) {
|
||||
data_end = brace+1;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -869,55 +866,107 @@ colvarparse::read_block::~read_block()
|
||||
|
||||
std::istream & operator>> (std::istream &is, colvarparse::read_block const &rb)
|
||||
{
|
||||
std::streampos start_pos = is.tellg();
|
||||
std::string read_key, next;
|
||||
auto start_pos = is.tellg();
|
||||
|
||||
if ( !(is >> read_key) || !(read_key == rb.key) ||
|
||||
!(is >> next) ) {
|
||||
// the requested keyword has not been found, or it is not possible
|
||||
// to read data after it
|
||||
std::string read_key;
|
||||
if ( !(is >> read_key) || !(read_key == rb.key) ) {
|
||||
// the requested keyword has not been found
|
||||
is.clear();
|
||||
is.seekg(start_pos, std::ios::beg);
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
return is;
|
||||
}
|
||||
|
||||
if (next != "{") {
|
||||
std::string next;
|
||||
if (is >> next) {
|
||||
if (next == "{") {
|
||||
// Parse a formatted brace-delimited block
|
||||
rb.read_block_contents(is);
|
||||
} else {
|
||||
if (rb.data) {
|
||||
*(rb.data) = next;
|
||||
}
|
||||
return is;
|
||||
}
|
||||
} else {
|
||||
is.clear();
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::badbit);
|
||||
}
|
||||
|
||||
size_t brace_count = 1;
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
std::istream &colvarparse::read_block::read_block_contents(std::istream &is,
|
||||
bool block_only) const
|
||||
{
|
||||
int brace_count = block_only ? 0 : 1;
|
||||
auto const start_pos = is.tellg();
|
||||
std::string line;
|
||||
while (colvarparse::getline_nocomments(is, line)) {
|
||||
size_t br = 0, br_old = 0;
|
||||
while ( (br = line.find_first_of("{}", br)) != std::string::npos) {
|
||||
if (line[br] == '{') brace_count++;
|
||||
if (line[br] == '}') brace_count--;
|
||||
while ((br = line.find_first_of("{}", br)) != std::string::npos) {
|
||||
if (line[br] == '{')
|
||||
brace_count++;
|
||||
if (line[br] == '}')
|
||||
brace_count--;
|
||||
br_old = br;
|
||||
br++;
|
||||
}
|
||||
if (brace_count) {
|
||||
if (rb.data) {
|
||||
(rb.data)->append(line + "\n");
|
||||
if (brace_count || block_only) {
|
||||
// Add whole line if (1) brace are unmatched or (2) we're reading the whole stream anyway
|
||||
if (data) {
|
||||
data->append(line + "\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (rb.data) {
|
||||
(rb.data)->append(line, 0, br_old);
|
||||
} else {
|
||||
// Not reading whole block and braces are matched; add until before the last brace
|
||||
if (data) {
|
||||
data->append(line.substr(0, br_old) + "\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (brace_count) {
|
||||
// end-of-file reached
|
||||
// restore initial position
|
||||
|
||||
if (block_only) {
|
||||
if (is.rdstate() & std::ios::eofbit) {
|
||||
// Clear EOF errors if we were meant to read the whole block
|
||||
is.clear();
|
||||
is.seekg(start_pos, std::ios::beg);
|
||||
}
|
||||
} else {
|
||||
if (brace_count) {
|
||||
// Could not match braces, restore initial position and set fail bit
|
||||
is.clear();
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
}
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream &operator>>(cvm::memory_stream &is, colvarparse::read_block const &rb)
|
||||
{
|
||||
auto const start_pos = is.tellg();
|
||||
|
||||
std::string read_key;
|
||||
if ( !(is >> read_key) || !(read_key == rb.key) ) {
|
||||
// the requested keyword has not been found
|
||||
is.clear();
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
return is;
|
||||
}
|
||||
|
||||
std::string content;
|
||||
if (is >> content) {
|
||||
std::istringstream iss(content);
|
||||
if (!rb.read_block_contents(iss, true)) {
|
||||
is.seekg(start_pos);
|
||||
is.setstate(std::ios::failbit);
|
||||
}
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#define COLVARPARSE_H
|
||||
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
@ -40,7 +41,7 @@ public:
|
||||
void set_string(std::string const &conf);
|
||||
|
||||
/// Default destructor
|
||||
virtual ~colvarparse();
|
||||
~colvarparse() override;
|
||||
|
||||
/// Get the configuration string (includes comments)
|
||||
inline std::string const & get_config() const
|
||||
@ -109,12 +110,12 @@ public:
|
||||
bool get_keyval(std::string const &conf,
|
||||
char const *key,
|
||||
int &value,
|
||||
int const &def_value = (int)0,
|
||||
int const &def_value = 0,
|
||||
Parse_Mode const parse_mode = parse_normal);
|
||||
bool get_keyval(std::string const &conf,
|
||||
char const *key,
|
||||
size_t &value,
|
||||
size_t const &def_value = (size_t)0,
|
||||
size_t const &def_value = 0,
|
||||
Parse_Mode const parse_mode = parse_normal);
|
||||
bool get_keyval(std::string const &conf,
|
||||
char const *key,
|
||||
@ -134,7 +135,7 @@ public:
|
||||
bool get_keyval(std::string const &conf,
|
||||
char const *key,
|
||||
cvm::real &value,
|
||||
cvm::real const &def_value = (cvm::real)0.0,
|
||||
cvm::real const &def_value = 0.0,
|
||||
Parse_Mode const parse_mode = parse_normal);
|
||||
bool get_keyval(std::string const &conf,
|
||||
char const *key,
|
||||
@ -159,17 +160,17 @@ public:
|
||||
bool get_keyval(std::string const &conf,
|
||||
char const *key,
|
||||
std::vector<int> &values,
|
||||
std::vector<int> const &def_values = std::vector<int>(0, (int)0),
|
||||
std::vector<int> const &def_values = std::vector<int>(0, 0),
|
||||
Parse_Mode const parse_mode = parse_normal);
|
||||
bool get_keyval(std::string const &conf,
|
||||
char const *key,
|
||||
std::vector<size_t> &values,
|
||||
std::vector<size_t> const &def_values = std::vector<size_t>(0, (size_t)0),
|
||||
std::vector<size_t> const &def_values = std::vector<size_t>(0, 0),
|
||||
Parse_Mode const parse_mode = parse_normal);
|
||||
bool get_keyval(std::string const &conf,
|
||||
char const *key,
|
||||
std::vector<long> &values,
|
||||
std::vector<long> const &def_values = std::vector<long>(0, (long)0),
|
||||
std::vector<long> const &def_values = std::vector<long>(0, 0),
|
||||
Parse_Mode const parse_mode = parse_normal);
|
||||
bool get_keyval(std::string const &conf,
|
||||
char const *key,
|
||||
@ -179,7 +180,7 @@ public:
|
||||
bool get_keyval(std::string const &conf,
|
||||
char const *key,
|
||||
std::vector<cvm::real> &values,
|
||||
std::vector<cvm::real> const &def_values = std::vector<cvm::real>(0, (cvm::real)0.0),
|
||||
std::vector<cvm::real> const &def_values = std::vector<cvm::real>(0, 0.0),
|
||||
Parse_Mode const parse_mode = parse_normal);
|
||||
bool get_keyval(std::string const &conf,
|
||||
char const *key,
|
||||
@ -262,33 +263,41 @@ public:
|
||||
{
|
||||
std::string out = "";
|
||||
for (size_t i = 0; i < in.size(); i++) {
|
||||
out.append(1, (char) ::tolower(in[i]) );
|
||||
out.append(1, static_cast<char>( ::tolower(in[i])) );
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// \brief Helper class to read a block of the type "key { ... }"
|
||||
/// from a stream and store it in a string
|
||||
/// Helper class to read a block "key { ... }" from a stream and store it in a string
|
||||
///
|
||||
/// Useful on restarts, where the file is too big to be loaded in a
|
||||
/// string by key_lookup; it can only check that the keyword is
|
||||
/// correct and the block is properly delimited by braces, not
|
||||
/// skipping other blocks
|
||||
/// Useful on restarts, where the file is too big to be loaded in a string
|
||||
/// by key_lookup(); it can only check that the keyword is correct and the
|
||||
/// block is properly delimited by braces, not skipping other blocks
|
||||
class read_block {
|
||||
|
||||
/// The keyword that identifies the block
|
||||
std::string const key;
|
||||
|
||||
/// Where to keep the data (may be NULL)
|
||||
std::string * const data;
|
||||
|
||||
public:
|
||||
|
||||
read_block(std::string const &key_in, std::string *data_in = NULL);
|
||||
read_block(std::string const &key, std::string *data = nullptr);
|
||||
|
||||
~read_block();
|
||||
|
||||
/// Read block from stream, first check that key matches, then call read_contents()
|
||||
friend std::istream & operator >> (std::istream &is, read_block const &rb);
|
||||
|
||||
/// Read block from stream, first check that key matches, then call read_contents()
|
||||
friend cvm::memory_stream & operator >> (cvm::memory_stream &is, read_block const &rb);
|
||||
|
||||
private:
|
||||
|
||||
/// Keyword that identifies the block
|
||||
std::string const key;
|
||||
|
||||
/// Where to keep the data
|
||||
std::string * const data;
|
||||
|
||||
/// Read the contents of a formatted block after checking that the keyword matches
|
||||
/// \param[in] is Stream object
|
||||
/// \param[in] block_only If true, stream is assumed to contain only the block without braces
|
||||
std::istream & read_block_contents(std::istream &is, bool block_only = false) const;
|
||||
};
|
||||
|
||||
|
||||
@ -304,8 +313,8 @@ public:
|
||||
/// within "conf", useful when doing multiple calls
|
||||
bool key_lookup(std::string const &conf,
|
||||
char const *key,
|
||||
std::string *data = NULL,
|
||||
size_t *save_pos = NULL);
|
||||
std::string *data = nullptr,
|
||||
size_t *save_pos = nullptr);
|
||||
|
||||
/// \brief Reads a configuration line, adds it to config_string, and returns
|
||||
/// the stream \param is Input stream \param line String that will hold the
|
||||
|
||||
@ -13,8 +13,9 @@
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarproxy.h"
|
||||
#include "colvar.h"
|
||||
#include "colvarbias.h"
|
||||
#include "colvarscript.h"
|
||||
#include "colvaratoms.h"
|
||||
#include "colvarmodule_utils.h"
|
||||
|
||||
|
||||
@ -23,6 +24,7 @@ colvarproxy_atoms::colvarproxy_atoms()
|
||||
{
|
||||
atoms_rms_applied_force_ = atoms_max_applied_force_ = 0.0;
|
||||
atoms_max_applied_force_id_ = -1;
|
||||
modified_atom_list_ = false;
|
||||
updated_masses_ = updated_charges_ = false;
|
||||
}
|
||||
|
||||
@ -55,6 +57,7 @@ int colvarproxy_atoms::add_atom_slot(int atom_id)
|
||||
atoms_positions.push_back(cvm::rvector(0.0, 0.0, 0.0));
|
||||
atoms_total_forces.push_back(cvm::rvector(0.0, 0.0, 0.0));
|
||||
atoms_new_colvar_forces.push_back(cvm::rvector(0.0, 0.0, 0.0));
|
||||
modified_atom_list_ = true;
|
||||
return (atoms_ids.size() - 1);
|
||||
}
|
||||
|
||||
@ -71,6 +74,12 @@ int colvarproxy_atoms::check_atom_id(int /* atom_number */)
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_atoms::check_atom_name_selections_available()
|
||||
{
|
||||
return COLVARS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_atoms::init_atom(cvm::residue_id const & /* residue */,
|
||||
std::string const & /* atom_name */,
|
||||
std::string const & /* segment_id */)
|
||||
@ -112,29 +121,6 @@ size_t colvarproxy_atoms::get_num_active_atoms() const
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_atoms::load_atoms(char const * /* filename */,
|
||||
cvm::atom_group & /* atoms */,
|
||||
std::string const & /* pdb_field */,
|
||||
double)
|
||||
{
|
||||
return cvm::error("Error: loading atom identifiers from a file "
|
||||
"is currently not implemented.\n",
|
||||
COLVARS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_atoms::load_coords(char const * /* filename */,
|
||||
std::vector<cvm::atom_pos> & /* pos */,
|
||||
std::vector<int> const & /* sorted_ids */,
|
||||
std::string const & /* pdb_field */,
|
||||
double)
|
||||
{
|
||||
return cvm::error("Error: loading atomic coordinates from a file "
|
||||
"is currently not implemented.\n",
|
||||
COLVARS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
void colvarproxy_atoms::compute_rms_atoms_applied_force()
|
||||
{
|
||||
atoms_rms_applied_force_ =
|
||||
@ -280,7 +266,7 @@ colvarproxy_smp::~colvarproxy_smp()
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_smp::smp_enabled()
|
||||
int colvarproxy_smp::check_smp_enabled()
|
||||
{
|
||||
#if defined(_OPENMP)
|
||||
if (b_smp_active) {
|
||||
@ -299,7 +285,7 @@ int colvarproxy_smp::smp_colvars_loop()
|
||||
colvarmodule *cv = cvm::main();
|
||||
colvarproxy *proxy = cv->proxy;
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < cv->variables_active_smp()->size(); i++) {
|
||||
for (int i = 0; i < static_cast<int>(cv->variables_active_smp()->size()); i++) {
|
||||
colvar *x = (*(cv->variables_active_smp()))[i];
|
||||
int x_item = (*(cv->variables_active_smp_items()))[i];
|
||||
if (cvm::debug()) {
|
||||
@ -324,7 +310,7 @@ int colvarproxy_smp::smp_biases_loop()
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp for
|
||||
for (size_t i = 0; i < cv->biases_active()->size(); i++) {
|
||||
for (int i = 0; i < static_cast<int>(cv->biases_active()->size()); i++) {
|
||||
colvarbias *b = (*(cv->biases_active()))[i];
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Calculating bias \""+b->name+"\" on thread "+
|
||||
@ -351,7 +337,7 @@ int colvarproxy_smp::smp_biases_script_loop()
|
||||
cv->calc_scripted_forces();
|
||||
}
|
||||
#pragma omp for
|
||||
for (size_t i = 0; i < cv->biases_active()->size(); i++) {
|
||||
for (int i = 0; i < static_cast<int>(cv->biases_active()->size()); i++) {
|
||||
colvarbias *b = (*(cv->biases_active()))[i];
|
||||
if (cvm::debug()) {
|
||||
cvm::log("Calculating bias \""+b->name+"\" on thread "+
|
||||
@ -484,16 +470,21 @@ colvarproxy::~colvarproxy()
|
||||
|
||||
bool colvarproxy::io_available()
|
||||
{
|
||||
return (smp_enabled() == COLVARS_OK && smp_thread_id() == 0) ||
|
||||
(smp_enabled() != COLVARS_OK);
|
||||
return (check_smp_enabled() == COLVARS_OK && smp_thread_id() == 0) ||
|
||||
(check_smp_enabled() != COLVARS_OK);
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy::reset()
|
||||
{
|
||||
if (cvm::debug()) {
|
||||
cvm::log("colvarproxy::reset()\n");
|
||||
}
|
||||
int error_code = COLVARS_OK;
|
||||
error_code |= colvarproxy_atoms::reset();
|
||||
error_code |= colvarproxy_atom_groups::reset();
|
||||
error_code |= colvarproxy_volmaps::reset();
|
||||
total_force_requested = false;
|
||||
return error_code;
|
||||
}
|
||||
|
||||
@ -541,6 +532,31 @@ int colvarproxy::parse_module_config()
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy::load_atoms_pdb(char const * /* filename */,
|
||||
cvm::atom_group & /* atoms */,
|
||||
std::string const & /* pdb_field */,
|
||||
double /* pdb_field_value */)
|
||||
{
|
||||
return cvm::error(
|
||||
"Error: loading atom indices from a PDB file is currently not implemented in " +
|
||||
engine_name() + ".\n",
|
||||
COLVARS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy::load_coords_pdb(char const * /* filename */,
|
||||
std::vector<cvm::atom_pos> & /* pos */,
|
||||
std::vector<int> const & /* sorted_ids */,
|
||||
std::string const & /* pdb_field */,
|
||||
double /* pdb_field_value */)
|
||||
{
|
||||
return cvm::error(
|
||||
"Error: loading atomic coordinates from a PDB file is currently not implemented in " +
|
||||
engine_name() + ".\n",
|
||||
COLVARS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy::update_input()
|
||||
{
|
||||
return COLVARS_OK;
|
||||
@ -591,47 +607,78 @@ void colvarproxy::print_input_atomic_data()
|
||||
cvm::log(cvm::line_marker);
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atoms_ids = "+cvm::to_str(atoms_ids)+"\n");
|
||||
"atoms_ids[size = "+cvm::to_str(atoms_ids.size())+
|
||||
"] = "+cvm::to_str(atoms_ids)+"\n");
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atoms_refcount = "+cvm::to_str(atoms_refcount)+"\n");
|
||||
"atoms_refcount[size = "+cvm::to_str(atoms_refcount.size())+
|
||||
"] = "+cvm::to_str(atoms_refcount)+"\n");
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atoms_masses = "+cvm::to_str(atoms_masses)+"\n");
|
||||
"atoms_masses[size = "+cvm::to_str(atoms_masses.size())+
|
||||
"] = "+cvm::to_str(atoms_masses)+"\n");
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atoms_charges = "+cvm::to_str(atoms_charges)+"\n");
|
||||
"atoms_charges[size = "+cvm::to_str(atoms_charges.size())+
|
||||
"] = "+cvm::to_str(atoms_charges)+"\n");
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atoms_positions = "+cvm::to_str(atoms_positions,
|
||||
"atoms_positions[size = "+cvm::to_str(atoms_positions.size())+
|
||||
"] = "+cvm::to_str(atoms_positions,
|
||||
cvm::cv_width,
|
||||
cvm::cv_prec)+"\n");
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atoms_total_forces = "+cvm::to_str(atoms_total_forces,
|
||||
"atoms_total_forces[size = "+
|
||||
cvm::to_str(atoms_total_forces.size())+
|
||||
"] = "+cvm::to_str(atoms_total_forces,
|
||||
cvm::cv_width,
|
||||
cvm::cv_prec)+"\n");
|
||||
|
||||
cvm::log(cvm::line_marker);
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atom_groups_ids = "+cvm::to_str(atom_groups_ids)+"\n");
|
||||
"atom_groups_ids[size = "+cvm::to_str(atom_groups_ids.size())+
|
||||
"] = "+cvm::to_str(atom_groups_ids)+"\n");
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atom_groups_refcount = "+cvm::to_str(atom_groups_refcount)+"\n");
|
||||
"atom_groups_refcount[size = "+
|
||||
cvm::to_str(atom_groups_refcount.size())+
|
||||
"] = "+cvm::to_str(atom_groups_refcount)+"\n");
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atom_groups_masses = "+cvm::to_str(atom_groups_masses)+"\n");
|
||||
"atom_groups_masses[size = "+
|
||||
cvm::to_str(atom_groups_masses.size())+
|
||||
"] = "+cvm::to_str(atom_groups_masses)+"\n");
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atom_groups_charges = "+cvm::to_str(atom_groups_charges)+"\n");
|
||||
"atom_groups_charges[size = "+
|
||||
cvm::to_str(atom_groups_charges.size())+
|
||||
"] = "+cvm::to_str(atom_groups_charges)+"\n");
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atom_groups_coms = "+cvm::to_str(atom_groups_coms,
|
||||
"atom_groups_coms[size = "+
|
||||
cvm::to_str(atom_groups_coms.size())+
|
||||
"] = "+cvm::to_str(atom_groups_coms,
|
||||
cvm::cv_width,
|
||||
cvm::cv_prec)+"\n");
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"atom_groups_total_forces = "+cvm::to_str(atom_groups_total_forces,
|
||||
"atom_groups_total_forces[size = "+
|
||||
cvm::to_str(atom_groups_total_forces.size())+
|
||||
"] = "+cvm::to_str(atom_groups_total_forces,
|
||||
cvm::cv_width,
|
||||
cvm::cv_prec)+"\n");
|
||||
|
||||
cvm::log(cvm::line_marker);
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"volmaps_ids = "+cvm::to_str(volmaps_ids)+"\n");
|
||||
"volmaps_ids[size = "+cvm::to_str(volmaps_ids.size())+
|
||||
"] = "+cvm::to_str(volmaps_ids)+"\n");
|
||||
|
||||
cvm::log("Step "+cvm::to_str(cvm::step_absolute())+", "+
|
||||
"volmaps_values = "+cvm::to_str(volmaps_values)+"\n");
|
||||
"volmaps_values[size = "+cvm::to_str(volmaps_values.size())+
|
||||
"] = "+cvm::to_str(volmaps_values)+"\n");
|
||||
|
||||
cvm::log(cvm::line_marker);
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvartypes.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarproxy_io.h"
|
||||
#include "colvarproxy_system.h"
|
||||
#include "colvarproxy_tcl.h"
|
||||
@ -56,6 +55,9 @@ public:
|
||||
/// corresponding atom yet
|
||||
virtual int check_atom_id(int atom_number);
|
||||
|
||||
/// Check whether it is possible to select atoms by residue number name
|
||||
virtual int check_atom_name_selections_available();
|
||||
|
||||
/// Select this atom for collective variables calculation, using name and
|
||||
/// residue number. Not all programs support this: leave this function as
|
||||
/// is in those cases.
|
||||
@ -72,31 +74,6 @@ public:
|
||||
/// (costly) set the corresponding atoms_refcount to zero
|
||||
virtual void clear_atom(int index);
|
||||
|
||||
/// \brief Select atom IDs from a file (usually PDB) \param filename name of
|
||||
/// the file \param atoms array to which atoms read from "filename" will be
|
||||
/// appended \param pdb_field (optional) if the file is a PDB and this
|
||||
/// string is non-empty, select atoms for which this field is non-zero
|
||||
/// \param pdb_field_value (optional) if non-zero, select only atoms whose
|
||||
/// pdb_field equals this
|
||||
virtual int load_atoms(char const *filename,
|
||||
cvm::atom_group &atoms,
|
||||
std::string const &pdb_field,
|
||||
double pdb_field_value = 0.0);
|
||||
|
||||
/// \brief Load a set of coordinates from a file (usually PDB); if "pos" is
|
||||
/// already allocated, the number of its elements must match the number of
|
||||
/// entries in "filename" \param filename name of the file \param pos array
|
||||
/// of coordinates \param sorted_ids array of sorted internal IDs, used to
|
||||
/// loop through the file only once \param pdb_field (optional) if the file
|
||||
/// is a PDB and this string is non-empty, select atoms for which this field
|
||||
/// is non-zero \param pdb_field_value (optional) if non-zero, select only
|
||||
/// atoms whose pdb_field equals this
|
||||
virtual int load_coords(char const *filename,
|
||||
std::vector<cvm::atom_pos> &pos,
|
||||
std::vector<int> const &sorted_ids,
|
||||
std::string const &pdb_field,
|
||||
double pdb_field_value = 0.0);
|
||||
|
||||
/// Clear atomic data
|
||||
int reset();
|
||||
|
||||
@ -245,6 +222,18 @@ public:
|
||||
return atoms_max_applied_force_id_;
|
||||
}
|
||||
|
||||
/// Whether the atom list has been modified internally
|
||||
inline bool modified_atom_list() const
|
||||
{
|
||||
return modified_atom_list_;
|
||||
}
|
||||
|
||||
/// Reset the modified atom list flag
|
||||
inline void reset_modified_atom_list()
|
||||
{
|
||||
modified_atom_list_ = false;
|
||||
}
|
||||
|
||||
/// Record whether masses have been updated
|
||||
inline bool updated_masses() const
|
||||
{
|
||||
@ -284,6 +273,9 @@ protected:
|
||||
/// ID of the atom with the maximum norm among all applied forces
|
||||
int atoms_max_applied_force_id_;
|
||||
|
||||
/// Whether the atom list has been modified internally
|
||||
bool modified_atom_list_;
|
||||
|
||||
/// Whether the masses and charges have been updated from the host code
|
||||
bool updated_masses_, updated_charges_;
|
||||
|
||||
@ -466,7 +458,7 @@ public:
|
||||
bool b_smp_active;
|
||||
|
||||
/// Whether threaded parallelization is available (TODO: make this a cvm::deps feature)
|
||||
virtual int smp_enabled();
|
||||
virtual int check_smp_enabled();
|
||||
|
||||
/// Distribute calculation of colvars (and their components) across threads
|
||||
virtual int smp_colvars_loop();
|
||||
@ -565,9 +557,9 @@ public:
|
||||
|
||||
|
||||
|
||||
/// \brief Interface between the collective variables module and
|
||||
/// the simulation or analysis program (NAMD, VMD, LAMMPS...).
|
||||
/// This is the base class: each interfaced program is supported by a derived class.
|
||||
/// Interface between Colvars and MD engine (GROMACS, LAMMPS, NAMD, VMD...)
|
||||
///
|
||||
/// This is the base class: each engine is supported by a derived class.
|
||||
class colvarproxy
|
||||
: public colvarproxy_system,
|
||||
public colvarproxy_atoms,
|
||||
@ -589,15 +581,20 @@ public:
|
||||
colvarproxy();
|
||||
|
||||
/// Destructor
|
||||
virtual ~colvarproxy();
|
||||
~colvarproxy() override;
|
||||
|
||||
virtual bool io_available() /* override */;
|
||||
inline std::string const &engine_name() const
|
||||
{
|
||||
return engine_name_;
|
||||
}
|
||||
|
||||
bool io_available() override;
|
||||
|
||||
/// Request deallocation of the module (currently only implemented by VMD)
|
||||
virtual int request_deletion();
|
||||
|
||||
/// Whether deallocation was requested
|
||||
inline bool delete_requested()
|
||||
inline bool delete_requested() const
|
||||
{
|
||||
return b_delete_requested;
|
||||
}
|
||||
@ -608,6 +605,26 @@ public:
|
||||
/// (Re)initialize the module
|
||||
virtual int parse_module_config();
|
||||
|
||||
/// \brief Read a selection of atom IDs from a PDB coordinate file
|
||||
/// \param[in] filename name of the file
|
||||
/// \param[in,out] atoms array into which atoms will be read from "filename"
|
||||
/// \param[in] pdb_field if the file is a PDB and this string is non-empty,
|
||||
/// select atoms for which this field is non-zero
|
||||
/// \param[in] pdb_field_value if non-zero, select only atoms whose pdb_field equals this
|
||||
virtual int load_atoms_pdb(char const *filename, cvm::atom_group &atoms,
|
||||
std::string const &pdb_field, double pdb_field_value);
|
||||
|
||||
/// \brief Load a set of coordinates from a PDB file
|
||||
/// \param[in] filename name of the file
|
||||
/// \param[in,out] pos array of coordinates to fill; if not empty, the number of its elements must match
|
||||
/// the number of entries in "filename"
|
||||
/// \param[in] sorted_ids array of sorted internal IDs, used to loop through the file only once
|
||||
/// \param[in] pdb_field if non-empty, only atoms for which this field is non-zero will be processed
|
||||
/// \param[in] pdb_field_value if non-zero, process only atoms whose pdb_field equals this
|
||||
virtual int load_coords_pdb(char const *filename, std::vector<cvm::atom_pos> &pos,
|
||||
std::vector<int> const &sorted_ids, std::string const &pdb_field,
|
||||
double pdb_field_value);
|
||||
|
||||
/// (Re)initialize required member data (called after the module)
|
||||
virtual int setup();
|
||||
|
||||
@ -703,7 +720,10 @@ protected:
|
||||
/// Track which features have been acknowledged during the last run
|
||||
size_t features_hash;
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
/// Name of the simulation engine that the derived proxy object supports
|
||||
std::string engine_name_ = "standalone";
|
||||
|
||||
/// Queue of config strings or files to be fed to the module
|
||||
void *config_queue_;
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
|
||||
colvarproxy_io::colvarproxy_io()
|
||||
{
|
||||
input_buffer_ = NULL;
|
||||
restart_frequency_engine = 0;
|
||||
input_stream_error_ = new std::istringstream();
|
||||
input_stream_error_->setstate(std::ios::badbit);
|
||||
@ -135,7 +134,9 @@ int colvarproxy_io::rename_file(char const *filename, char const *newfilename)
|
||||
int error_code = COLVARS_OK;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
// On straight Windows, must remove the destination before renaming it
|
||||
if (_access(newfilename, 00) == 0) {
|
||||
error_code |= remove_file(newfilename);
|
||||
}
|
||||
#endif
|
||||
int rename_exit_code = 0;
|
||||
while ((rename_exit_code = std::rename(filename, newfilename)) != 0) {
|
||||
@ -151,6 +152,51 @@ int colvarproxy_io::rename_file(char const *filename, char const *newfilename)
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_io::set_input_prefix(std::string const &prefix)
|
||||
{
|
||||
// set input restart name and strip the extension, if present
|
||||
input_prefix_str = prefix;
|
||||
if (input_prefix_str.rfind(".colvars.state") != std::string::npos) {
|
||||
input_prefix_str.erase(input_prefix_str.rfind(".colvars.state"),
|
||||
std::string(".colvars.state").size());
|
||||
}
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_io::set_output_prefix(std::string const &prefix)
|
||||
{
|
||||
// set input restart name and strip the extension, if present
|
||||
output_prefix_str = prefix;
|
||||
if (output_prefix_str.rfind(".colvars.state") != std::string::npos) {
|
||||
output_prefix_str.erase(output_prefix_str.rfind(".colvars.state"),
|
||||
std::string(".colvars.state").size());
|
||||
}
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_io::set_restart_output_prefix(std::string const &prefix)
|
||||
{
|
||||
// set input restart name and strip the extension, if present
|
||||
restart_output_prefix_str = prefix;
|
||||
if (restart_output_prefix_str.rfind(".colvars.state") != std::string::npos) {
|
||||
restart_output_prefix_str.erase(restart_output_prefix_str.rfind(".colvars.state"),
|
||||
std::string(".colvars.state").size());
|
||||
}
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_io::set_default_restart_frequency(int freq)
|
||||
{
|
||||
// TODO check for compatibility with colvarsRestartFrequency
|
||||
restart_frequency_engine = freq;
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::istream &colvarproxy_io::input_stream(std::string const &input_name,
|
||||
std::string const description,
|
||||
bool error_on_fail)
|
||||
@ -162,13 +208,18 @@ std::istream &colvarproxy_io::input_stream(std::string const &input_name,
|
||||
}
|
||||
|
||||
if (colvarproxy_io::input_stream_exists(input_name)) {
|
||||
return *(input_streams_[input_name]);
|
||||
}
|
||||
|
||||
// Using binary to work around differences in line termination conventions
|
||||
std::ifstream *ifs =
|
||||
dynamic_cast<std::ifstream *>(input_streams_[input_name]);
|
||||
if (ifs && !ifs->is_open()) {
|
||||
// This file was opened before, re-open it. Using std::ios::binary to
|
||||
// work around differences in line termination conventions
|
||||
// See https://github.com/Colvars/colvars/commit/8236879f7de4
|
||||
ifs->open(input_name.c_str(), std::ios::binary);
|
||||
}
|
||||
} else {
|
||||
input_streams_[input_name] = new std::ifstream(input_name.c_str(),
|
||||
std::ios::binary);
|
||||
}
|
||||
|
||||
if (input_streams_[input_name]->fail() && error_on_fail) {
|
||||
cvm::error("Error: cannot open "+description+" \""+input_name+"\".\n",
|
||||
@ -179,6 +230,41 @@ std::istream &colvarproxy_io::input_stream(std::string const &input_name,
|
||||
}
|
||||
|
||||
|
||||
std::istream &
|
||||
colvarproxy_io::input_stream_from_string(std::string const &input_name,
|
||||
std::string const &content,
|
||||
std::string const description)
|
||||
{
|
||||
if (!io_available()) {
|
||||
cvm::error("Error: trying to access an input file/channel "
|
||||
"from the wrong thread.\n", COLVARS_BUG_ERROR);
|
||||
return *input_stream_error_;
|
||||
}
|
||||
|
||||
if (colvarproxy_io::input_stream_exists(input_name)) {
|
||||
|
||||
std::istringstream *iss =
|
||||
dynamic_cast<std::istringstream *>(input_streams_[input_name]);
|
||||
if (iss) {
|
||||
// If there is already a stringstream, replace it
|
||||
delete iss;
|
||||
} else {
|
||||
std::ifstream *ifs =
|
||||
dynamic_cast<std::ifstream *>(input_streams_[input_name]);
|
||||
if (ifs) {
|
||||
if (ifs->is_open()) {
|
||||
ifs->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input_streams_[input_name] = new std::istringstream(content);
|
||||
|
||||
return *(input_streams_[input_name]);
|
||||
}
|
||||
|
||||
|
||||
bool colvarproxy_io::input_stream_exists(std::string const &input_name)
|
||||
{
|
||||
return (input_streams_.count(input_name) > 0);
|
||||
@ -188,7 +274,38 @@ bool colvarproxy_io::input_stream_exists(std::string const &input_name)
|
||||
int colvarproxy_io::close_input_stream(std::string const &input_name)
|
||||
{
|
||||
if (colvarproxy_io::input_stream_exists(input_name)) {
|
||||
delete input_streams_[input_name];
|
||||
std::ifstream *ifs = dynamic_cast<std::ifstream *>(input_streams_[input_name]);
|
||||
if (ifs) {
|
||||
if (ifs->is_open()) {
|
||||
ifs->close();
|
||||
}
|
||||
} else {
|
||||
// From a string, just rewind to the begining
|
||||
std::istringstream * iss = dynamic_cast<std::istringstream *>(input_streams_[input_name]);
|
||||
if (iss) {
|
||||
iss->clear();
|
||||
iss->seekg(0);
|
||||
}
|
||||
}
|
||||
return COLVARS_OK;
|
||||
}
|
||||
return cvm::error("Error: input file/channel \""+input_name+
|
||||
"\" does not exist.\n", COLVARS_FILE_ERROR);
|
||||
}
|
||||
|
||||
|
||||
int colvarproxy_io::delete_input_stream(std::string const &input_name)
|
||||
{
|
||||
if (colvarproxy_io::close_input_stream(input_name) == COLVARS_OK) {
|
||||
std::ifstream *ifs = dynamic_cast<std::ifstream *>(input_streams_[input_name]);
|
||||
if (ifs) {
|
||||
delete ifs;
|
||||
} else {
|
||||
std::istringstream * iss = dynamic_cast<std::istringstream *>(input_streams_[input_name]);
|
||||
if (iss) {
|
||||
delete iss;
|
||||
}
|
||||
}
|
||||
input_streams_.erase(input_name);
|
||||
return COLVARS_OK;
|
||||
}
|
||||
@ -199,7 +316,8 @@ int colvarproxy_io::close_input_stream(std::string const &input_name)
|
||||
|
||||
int colvarproxy_io::close_input_streams()
|
||||
{
|
||||
for (std::map<std::string, std::istream *>::iterator ii = input_streams_.begin();
|
||||
for (std::map<std::string,
|
||||
std::istream *>::iterator ii = input_streams_.begin();
|
||||
ii != input_streams_.end();
|
||||
ii++) {
|
||||
delete ii->second;
|
||||
@ -209,6 +327,19 @@ int colvarproxy_io::close_input_streams()
|
||||
}
|
||||
|
||||
|
||||
std::list<std::string> colvarproxy_io::list_input_stream_names() const
|
||||
{
|
||||
std::list<std::string> result;
|
||||
for (std::map<std::string,
|
||||
std::istream *>::const_iterator ii = input_streams_.begin();
|
||||
ii != input_streams_.end();
|
||||
ii++) {
|
||||
result.push_back(ii->first);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::ostream & colvarproxy_io::output_stream(std::string const &output_name,
|
||||
std::string const description)
|
||||
{
|
||||
@ -228,7 +359,7 @@ std::ostream & colvarproxy_io::output_stream(std::string const &output_name,
|
||||
|
||||
backup_file(output_name.c_str());
|
||||
|
||||
output_streams_[output_name] = new std::ofstream(output_name.c_str());
|
||||
output_streams_[output_name] = new std::ofstream(output_name.c_str(), std::ios::binary);
|
||||
if (!*(output_streams_[output_name])) {
|
||||
cvm::error("Error: cannot write to "+description+" \""+output_name+"\".\n",
|
||||
COLVARS_FILE_ERROR);
|
||||
@ -303,6 +434,7 @@ int colvarproxy_io::close_output_streams()
|
||||
osi != output_streams_.end();
|
||||
osi++) {
|
||||
(dynamic_cast<std::ofstream *>(osi->second))->close();
|
||||
delete osi->second;
|
||||
}
|
||||
output_streams_.clear();
|
||||
|
||||
|
||||
@ -10,9 +10,10 @@
|
||||
#ifndef COLVARPROXY_IO_H
|
||||
#define COLVARPROXY_IO_H
|
||||
|
||||
#include <iosfwd>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
|
||||
|
||||
/// Methods for data input/output
|
||||
@ -66,57 +67,80 @@ public:
|
||||
}
|
||||
|
||||
/// Prefix of the input state file to be read next
|
||||
inline std::string & input_prefix()
|
||||
inline std::string const & input_prefix() const
|
||||
{
|
||||
return input_prefix_str;
|
||||
}
|
||||
|
||||
/// Initialize input_prefix (NOTE: it will be erased after state file is read)
|
||||
virtual int set_input_prefix(std::string const &prefix);
|
||||
|
||||
/// Default prefix to be used for all output files (final configuration)
|
||||
inline std::string & output_prefix()
|
||||
inline std::string const & output_prefix() const
|
||||
{
|
||||
return output_prefix_str;
|
||||
}
|
||||
|
||||
/// Set default output prefix
|
||||
virtual int set_output_prefix(std::string const &prefix);
|
||||
|
||||
/// Prefix of the restart (checkpoint) file to be written next
|
||||
inline std::string & restart_output_prefix()
|
||||
inline std::string const & restart_output_prefix() const
|
||||
{
|
||||
return restart_output_prefix_str;
|
||||
}
|
||||
|
||||
/// Set default restart state file prefix
|
||||
virtual int set_restart_output_prefix(std::string const &prefix);
|
||||
|
||||
/// Default restart frequency (as set by the simulation engine)
|
||||
inline int default_restart_frequency() const
|
||||
{
|
||||
return restart_frequency_engine;
|
||||
}
|
||||
|
||||
/// Buffer from which the input state information may be read
|
||||
inline char const * & input_buffer()
|
||||
{
|
||||
return input_buffer_;
|
||||
}
|
||||
/// Communicate/set the restart frequency of the simulation engine
|
||||
virtual int set_default_restart_frequency(int freq);
|
||||
|
||||
// The input stream functions below are not virtual, because they currently
|
||||
// rely on the fact that either std::ifstream or std::istringstream is used
|
||||
|
||||
/// Returns a reference to given input stream, creating it if needed
|
||||
/// \param input_name File name (later only a handle)
|
||||
/// \param description Purpose of the file
|
||||
/// \param error_on_fail Raise error when failing to open (allow testing)
|
||||
virtual std::istream &input_stream(std::string const &input_name,
|
||||
std::istream & input_stream(std::string const &input_name,
|
||||
std::string const description = "file/channel",
|
||||
bool error_on_fail = true);
|
||||
|
||||
/// Returns a reference to given input stream, creating it if needed
|
||||
/// \param input_name Identifier of the input stream
|
||||
/// \param content Set this string as the stream's buffer
|
||||
/// \param description Purpose of the stream
|
||||
std::istream & input_stream_from_string(std::string const &input_name,
|
||||
std::string const &content,
|
||||
std::string const description = "string");
|
||||
|
||||
/// Check if the file/channel is open (without opening it if not)
|
||||
virtual bool input_stream_exists(std::string const &input_name);
|
||||
bool input_stream_exists(std::string const &input_name);
|
||||
|
||||
/// Closes the given input stream
|
||||
virtual int close_input_stream(std::string const &input_name);
|
||||
int close_input_stream(std::string const &input_name);
|
||||
|
||||
/// Closes all input streams
|
||||
virtual int close_input_streams();
|
||||
int close_input_streams();
|
||||
|
||||
/// Same as close_input_stream(), but also removes the corresponding entry from memory
|
||||
int delete_input_stream(std::string const &input_name);
|
||||
|
||||
/// List all input streams that were opened at some point
|
||||
std::list<std::string> list_input_stream_names() const;
|
||||
|
||||
/// Returns a reference to the named output file/channel (open it if needed)
|
||||
/// \param output_name File name or identifier
|
||||
/// \param description Purpose of the file
|
||||
virtual std::ostream &output_stream(std::string const &output_name,
|
||||
std::string const description = "file/channel");
|
||||
std::string const description);
|
||||
|
||||
/// Check if the file/channel is open (without opening it if not)
|
||||
virtual bool output_stream_exists(std::string const &output_name);
|
||||
@ -158,9 +182,6 @@ protected:
|
||||
|
||||
/// Object whose reference is returned when write errors occur
|
||||
std::ostream *output_stream_error_;
|
||||
|
||||
/// Buffer from which the input state information may be read
|
||||
char const *input_buffer_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@ colvarproxy_system::colvarproxy_system()
|
||||
{
|
||||
angstrom_value_ = 0.0;
|
||||
kcal_mol_value_ = 0.0;
|
||||
timestep_ = 1.0;
|
||||
target_temperature_ = 0.0;
|
||||
boltzmann_ = 0.001987191; // Default: kcal/mol/K
|
||||
boundaries_type = boundaries_unsupported;
|
||||
@ -46,10 +47,10 @@ int colvarproxy_system::set_target_temperature(cvm::real T)
|
||||
}
|
||||
|
||||
|
||||
cvm::real colvarproxy_system::dt()
|
||||
int colvarproxy_system::set_integration_timestep(cvm::real dt)
|
||||
{
|
||||
// TODO define, document and implement a user method to set the value of this
|
||||
return 1.0;
|
||||
timestep_ = dt;
|
||||
return COLVARS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -61,8 +61,14 @@ public:
|
||||
/// Set the current target temperature of the simulation (K units)
|
||||
virtual int set_target_temperature(cvm::real T);
|
||||
|
||||
/// \brief Time step of the simulation (fs)
|
||||
virtual cvm::real dt();
|
||||
/// Time step of the simulation (fs units)
|
||||
inline double dt() const
|
||||
{
|
||||
return timestep_;
|
||||
}
|
||||
|
||||
/// Set the current integration timestep of the simulation (fs units)
|
||||
virtual int set_integration_timestep(cvm::real dt);
|
||||
|
||||
/// \brief Pseudo-random number with Gaussian distribution
|
||||
virtual cvm::real rand_gaussian(void);
|
||||
@ -137,9 +143,12 @@ protected:
|
||||
/// Boltzmann constant in internal Colvars units
|
||||
cvm::real boltzmann_;
|
||||
|
||||
/// Most up to date target temperature for the system (in K)
|
||||
/// Most up to date target temperature (K units); default to 0.0 if undefined
|
||||
cvm::real target_temperature_;
|
||||
|
||||
/// Current integration timestep (engine units); default to 1.0 if undefined
|
||||
double timestep_;
|
||||
|
||||
/// \brief Value of 1 Angstrom in the internal (front-end) Colvars unit for atomic coordinates
|
||||
/// * defaults to 0 in the base class; derived proxy classes must set it
|
||||
/// * in VMD proxy, can only be changed when no variables are defined
|
||||
|
||||
@ -83,7 +83,7 @@ int colvarproxy_tcl::tcl_run_file(std::string const &fileName)
|
||||
Tcl_Interp *const interp = get_tcl_interp();
|
||||
int err = Tcl_EvalFile(interp, fileName.c_str());
|
||||
if (err != TCL_OK) {
|
||||
cvm::log("Error while executing Tcl script file" + fileName + ":\n");
|
||||
cvm::log("Error while executing Tcl script file \"" + fileName + "\":\n");
|
||||
cvm::error(Tcl_GetStringResult(interp));
|
||||
return COLVARS_ERROR;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ colvarproxy_volmaps::colvarproxy_volmaps()
|
||||
colvarproxy_volmaps::~colvarproxy_volmaps() {}
|
||||
|
||||
|
||||
int colvarproxy_volmaps::volmaps_available()
|
||||
int colvarproxy_volmaps::check_volmaps_available()
|
||||
{
|
||||
return COLVARS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
@ -18,8 +18,8 @@ public:
|
||||
/// Clear volumetric map data
|
||||
int reset();
|
||||
|
||||
/// \brief Whether this implementation has capability to use volumetric maps
|
||||
virtual int volmaps_available();
|
||||
/// Test whether this implementation can use volumetric maps as CVs
|
||||
virtual int check_volmaps_available();
|
||||
|
||||
/// Create a slot for a volumetric map not requested yet
|
||||
int add_volmap_slot(int volmap_id);
|
||||
|
||||
102
lib/colvars/colvars_memstream.cpp
Normal file
102
lib/colvars/colvars_memstream.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
// -*- 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.
|
||||
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvartypes.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvars_memstream.h"
|
||||
|
||||
|
||||
bool cvm::memory_stream::expand_output_buffer(size_t add_bytes)
|
||||
{
|
||||
auto &buffer = external_output_buffer_ ? *external_output_buffer_ : internal_buffer_;
|
||||
if ((buffer.size() + add_bytes) <= max_length_) {
|
||||
buffer.resize((buffer.size() + add_bytes));
|
||||
} else {
|
||||
setstate(std::ios::badbit);
|
||||
}
|
||||
return bool(*this);
|
||||
}
|
||||
|
||||
|
||||
template <> void cvm::memory_stream::write_object(std::string const &t)
|
||||
{
|
||||
size_t const string_length = t.size();
|
||||
size_t const new_data_size = sizeof(size_t) + sizeof(char) * string_length;
|
||||
if (expand_output_buffer(new_data_size)) {
|
||||
std::memcpy(output_location(), &string_length, sizeof(size_t));
|
||||
incr_write_pos(sizeof(size_t));
|
||||
std::memcpy(output_location(), t.c_str(), t.size() * sizeof(char));
|
||||
incr_write_pos(t.size() * sizeof(char));
|
||||
}
|
||||
}
|
||||
|
||||
template <> cvm::memory_stream &operator<<(cvm::memory_stream &os, std::string const &t)
|
||||
{
|
||||
os.write_object<std::string>(t);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <> void cvm::memory_stream::write_object(colvarvalue const &t)
|
||||
{
|
||||
*this << t;
|
||||
}
|
||||
|
||||
template <> void cvm::memory_stream::write_object(cvm::vector1d<cvm::real> const &t)
|
||||
{
|
||||
return write_vector<cvm::real>(t.data_array());
|
||||
}
|
||||
|
||||
template <>
|
||||
cvm::memory_stream &operator<<(cvm::memory_stream &os, cvm::vector1d<cvm::real> const &t)
|
||||
{
|
||||
os.write_vector<cvm::real>(t.data_array());
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template <> void cvm::memory_stream::read_object(std::string &t)
|
||||
{
|
||||
begin_reading();
|
||||
size_t string_length = 0;
|
||||
if (has_remaining(sizeof(size_t))) {
|
||||
std::memcpy(&string_length, input_location(), sizeof(size_t));
|
||||
incr_read_pos(sizeof(size_t));
|
||||
if (has_remaining(string_length * sizeof(char))) {
|
||||
t.assign(reinterpret_cast<char const *>(input_location()), string_length);
|
||||
incr_read_pos(string_length * sizeof(char));
|
||||
done_reading();
|
||||
} else {
|
||||
setstate(std::ios::failbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, std::string &t)
|
||||
{
|
||||
is.read_object<std::string>(t);
|
||||
return is;
|
||||
}
|
||||
|
||||
template <> void cvm::memory_stream::read_object(colvarvalue &t)
|
||||
{
|
||||
*this >> t;
|
||||
}
|
||||
|
||||
template <> void cvm::memory_stream::read_object(cvm::vector1d<cvm::real> &t)
|
||||
{
|
||||
return read_vector<cvm::real>(t.data_array());
|
||||
}
|
||||
|
||||
template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, cvm::vector1d<cvm::real> &t)
|
||||
{
|
||||
is.read_vector<cvm::real>(t.data_array());
|
||||
return is;
|
||||
}
|
||||
289
lib/colvars/colvars_memstream.h
Normal file
289
lib/colvars/colvars_memstream.h
Normal file
@ -0,0 +1,289 @@
|
||||
// -*- 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 MEMORY_STREAM_H
|
||||
#define MEMORY_STREAM_H
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
// Work around missing std::is_trivially_copyable in old GCC and Clang versions
|
||||
// TODO remove this after CentOS 7 has been beyond EOL for a while
|
||||
#if (defined(__GNUC__) && (__GNUC__ < 5) && !defined(__clang__)) || (defined(__clang__) && (__clang_major__ < 7))
|
||||
// Clang needs an exception, because it defines __GNUC__ as well
|
||||
#define IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
|
||||
#else
|
||||
#define IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
|
||||
#endif
|
||||
|
||||
|
||||
class cvm::memory_stream {
|
||||
|
||||
public:
|
||||
|
||||
/// Set up an empty stream with an internal buffer, suitable for writing to
|
||||
/// \param max_length Maximum allowed capacity (default is 64 GiB)
|
||||
memory_stream(size_t max_length = (static_cast<size_t>(1L) << 36)) : max_length_(max_length) {}
|
||||
|
||||
/// Set up a stream based on an external input buffer
|
||||
memory_stream(size_t n, unsigned char const *buf)
|
||||
: external_input_buffer_(buf), internal_buffer_(), data_length_(n), max_length_(data_length_)
|
||||
{
|
||||
}
|
||||
|
||||
/// Set up a stream based on an external output buffer
|
||||
memory_stream(std::vector<unsigned char> &buf) : memory_stream()
|
||||
{
|
||||
external_output_buffer_ = &buf;
|
||||
}
|
||||
|
||||
/// Length of the buffer
|
||||
inline size_t length() const { return data_length_; }
|
||||
|
||||
/// Output buffer
|
||||
inline unsigned char *output_buffer()
|
||||
{
|
||||
return (external_output_buffer_ ? external_output_buffer_->data() : internal_buffer_.data());
|
||||
}
|
||||
|
||||
/// Next location to write to
|
||||
inline unsigned char *output_location() { return output_buffer() + data_length_; }
|
||||
|
||||
/// Input buffer
|
||||
inline unsigned char const *input_buffer() const
|
||||
{
|
||||
return (external_input_buffer_ ? external_input_buffer_ : internal_buffer_.data());
|
||||
}
|
||||
|
||||
/// Next location to read from
|
||||
inline unsigned char const *input_location() const { return input_buffer() + read_pos_; }
|
||||
|
||||
/// Cast operator to be used to test for errors
|
||||
inline explicit operator bool() const { return state_ == std::ios::goodbit; }
|
||||
|
||||
/// Write a simple object to the output buffer
|
||||
template <typename T> void write_object(T const &t);
|
||||
|
||||
/// Wrapper to write_object()
|
||||
template <typename T> friend memory_stream &operator<<(memory_stream &os, T const &t);
|
||||
|
||||
/// Write a vector of simple objects to the output buffer
|
||||
template <typename T> void write_vector(std::vector<T> const &t);
|
||||
|
||||
/// Wrapper to write_vector()
|
||||
template <typename T>
|
||||
friend memory_stream &operator<<(memory_stream &os, std::vector<T> const &t);
|
||||
|
||||
/// Read a simple object from the buffer
|
||||
template <typename T> void read_object(T &t);
|
||||
|
||||
/// Wrapper to read_object()
|
||||
template <typename T> friend memory_stream &operator>>(memory_stream &is, T &t);
|
||||
|
||||
/// Read a vector of simple objects from the buffer
|
||||
template <typename T> void read_vector(std::vector<T> &t);
|
||||
|
||||
/// Wrapper to read_vector()
|
||||
template <typename T> friend memory_stream &operator>>(memory_stream &is, std::vector<T> &t);
|
||||
|
||||
|
||||
// Compatibility with STL stream functions
|
||||
|
||||
/// Report the current position in the buffer
|
||||
inline size_t tellg() const { return read_pos_; }
|
||||
|
||||
/// Report the current position in the buffer
|
||||
inline memory_stream & seekg(size_t pos) { read_pos_ = pos; return *this; }
|
||||
|
||||
/// Ignore formatting operators
|
||||
inline void setf(decltype(std::ios::fmtflags(0)), decltype(std::ios::floatfield)) {}
|
||||
|
||||
/// Ignore formatting operators
|
||||
inline void flags(decltype(std::ios::fmtflags(0))) {}
|
||||
|
||||
/// Get the current formatting flags (i.e. none because this stream is unformatted)
|
||||
inline decltype(std::ios::fmtflags(0)) flags() const { return std::ios::fmtflags(0); }
|
||||
|
||||
/// Get the error code
|
||||
inline std::ios::iostate rdstate() const { return state_; }
|
||||
|
||||
/// Set the error code
|
||||
inline void setstate(std::ios::iostate new_state) { state_ |= new_state; }
|
||||
|
||||
/// Clear the error code
|
||||
inline void clear() { state_ = std::ios::goodbit; }
|
||||
|
||||
protected:
|
||||
|
||||
/// External output buffer
|
||||
std::vector<unsigned char> *external_output_buffer_ = nullptr;
|
||||
|
||||
/// External input buffer
|
||||
unsigned char const *external_input_buffer_ = nullptr;
|
||||
|
||||
/// Internal buffer (may server for both input and output)
|
||||
std::vector<unsigned char> internal_buffer_;
|
||||
|
||||
/// Length of the data buffer (either internal or external)
|
||||
size_t data_length_ = 0L;
|
||||
|
||||
/// Largest allowed capacity of the data buffer
|
||||
size_t const max_length_;
|
||||
|
||||
/// Error status
|
||||
std::ios::iostate state_ = std::ios::goodbit;
|
||||
|
||||
/// Add the requester number of bytes to the array capacity; return false if buffer is external
|
||||
bool expand_output_buffer(size_t add_bytes);
|
||||
|
||||
/// Move the buffer position past the data just written
|
||||
inline void incr_write_pos(size_t c) { data_length_ += c; }
|
||||
|
||||
/// Current position when reading from the buffer
|
||||
size_t read_pos_ = 0L;
|
||||
|
||||
/// Begin an attempt to read an object; assume EOF unless there is space remaining
|
||||
inline void begin_reading() { setstate(std::ios::eofbit); }
|
||||
|
||||
/// Mark the reading attempt succesful
|
||||
inline void done_reading() { clear(); }
|
||||
|
||||
/// Move the buffer position past the data just read
|
||||
inline void incr_read_pos(size_t c) { read_pos_ += c; }
|
||||
|
||||
/// Check that the buffer contains enough bytes to read as the argument says, set error
|
||||
/// otherwise
|
||||
inline bool has_remaining(size_t c) { return c <= (data_length_ - read_pos_); }
|
||||
};
|
||||
|
||||
template <typename T> void cvm::memory_stream::write_object(T const &t)
|
||||
{
|
||||
static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use write_object() on complex type");
|
||||
size_t const new_data_size = sizeof(T);
|
||||
if (expand_output_buffer(new_data_size)) {
|
||||
std::memcpy(output_location(), &t, sizeof(T));
|
||||
incr_write_pos(new_data_size);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os, T const &t)
|
||||
{
|
||||
os.write_object<T>(t);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename T> void cvm::memory_stream::write_vector(std::vector<T> const &t)
|
||||
{
|
||||
static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use write_vector() on complex type");
|
||||
size_t const vector_length = t.size();
|
||||
size_t const new_data_size = sizeof(size_t) + sizeof(T) * vector_length;
|
||||
if (expand_output_buffer(new_data_size)) {
|
||||
std::memcpy(output_location(), &vector_length, sizeof(size_t));
|
||||
incr_write_pos(sizeof(T));
|
||||
std::memcpy(output_location(), t.data(), t.size() * sizeof(T));
|
||||
incr_write_pos(t.size() * sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
cvm::memory_stream &operator<<(cvm::memory_stream &os, std::vector<T> const &t)
|
||||
{
|
||||
os.write_vector<T>(t);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename T> void cvm::memory_stream::read_object(T &t)
|
||||
{
|
||||
static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use read_object() on complex type");
|
||||
begin_reading();
|
||||
if (has_remaining(sizeof(T))) {
|
||||
std::memcpy(&t, input_location(), sizeof(T));
|
||||
incr_read_pos(sizeof(T));
|
||||
done_reading();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> cvm::memory_stream &operator>>(cvm::memory_stream &is, T &t)
|
||||
{
|
||||
is.read_object<T>(t);
|
||||
return is;
|
||||
}
|
||||
|
||||
template <typename T> void cvm::memory_stream::read_vector(std::vector<T> &t)
|
||||
{
|
||||
static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use read_vector() on complex type");
|
||||
begin_reading();
|
||||
size_t vector_length = 0;
|
||||
if (has_remaining(sizeof(size_t))) {
|
||||
std::memcpy(&vector_length, input_location(), sizeof(size_t));
|
||||
incr_read_pos(sizeof(size_t));
|
||||
if (has_remaining(vector_length * sizeof(T))) {
|
||||
t.resize(vector_length);
|
||||
std::memcpy(t.data(), input_location(), vector_length * sizeof(T));
|
||||
incr_read_pos(vector_length * sizeof(T));
|
||||
done_reading();
|
||||
} else {
|
||||
setstate(std::ios::failbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> cvm::memory_stream &operator>>(cvm::memory_stream &is, std::vector<T> &t)
|
||||
{
|
||||
is.read_vector<T>(t);
|
||||
return is;
|
||||
}
|
||||
|
||||
template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os,
|
||||
decltype(std::setprecision(10)) const &)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER) && !defined(__SUNPRO_CC)
|
||||
// Visual Studio and MSVC use the same return type for both modifiers
|
||||
template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os,
|
||||
decltype(std::setw(10)) const &)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Declare specializations
|
||||
|
||||
template <> void cvm::memory_stream::write_object(std::string const &t);
|
||||
|
||||
template <> cvm::memory_stream &operator<<(cvm::memory_stream &os, std::string const &t);
|
||||
|
||||
template <> void cvm::memory_stream::write_object(colvarvalue const &t);
|
||||
|
||||
template <> cvm::memory_stream &operator<<(cvm::memory_stream &os, colvarvalue const &x);
|
||||
|
||||
template <> void cvm::memory_stream::write_object(cvm::vector1d<cvm::real> const &t);
|
||||
|
||||
template <>
|
||||
cvm::memory_stream &operator<<(cvm::memory_stream &os, cvm::vector1d<cvm::real> const &t);
|
||||
|
||||
template <> void cvm::memory_stream::read_object(std::string &t);
|
||||
|
||||
template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, std::string &t);
|
||||
|
||||
template <> void cvm::memory_stream::read_object(colvarvalue &t);
|
||||
|
||||
template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, colvarvalue &t);
|
||||
|
||||
template <> void cvm::memory_stream::read_object(cvm::vector1d<cvm::real> &t);
|
||||
|
||||
template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, cvm::vector1d<cvm::real> &t);
|
||||
|
||||
#endif
|
||||
@ -1,3 +1,3 @@
|
||||
#ifndef COLVARS_VERSION
|
||||
#define COLVARS_VERSION "2023-05-01"
|
||||
#define COLVARS_VERSION "2024-06-04"
|
||||
#endif
|
||||
|
||||
@ -7,8 +7,6 @@
|
||||
// If you wish to distribute your changes, please submit them to the
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
#include "colvarproxy.h"
|
||||
@ -35,6 +33,7 @@ colvarscript::colvarscript(colvarproxy *p, colvarmodule *m)
|
||||
: proxy_(p),
|
||||
colvars(m)
|
||||
{
|
||||
cmdline_main_cmd_ = std::string("cv");
|
||||
cmd_names = NULL;
|
||||
init_commands();
|
||||
#ifdef COLVARS_TCL
|
||||
@ -141,7 +140,7 @@ int colvarscript::init_command(colvarscript::command const &comm,
|
||||
}
|
||||
|
||||
cmd_full_help[comm] = cmd_help[comm]+"\n";
|
||||
if (cmd_n_args_min[comm] > 0) {
|
||||
if (cmd_n_args_max[comm] > 0) {
|
||||
cmd_full_help[comm] += "\nParameters\n";
|
||||
cmd_full_help[comm] += "----------\n\n";
|
||||
size_t i;
|
||||
@ -281,11 +280,15 @@ std::string colvarscript::get_command_cmdline_syntax(colvarscript::Object_type t
|
||||
|
||||
switch (t) {
|
||||
case use_module:
|
||||
return std::string("cv "+cmdline_cmd+cmdline_args); break;
|
||||
return std::string(cmdline_main_cmd_ + " " + cmdline_cmd + cmdline_args);
|
||||
break;
|
||||
case use_colvar:
|
||||
return std::string("cv colvar name "+cmdline_cmd+cmdline_args); break;
|
||||
return std::string(cmdline_main_cmd_ + " colvar name " + cmdline_cmd+
|
||||
cmdline_args);
|
||||
break;
|
||||
case use_bias:
|
||||
return std::string("cv bias name "+cmdline_cmd+cmdline_args); break;
|
||||
return std::string(cmdline_main_cmd_ + " bias name " + cmdline_cmd+cmdline_args);
|
||||
break;
|
||||
default:
|
||||
// Already handled, but silence the warning
|
||||
return std::string("");
|
||||
@ -353,7 +356,7 @@ int colvarscript::run(int objc, unsigned char *const objv[])
|
||||
}
|
||||
|
||||
if (objc < 2) {
|
||||
set_result_str("No commands given: use \"cv help\" "
|
||||
set_result_str("No commands given: use \""+cmdline_main_cmd_+" help\" "
|
||||
"for a list of commands.");
|
||||
return COLVARSCRIPT_ERROR;
|
||||
}
|
||||
@ -436,7 +439,8 @@ int colvarscript::run(int objc, unsigned char *const objv[])
|
||||
error_code = (*cmd_fn)(obj_for_cmd, objc, objv);
|
||||
} else {
|
||||
add_error_msg("Syntax error: "+cmdline+"\n"
|
||||
" Run \"cv help\" or \"cv help <command>\" "
|
||||
" Run \""+main_cmd+" help\" or \""+
|
||||
main_cmd+" help <command>\" "
|
||||
"to get the correct syntax.\n");
|
||||
error_code = COLVARSCRIPT_ERROR;
|
||||
}
|
||||
@ -763,7 +767,7 @@ extern "C" int tcl_run_colvarscript_command(ClientData /* clientData */,
|
||||
int colvarscript::set_result_text_from_str(std::string const &x_str,
|
||||
unsigned char *obj) {
|
||||
if (obj) {
|
||||
strcpy(reinterpret_cast<char *>(obj), x_str.c_str());
|
||||
std::memcpy(reinterpret_cast<char *>(obj), x_str.c_str(), x_str.size());
|
||||
} else {
|
||||
set_result_str(x_str);
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvarbias.h"
|
||||
#include "colvarproxy.h"
|
||||
|
||||
|
||||
@ -25,6 +24,8 @@
|
||||
#define COLVARSCRIPT_OK 0
|
||||
|
||||
|
||||
class colvardeps;
|
||||
|
||||
class colvarscript {
|
||||
|
||||
private:
|
||||
@ -161,6 +162,11 @@ public:
|
||||
/// \param cmd Name of the command's function (e.g. "cv_units")
|
||||
int get_command_n_args_max(char const *cmd);
|
||||
|
||||
/// Set the main command for the CLI, when it is not "cv" (e.g. LAMMPS)
|
||||
inline void set_cmdline_main_cmd(std::string const &cmd) {
|
||||
cmdline_main_cmd_ = cmd;
|
||||
}
|
||||
|
||||
/// Get help string for a command (does not specify how it is launched)
|
||||
/// \param cmd Name of the command's function (e.g. "cv_units")
|
||||
char const *get_command_full_help(char const *cmd);
|
||||
@ -263,6 +269,9 @@ private: // TODO
|
||||
/// Internal identifiers of command strings
|
||||
std::map<std::string, command> cmd_str_map;
|
||||
|
||||
/// Main command used in command line ("cv" by default)
|
||||
std::string cmdline_main_cmd_;
|
||||
|
||||
/// Inverse of cmd_str_map (to be exported outside this class)
|
||||
char const **cmd_names;
|
||||
|
||||
|
||||
@ -8,9 +8,9 @@
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <string.h>
|
||||
|
||||
#include "colvar.h"
|
||||
#include "colvarbias.h"
|
||||
#include "colvarproxy.h"
|
||||
#include "colvardeps.h"
|
||||
#include "colvarscript.h"
|
||||
|
||||
@ -47,14 +47,10 @@
|
||||
// If CVSCRIPT is not defined, this file yields the function prototypes
|
||||
#ifndef CVSCRIPT
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define CVSCRIPT_COMM_PROTO(COMM) \
|
||||
extern "C" int CVSCRIPT_COMM_FNAME(COMM)(void *, \
|
||||
int, unsigned char *const *);
|
||||
#else
|
||||
#define CVSCRIPT_COMM_PROTO(COMM) \
|
||||
int CVSCRIPT_COMM_FNAME(COMM)(void *, int, unsigned char *const *);
|
||||
#endif
|
||||
int, \
|
||||
unsigned char *const *);
|
||||
|
||||
#define CVSCRIPT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \
|
||||
CVSCRIPT_COMM_PROTO(COMM)
|
||||
@ -454,7 +450,8 @@ CVSCRIPT(cv_listcommands,
|
||||
)
|
||||
|
||||
CVSCRIPT(cv_listindexfiles,
|
||||
"Get a list of the index files loaded in this session",
|
||||
"Get a list of the index files loaded in this session\n"
|
||||
"list : sequence of strings - List of index file names",
|
||||
0, 0,
|
||||
"",
|
||||
int const n_files = script->module()->index_file_names.size();
|
||||
@ -467,19 +464,36 @@ CVSCRIPT(cv_listindexfiles,
|
||||
return COLVARS_OK;
|
||||
)
|
||||
|
||||
CVSCRIPT(cv_listinputfiles,
|
||||
"Get a list of all input/configuration files loaded in this session\n"
|
||||
"list : sequence of strings - List of file names",
|
||||
0, 0,
|
||||
"",
|
||||
std::list<std::string> const l =
|
||||
script->proxy()->list_input_stream_names();
|
||||
std::string result;
|
||||
for (std::list<std::string>::const_iterator li = l.begin();
|
||||
li != l.end(); li++) {
|
||||
if (li != l.begin()) result.append(1, ' ');
|
||||
result.append(*li);
|
||||
}
|
||||
script->set_result_str(result);
|
||||
return COLVARS_OK;
|
||||
)
|
||||
|
||||
CVSCRIPT(cv_load,
|
||||
"Load data from a state file into all matching colvars and biases",
|
||||
1, 1,
|
||||
"prefix : string - Path to existing state file or input prefix",
|
||||
char const *arg =
|
||||
script->obj_to_str(script->get_module_cmd_arg(0, objc, objv));
|
||||
script->proxy()->input_prefix() = cvm::state_file_prefix(arg);
|
||||
if (script->module()->setup_input() == COLVARS_OK) {
|
||||
return COLVARS_OK;
|
||||
} else {
|
||||
int error_code =
|
||||
script->proxy()->set_input_prefix(cvm::state_file_prefix(arg));
|
||||
error_code |= script->module()->setup_input();
|
||||
if (error_code != COLVARS_OK) {
|
||||
script->add_error_msg("Error loading state file");
|
||||
return COLVARSCRIPT_ERROR;
|
||||
}
|
||||
return error_code;
|
||||
)
|
||||
|
||||
CVSCRIPT(cv_loadfromstring,
|
||||
@ -488,7 +502,8 @@ CVSCRIPT(cv_loadfromstring,
|
||||
"buffer : string - String buffer containing the state information",
|
||||
char const *arg =
|
||||
script->obj_to_str(script->get_module_cmd_arg(0, objc, objv));
|
||||
script->proxy()->input_buffer() = arg;
|
||||
script->proxy()->input_stream_from_string("input state string",
|
||||
std::string(arg));
|
||||
if (script->module()->setup_input() == COLVARS_OK) {
|
||||
return COLVARS_OK;
|
||||
} else {
|
||||
@ -560,8 +575,7 @@ CVSCRIPT(cv_save,
|
||||
"prefix : string - Output prefix with trailing \".colvars.state\" gets removed)",
|
||||
std::string const prefix =
|
||||
cvm::state_file_prefix(script->obj_to_str(script->get_module_cmd_arg(0, objc, objv)));
|
||||
script->proxy()->output_prefix() = prefix;
|
||||
int error_code = COLVARS_OK;
|
||||
int error_code = script->proxy()->set_output_prefix(prefix);
|
||||
error_code |= script->module()->setup_output();
|
||||
error_code |= script->module()->write_restart_file(prefix+
|
||||
".colvars.state");
|
||||
@ -578,10 +592,10 @@ CVSCRIPT(cv_savetostring,
|
||||
)
|
||||
|
||||
CVSCRIPT(cv_targettemperature,
|
||||
"Get/set target temperature, overriding what the MD engine provides\n"
|
||||
"Get/set target temperature, overriding internally what the MD engine reports\n"
|
||||
"T : float - Current target temperature in K",
|
||||
0, 1,
|
||||
"T : float - New target temperature in K",
|
||||
"T : float - New target temperature in K (internal use)",
|
||||
char const *Targ =
|
||||
script->obj_to_str(script->get_module_cmd_arg(0, objc, objv));
|
||||
if (Targ == NULL) {
|
||||
@ -591,6 +605,20 @@ CVSCRIPT(cv_targettemperature,
|
||||
}
|
||||
)
|
||||
|
||||
CVSCRIPT(cv_timestep,
|
||||
"Get/set integration timestep, overriding internally what the MD engine reports\n"
|
||||
"dt : float - Current integration timestep in MD engine units",
|
||||
0, 1,
|
||||
"dt : float - New integration timestep in MD engine units",
|
||||
char const *arg =
|
||||
script->obj_to_str(script->get_module_cmd_arg(0, objc, objv));
|
||||
if (arg == NULL) {
|
||||
return script->set_result_real(script->proxy()->dt());
|
||||
} else {
|
||||
return script->proxy()->set_integration_timestep(strtod(arg, NULL));
|
||||
}
|
||||
)
|
||||
|
||||
CVSCRIPT(cv_units,
|
||||
"Get or set the current Colvars unit system\n"
|
||||
"units : string - The current unit system",
|
||||
|
||||
@ -9,11 +9,9 @@
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "colvarproxy.h"
|
||||
#include "colvarbias.h"
|
||||
#include "colvardeps.h"
|
||||
#include "colvarscript.h"
|
||||
#include "colvarscript_commands.h"
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
|
||||
CVSCRIPT(bias_bin,
|
||||
"Get the current grid bin index (1D ABF only for now)\n"
|
||||
"Get the current grid bin index (flattened if more than 1d)\n"
|
||||
"bin : integer - Bin index",
|
||||
0, 0,
|
||||
"",
|
||||
@ -17,6 +17,8 @@ CVSCRIPT(bias_bin,
|
||||
return COLVARS_OK;
|
||||
)
|
||||
|
||||
/// This is deprecated in the context of mwABF; no other known uses
|
||||
/// But removing it may break user scripts
|
||||
CVSCRIPT(bias_bincount,
|
||||
"Get the number of samples at the given grid bin (1D ABF only for now)\n"
|
||||
"samples : integer - Number of samples",
|
||||
@ -36,6 +38,25 @@ CVSCRIPT(bias_bincount,
|
||||
return COLVARS_OK;
|
||||
)
|
||||
|
||||
CVSCRIPT(bias_local_sample_count,
|
||||
"Get the number of samples around the current bin"
|
||||
"samples : integer - Number of samples",
|
||||
0, 1,
|
||||
"radius : integer - Sum over radius bins around current bin",
|
||||
int radius = 0;
|
||||
char const *arg =
|
||||
script->obj_to_str(script->get_bias_cmd_arg(0, objc, objv));
|
||||
if (arg) {
|
||||
std::string const param(arg);
|
||||
if (!(std::istringstream(param) >> radius)) {
|
||||
script->add_error_msg("local_sample_count: error parsing radius");
|
||||
return COLVARSCRIPT_ERROR;
|
||||
}
|
||||
}
|
||||
script->set_result_str(cvm::to_str(this_bias->local_sample_count(radius)));
|
||||
return COLVARS_OK;
|
||||
)
|
||||
|
||||
CVSCRIPT(bias_binnum,
|
||||
"Get the total number of grid points of this bias (1D ABF only for now)\n"
|
||||
"Bins : integer - Number of grid points",
|
||||
|
||||
@ -11,8 +11,8 @@
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "colvar.h"
|
||||
#include "colvarproxy.h"
|
||||
#include "colvardeps.h"
|
||||
#include "colvarscript.h"
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
|
||||
CVSCRIPT(colvar_addforce,
|
||||
"Apply the given force onto this colvar and return the same\n"
|
||||
"Apply the given force onto this colvar (no effects outside run)\n"
|
||||
"force : float or array - Applied force; matches colvar dimensionality",
|
||||
1, 1,
|
||||
"force : float or array - Applied force; must match colvar dimensionality",
|
||||
|
||||
@ -7,12 +7,10 @@
|
||||
// If you wish to distribute your changes, please submit them to the
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvartypes.h"
|
||||
#include "colvarparse.h"
|
||||
#include "colvaratoms.h"
|
||||
#include "colvar_rotation_derivative.h"
|
||||
|
||||
#ifdef COLVARS_LAMMPS
|
||||
// Use open-source Jacobi implementation
|
||||
@ -204,14 +202,6 @@ cvm::quaternion::position_derivative_inner(cvm::rvector const &pos,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Calculate the optimal rotation between two groups, and implement it
|
||||
// as a quaternion. Uses the method documented in: Coutsias EA,
|
||||
// Seok C, Dill KA. Using quaternions to calculate RMSD. J Comput
|
||||
// Chem. 25(15):1849-57 (2004) DOI: 10.1002/jcc.20110 PubMed: 15376254
|
||||
|
||||
#ifdef COLVARS_LAMMPS
|
||||
namespace {
|
||||
inline void *new_Jacobi_solver(int size) {
|
||||
@ -226,7 +216,7 @@ namespace {
|
||||
int colvarmodule::rotation::init()
|
||||
{
|
||||
b_debug_gradients = false;
|
||||
lambda = 0.0;
|
||||
// lambda = 0.0;
|
||||
cvm::main()->cite_feature("Optimal rotation via flexible fitting");
|
||||
return COLVARS_OK;
|
||||
}
|
||||
@ -300,6 +290,25 @@ void colvarmodule::rotation::build_correlation_matrix(
|
||||
}
|
||||
}
|
||||
|
||||
void colvarmodule::rotation::build_correlation_matrix(
|
||||
std::vector<cvm::atom> const &pos1,
|
||||
std::vector<cvm::atom_pos> const &pos2)
|
||||
{
|
||||
// build the correlation matrix
|
||||
size_t i;
|
||||
for (i = 0; i < pos1.size(); i++) {
|
||||
C.xx += pos1[i].pos.x * pos2[i].x;
|
||||
C.xy += pos1[i].pos.x * pos2[i].y;
|
||||
C.xz += pos1[i].pos.x * pos2[i].z;
|
||||
C.yx += pos1[i].pos.y * pos2[i].x;
|
||||
C.yy += pos1[i].pos.y * pos2[i].y;
|
||||
C.yz += pos1[i].pos.y * pos2[i].z;
|
||||
C.zx += pos1[i].pos.z * pos2[i].x;
|
||||
C.zy += pos1[i].pos.z * pos2[i].y;
|
||||
C.zz += pos1[i].pos.z * pos2[i].z;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void colvarmodule::rotation::compute_overlap_matrix()
|
||||
{
|
||||
@ -325,28 +334,26 @@ void colvarmodule::rotation::compute_overlap_matrix()
|
||||
|
||||
|
||||
#ifndef COLVARS_LAMMPS
|
||||
namespace {
|
||||
namespace NR {
|
||||
|
||||
void diagonalize_matrix(cvm::matrix2d<cvm::real> &m,
|
||||
cvm::vector1d<cvm::real> &eigval,
|
||||
cvm::matrix2d<cvm::real> &eigvec)
|
||||
void diagonalize_matrix(cvm::real m[4][4],
|
||||
cvm::real eigval[4],
|
||||
cvm::real eigvec[4][4])
|
||||
{
|
||||
eigval.resize(4);
|
||||
eigval.reset();
|
||||
eigvec.resize(4, 4);
|
||||
eigvec.reset();
|
||||
std::memset(eigval, 0, sizeof(cvm::real) * 4);
|
||||
std::memset(eigvec, 0, sizeof(cvm::real) * 4 * 4);
|
||||
|
||||
// diagonalize
|
||||
int jac_nrot = 0;
|
||||
if (NR_Jacobi::jacobi(m.c_array(), eigval.c_array(), eigvec.c_array(), &jac_nrot) !=
|
||||
if (NR_Jacobi::jacobi(m, eigval, eigvec, &jac_nrot) !=
|
||||
COLVARS_OK) {
|
||||
cvm::error("Too many iterations in jacobi diagonalization.\n"
|
||||
"This is usually the result of an ill-defined set of atoms for "
|
||||
"rotational alignment (RMSD, rotateReference, etc).\n");
|
||||
}
|
||||
NR_Jacobi::eigsrt(eigval.c_array(), eigvec.c_array());
|
||||
NR_Jacobi::eigsrt(eigval, eigvec);
|
||||
// jacobi saves eigenvectors by columns
|
||||
NR_Jacobi::transpose(eigvec.c_array());
|
||||
NR_Jacobi::transpose(eigvec);
|
||||
|
||||
// normalize eigenvectors
|
||||
for (size_t ie = 0; ie < 4; ie++) {
|
||||
@ -375,27 +382,51 @@ void colvarmodule::rotation::calc_optimal_rotation(
|
||||
C.reset();
|
||||
build_correlation_matrix(pos1, pos2);
|
||||
|
||||
S.resize(4, 4);
|
||||
S.reset();
|
||||
calc_optimal_rotation_impl();
|
||||
|
||||
if (b_debug_gradients) debug_gradients<cvm::atom_pos, cvm::atom_pos>(*this, pos1, pos2);
|
||||
}
|
||||
|
||||
void colvarmodule::rotation::calc_optimal_rotation(
|
||||
std::vector<cvm::atom> const &pos1,
|
||||
std::vector<cvm::atom_pos> const &pos2)
|
||||
{
|
||||
C.reset();
|
||||
build_correlation_matrix(pos1, pos2);
|
||||
|
||||
calc_optimal_rotation_impl();
|
||||
|
||||
if (b_debug_gradients) debug_gradients<cvm::atom, cvm::atom_pos>(*this, pos1, pos2);
|
||||
}
|
||||
|
||||
// Calculate the optimal rotation between two groups, and implement it
|
||||
// as a quaternion. Uses the method documented in: Coutsias EA,
|
||||
// Seok C, Dill KA. Using quaternions to calculate RMSD. J Comput
|
||||
// Chem. 25(15):1849-57 (2004) DOI: 10.1002/jcc.20110 PubMed: 15376254
|
||||
void colvarmodule::rotation::calc_optimal_rotation_impl() {
|
||||
compute_overlap_matrix();
|
||||
|
||||
S_backup.resize(4, 4);
|
||||
S_backup = S;
|
||||
// S_backup = S;
|
||||
std::memcpy(&S_backup[0][0], &S, 4*4*sizeof(cvm::real));
|
||||
|
||||
if (b_debug_gradients) {
|
||||
cvm::log("S = "+cvm::to_str(S_backup, cvm::cv_width, cvm::cv_prec)+"\n");
|
||||
cvm::matrix2d<cvm::real> S_backup_out(4, 4);
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
for (size_t j = 0; j < 4; ++j) {
|
||||
S_backup_out[i][j] = S_backup[i][j];
|
||||
}
|
||||
}
|
||||
cvm::log("S = "+cvm::to_str(S_backup_out, cvm::cv_width, cvm::cv_prec)+"\n");
|
||||
}
|
||||
|
||||
S_eigval.resize(4);
|
||||
S_eigvec.resize(4, 4);
|
||||
|
||||
#ifdef COLVARS_LAMMPS
|
||||
MathEigen::Jacobi<cvm::real,
|
||||
cvm::vector1d<cvm::real> &,
|
||||
cvm::matrix2d<cvm::real> &> *ecalc =
|
||||
cvm::real[4],
|
||||
cvm::real[4][4]> *ecalc =
|
||||
reinterpret_cast<MathEigen::Jacobi<cvm::real,
|
||||
cvm::vector1d<cvm::real> &,
|
||||
cvm::matrix2d<cvm::real> &> *>(jacobi);
|
||||
cvm::real[4],
|
||||
cvm::real[4][4]> *>(jacobi);
|
||||
|
||||
int ierror = ecalc->Diagonalize(S, S_eigval, S_eigvec);
|
||||
if (ierror) {
|
||||
@ -404,22 +435,9 @@ void colvarmodule::rotation::calc_optimal_rotation(
|
||||
"rotational alignment (RMSD, rotateReference, etc).\n");
|
||||
}
|
||||
#else
|
||||
diagonalize_matrix(S, S_eigval, S_eigvec);
|
||||
NR::diagonalize_matrix(S, S_eigval, S_eigvec);
|
||||
#endif
|
||||
|
||||
|
||||
// eigenvalues and eigenvectors
|
||||
cvm::real const L0 = S_eigval[0];
|
||||
cvm::real const L1 = S_eigval[1];
|
||||
cvm::real const L2 = S_eigval[2];
|
||||
cvm::real const L3 = S_eigval[3];
|
||||
cvm::quaternion const Q0(S_eigvec[0]);
|
||||
cvm::quaternion const Q1(S_eigvec[1]);
|
||||
cvm::quaternion const Q2(S_eigvec[2]);
|
||||
cvm::quaternion const Q3(S_eigvec[3]);
|
||||
|
||||
lambda = L0;
|
||||
q = Q0;
|
||||
q = cvm::quaternion{S_eigvec[0][0], S_eigvec[0][1], S_eigvec[0][2], S_eigvec[0][3]};
|
||||
|
||||
if (cvm::rotation::monitor_crossings) {
|
||||
if (q_old.norm2() > 0.0) {
|
||||
@ -431,178 +449,4 @@ void colvarmodule::rotation::calc_optimal_rotation(
|
||||
}
|
||||
q_old = q;
|
||||
}
|
||||
|
||||
if (b_debug_gradients) {
|
||||
cvm::log("L0 = "+cvm::to_str(L0, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q0 = "+cvm::to_str(Q0, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q0*Q0 = "+cvm::to_str(Q0.inner(Q0), cvm::cv_width, cvm::cv_prec)+
|
||||
"\n");
|
||||
cvm::log("L1 = "+cvm::to_str(L1, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q1 = "+cvm::to_str(Q1, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q0*Q1 = "+cvm::to_str(Q0.inner(Q1), cvm::cv_width, cvm::cv_prec)+
|
||||
"\n");
|
||||
cvm::log("L2 = "+cvm::to_str(L2, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q2 = "+cvm::to_str(Q2, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q0*Q2 = "+cvm::to_str(Q0.inner(Q2), cvm::cv_width, cvm::cv_prec)+
|
||||
"\n");
|
||||
cvm::log("L3 = "+cvm::to_str(L3, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q3 = "+cvm::to_str(Q3, cvm::cv_width, cvm::cv_prec)+
|
||||
", Q0*Q3 = "+cvm::to_str(Q0.inner(Q3), cvm::cv_width, cvm::cv_prec)+
|
||||
"\n");
|
||||
}
|
||||
|
||||
// calculate derivatives of L0 and Q0 with respect to each atom in
|
||||
// either group; note: if dS_1 is a null vector, nothing will be
|
||||
// calculated
|
||||
size_t ia;
|
||||
for (ia = 0; ia < dS_1.size(); ia++) {
|
||||
|
||||
cvm::real const &a2x = pos2[ia].x;
|
||||
cvm::real const &a2y = pos2[ia].y;
|
||||
cvm::real const &a2z = pos2[ia].z;
|
||||
|
||||
cvm::matrix2d<cvm::rvector> &ds_1 = dS_1[ia];
|
||||
|
||||
// derivative of the S matrix
|
||||
ds_1.reset();
|
||||
ds_1[0][0].set( a2x, a2y, a2z);
|
||||
ds_1[1][0].set( 0.0, a2z, -a2y);
|
||||
ds_1[0][1] = ds_1[1][0];
|
||||
ds_1[2][0].set(-a2z, 0.0, a2x);
|
||||
ds_1[0][2] = ds_1[2][0];
|
||||
ds_1[3][0].set( a2y, -a2x, 0.0);
|
||||
ds_1[0][3] = ds_1[3][0];
|
||||
ds_1[1][1].set( a2x, -a2y, -a2z);
|
||||
ds_1[2][1].set( a2y, a2x, 0.0);
|
||||
ds_1[1][2] = ds_1[2][1];
|
||||
ds_1[3][1].set( a2z, 0.0, a2x);
|
||||
ds_1[1][3] = ds_1[3][1];
|
||||
ds_1[2][2].set(-a2x, a2y, -a2z);
|
||||
ds_1[3][2].set( 0.0, a2z, a2y);
|
||||
ds_1[2][3] = ds_1[3][2];
|
||||
ds_1[3][3].set(-a2x, -a2y, a2z);
|
||||
|
||||
cvm::rvector &dl0_1 = dL0_1[ia];
|
||||
cvm::vector1d<cvm::rvector> &dq0_1 = dQ0_1[ia];
|
||||
|
||||
// matrix multiplications; derivatives of L_0 and Q_0 are
|
||||
// calculated using Hellmann-Feynman theorem (i.e. exploiting the
|
||||
// fact that the eigenvectors Q_i form an orthonormal basis)
|
||||
|
||||
dl0_1.reset();
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
dl0_1 += Q0[i] * ds_1[i][j] * Q0[j];
|
||||
}
|
||||
}
|
||||
|
||||
dq0_1.reset();
|
||||
for (size_t p = 0; p < 4; p++) {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
dq0_1[p] +=
|
||||
(Q1[i] * ds_1[i][j] * Q0[j]) / (L0-L1) * Q1[p] +
|
||||
(Q2[i] * ds_1[i][j] * Q0[j]) / (L0-L2) * Q2[p] +
|
||||
(Q3[i] * ds_1[i][j] * Q0[j]) / (L0-L3) * Q3[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do the same for the second group
|
||||
for (ia = 0; ia < dS_2.size(); ia++) {
|
||||
|
||||
cvm::real const &a1x = pos1[ia].x;
|
||||
cvm::real const &a1y = pos1[ia].y;
|
||||
cvm::real const &a1z = pos1[ia].z;
|
||||
|
||||
cvm::matrix2d<cvm::rvector> &ds_2 = dS_2[ia];
|
||||
|
||||
ds_2.reset();
|
||||
ds_2[0][0].set( a1x, a1y, a1z);
|
||||
ds_2[1][0].set( 0.0, -a1z, a1y);
|
||||
ds_2[0][1] = ds_2[1][0];
|
||||
ds_2[2][0].set( a1z, 0.0, -a1x);
|
||||
ds_2[0][2] = ds_2[2][0];
|
||||
ds_2[3][0].set(-a1y, a1x, 0.0);
|
||||
ds_2[0][3] = ds_2[3][0];
|
||||
ds_2[1][1].set( a1x, -a1y, -a1z);
|
||||
ds_2[2][1].set( a1y, a1x, 0.0);
|
||||
ds_2[1][2] = ds_2[2][1];
|
||||
ds_2[3][1].set( a1z, 0.0, a1x);
|
||||
ds_2[1][3] = ds_2[3][1];
|
||||
ds_2[2][2].set(-a1x, a1y, -a1z);
|
||||
ds_2[3][2].set( 0.0, a1z, a1y);
|
||||
ds_2[2][3] = ds_2[3][2];
|
||||
ds_2[3][3].set(-a1x, -a1y, a1z);
|
||||
|
||||
cvm::rvector &dl0_2 = dL0_2[ia];
|
||||
cvm::vector1d<cvm::rvector> &dq0_2 = dQ0_2[ia];
|
||||
|
||||
dl0_2.reset();
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
dl0_2 += Q0[i] * ds_2[i][j] * Q0[j];
|
||||
}
|
||||
}
|
||||
|
||||
dq0_2.reset();
|
||||
for (size_t p = 0; p < 4; p++) {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
dq0_2[p] +=
|
||||
(Q1[i] * ds_2[i][j] * Q0[j]) / (L0-L1) * Q1[p] +
|
||||
(Q2[i] * ds_2[i][j] * Q0[j]) / (L0-L2) * Q2[p] +
|
||||
(Q3[i] * ds_2[i][j] * Q0[j]) / (L0-L3) * Q3[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (b_debug_gradients) {
|
||||
|
||||
cvm::matrix2d<cvm::real> S_new(4, 4);
|
||||
cvm::vector1d<cvm::real> S_new_eigval(4);
|
||||
cvm::matrix2d<cvm::real> S_new_eigvec(4, 4);
|
||||
|
||||
// make an infitesimal move along each cartesian coordinate of
|
||||
// this atom, and solve again the eigenvector problem
|
||||
for (size_t comp = 0; comp < 3; comp++) {
|
||||
|
||||
S_new = S_backup;
|
||||
// diagonalize the new overlap matrix
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
S_new[i][j] +=
|
||||
colvarmodule::debug_gradients_step_size * ds_2[i][j][comp];
|
||||
}
|
||||
}
|
||||
|
||||
// cvm::log("S_new = "+cvm::to_str(cvm::to_str (S_new), cvm::cv_width, cvm::cv_prec)+"\n");
|
||||
|
||||
#ifdef COLVARS_LAMMPS
|
||||
ecalc->Diagonalize(S_new, S_new_eigval, S_new_eigvec);
|
||||
#else
|
||||
diagonalize_matrix(S_new, S_new_eigval, S_new_eigvec);
|
||||
#endif
|
||||
|
||||
cvm::real const &L0_new = S_new_eigval[0];
|
||||
cvm::quaternion const Q0_new(S_new_eigvec[0]);
|
||||
|
||||
cvm::real const DL0 = (dl0_2[comp]) * colvarmodule::debug_gradients_step_size;
|
||||
cvm::quaternion const DQ0(dq0_2[0][comp] * colvarmodule::debug_gradients_step_size,
|
||||
dq0_2[1][comp] * colvarmodule::debug_gradients_step_size,
|
||||
dq0_2[2][comp] * colvarmodule::debug_gradients_step_size,
|
||||
dq0_2[3][comp] * colvarmodule::debug_gradients_step_size);
|
||||
|
||||
cvm::log( "|(l_0+dl_0) - l_0^new|/l_0 = "+
|
||||
cvm::to_str(cvm::fabs(L0+DL0 - L0_new)/L0, cvm::cv_width, cvm::cv_prec)+
|
||||
", |(q_0+dq_0) - q_0^new| = "+
|
||||
cvm::to_str((Q0+DQ0 - Q0_new).norm(), cvm::cv_width, cvm::cv_prec)+
|
||||
"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -10,8 +10,14 @@
|
||||
#ifndef COLVARTYPES_H
|
||||
#define COLVARTYPES_H
|
||||
|
||||
#include <sstream> // TODO specialize templates and replace this with iosfwd
|
||||
#include <vector>
|
||||
|
||||
#ifdef COLVARS_LAMMPS
|
||||
// Use open-source Jacobi implementation
|
||||
#include "math_eigen_impl.h"
|
||||
#endif
|
||||
|
||||
#include "colvarmodule.h"
|
||||
|
||||
#ifndef PI
|
||||
@ -53,6 +59,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// Explicit Copy constructor
|
||||
inline vector1d(const vector1d&) = default;
|
||||
|
||||
/// Explicit Copy assignement
|
||||
inline vector1d& operator=(const vector1d&) = default;
|
||||
|
||||
/// Return a pointer to the data location
|
||||
inline T * c_array()
|
||||
{
|
||||
@ -69,6 +81,12 @@ public:
|
||||
return data;
|
||||
}
|
||||
|
||||
/// Return a reference to the data
|
||||
inline std::vector<T> const &data_array() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
inline ~vector1d()
|
||||
{
|
||||
data.clear();
|
||||
@ -493,6 +511,12 @@ public:
|
||||
return data;
|
||||
}
|
||||
|
||||
/// Return a reference to the data
|
||||
inline std::vector<T> const &data_array() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
inline row & operator [] (size_t const i)
|
||||
{
|
||||
return rows[i];
|
||||
@ -896,9 +920,6 @@ public:
|
||||
zz = zzi;
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
inline ~rmatrix()
|
||||
{}
|
||||
|
||||
inline void reset()
|
||||
{
|
||||
@ -1278,59 +1299,50 @@ public:
|
||||
|
||||
};
|
||||
|
||||
#ifndef COLVARS_LAMMPS
|
||||
namespace NR {
|
||||
void diagonalize_matrix(cvm::real m[4][4],
|
||||
cvm::real eigval[4],
|
||||
cvm::real eigvec[4][4]);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/// \brief A rotation between two sets of coordinates (for the moment
|
||||
/// a wrapper for colvarmodule::quaternion)
|
||||
class colvarmodule::rotation
|
||||
{
|
||||
public:
|
||||
|
||||
/// \brief The rotation itself (implemented as a quaternion)
|
||||
cvm::quaternion q;
|
||||
|
||||
/// \brief Eigenvalue corresponding to the optimal rotation
|
||||
cvm::real lambda;
|
||||
|
||||
/// \brief Perform gradient tests
|
||||
bool b_debug_gradients;
|
||||
|
||||
private:
|
||||
/// Correlation matrix C (3, 3)
|
||||
cvm::rmatrix C;
|
||||
|
||||
/// Overlap matrix S (4, 4)
|
||||
cvm::matrix2d<cvm::real> S;
|
||||
cvm::real S[4][4];
|
||||
|
||||
/// Eigenvalues of S
|
||||
cvm::vector1d<cvm::real> S_eigval;
|
||||
cvm::real S_eigval[4];
|
||||
|
||||
/// Eigenvectors of S
|
||||
cvm::matrix2d<cvm::real> S_eigvec;
|
||||
cvm::real S_eigvec[4][4];
|
||||
|
||||
/// Used for debugging gradients
|
||||
cvm::matrix2d<cvm::real> S_backup;
|
||||
cvm::real S_backup[4][4];
|
||||
|
||||
/// Derivatives of S
|
||||
std::vector< cvm::matrix2d<cvm::rvector> > dS_1, dS_2;
|
||||
/// Derivatives of leading eigenvalue
|
||||
std::vector< cvm::rvector > dL0_1, dL0_2;
|
||||
/// Derivatives of leading eigenvector
|
||||
std::vector< cvm::vector1d<cvm::rvector> > dQ0_1, dQ0_2;
|
||||
public:
|
||||
/// \brief Perform gradient tests
|
||||
bool b_debug_gradients;
|
||||
|
||||
/// Allocate space for the derivatives of the rotation
|
||||
inline void request_group1_gradients(size_t n)
|
||||
{
|
||||
dS_1.resize(n, cvm::matrix2d<cvm::rvector>(4, 4));
|
||||
dL0_1.resize(n, cvm::rvector(0.0, 0.0, 0.0));
|
||||
dQ0_1.resize(n, cvm::vector1d<cvm::rvector>(4));
|
||||
}
|
||||
/// \brief The rotation itself (implemented as a quaternion)
|
||||
cvm::quaternion q;
|
||||
|
||||
/// Allocate space for the derivatives of the rotation
|
||||
inline void request_group2_gradients(size_t n)
|
||||
{
|
||||
dS_2.resize(n, cvm::matrix2d<cvm::rvector>(4, 4));
|
||||
dL0_2.resize(n, cvm::rvector(0.0, 0.0, 0.0));
|
||||
dQ0_2.resize(n, cvm::vector1d<cvm::rvector>(4));
|
||||
}
|
||||
template <typename T1, typename T2>
|
||||
friend struct rotation_derivative;
|
||||
|
||||
template<typename T1, typename T2>
|
||||
friend void debug_gradients(
|
||||
cvm::rotation &rot,
|
||||
const std::vector<T1> &pos1,
|
||||
const std::vector<T2> &pos2);
|
||||
|
||||
/// \brief Calculate the optimal rotation and store the
|
||||
/// corresponding eigenvalue and eigenvector in the arguments l0 and
|
||||
@ -1344,6 +1356,8 @@ public:
|
||||
/// DOI: 10.1002/jcc.20110 PubMed: 15376254
|
||||
void calc_optimal_rotation(std::vector<atom_pos> const &pos1,
|
||||
std::vector<atom_pos> const &pos2);
|
||||
void calc_optimal_rotation(std::vector<cvm::atom> const &pos1,
|
||||
std::vector<atom_pos> const &pos2);
|
||||
|
||||
/// Initialize member data
|
||||
int init();
|
||||
@ -1478,6 +1492,11 @@ protected:
|
||||
/// Build the correlation matrix C (used by calc_optimal_rotation())
|
||||
void build_correlation_matrix(std::vector<cvm::atom_pos> const &pos1,
|
||||
std::vector<cvm::atom_pos> const &pos2);
|
||||
void build_correlation_matrix(std::vector<cvm::atom> const &pos1,
|
||||
std::vector<cvm::atom_pos> const &pos2);
|
||||
|
||||
/// \brief Actual implementation of `calc_optimal_rotation` (and called by it)
|
||||
void calc_optimal_rotation_impl();
|
||||
|
||||
/// Compute the overlap matrix S (used by calc_optimal_rotation())
|
||||
void compute_overlap_matrix();
|
||||
|
||||
@ -8,11 +8,10 @@
|
||||
// Colvars repository at GitHub.
|
||||
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvarvalue.h"
|
||||
#include "colvars_memstream.h"
|
||||
|
||||
|
||||
|
||||
@ -721,29 +720,43 @@ int colvarvalue::from_simple_string(std::string const &s)
|
||||
return COLVARS_ERROR;
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream &os, colvarvalue const &x)
|
||||
|
||||
template <typename OST> void colvarvalue::write_to_stream_template_(OST &os) const
|
||||
{
|
||||
switch (x.type()) {
|
||||
switch (type()) {
|
||||
case colvarvalue::type_scalar:
|
||||
os << x.real_value;
|
||||
os << real_value;
|
||||
break;
|
||||
case colvarvalue::type_3vector:
|
||||
case colvarvalue::type_unit3vector:
|
||||
case colvarvalue::type_unit3vectorderiv:
|
||||
os << x.rvector_value;
|
||||
os << rvector_value;
|
||||
break;
|
||||
case colvarvalue::type_quaternion:
|
||||
case colvarvalue::type_quaternionderiv:
|
||||
os << x.quaternion_value;
|
||||
os << quaternion_value;
|
||||
break;
|
||||
case colvarvalue::type_vector:
|
||||
os << x.vector1d_value;
|
||||
os << vector1d_value;
|
||||
break;
|
||||
case colvarvalue::type_notset:
|
||||
default:
|
||||
os << "not set";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::ostream & operator << (std::ostream &os, colvarvalue const &x)
|
||||
{
|
||||
x.write_to_stream_template_<std::ostream>(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream & operator << (cvm::memory_stream &os, colvarvalue const &x)
|
||||
{
|
||||
x.write_to_stream_template_<cvm::memory_stream>(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
@ -758,44 +771,55 @@ std::ostream & operator << (std::ostream &os, std::vector<colvarvalue> const &v)
|
||||
}
|
||||
|
||||
|
||||
std::istream & operator >> (std::istream &is, colvarvalue &x)
|
||||
template <typename IST> void colvarvalue::read_from_stream_template_(IST &is)
|
||||
{
|
||||
if (x.type() == colvarvalue::type_notset) {
|
||||
if (type() == colvarvalue::type_notset) {
|
||||
cvm::error("Trying to read from a stream a colvarvalue, "
|
||||
"which has not yet been assigned a data type.\n");
|
||||
return is;
|
||||
}
|
||||
|
||||
switch (x.type()) {
|
||||
switch (type()) {
|
||||
case colvarvalue::type_scalar:
|
||||
is >> x.real_value;
|
||||
is >> real_value;
|
||||
break;
|
||||
case colvarvalue::type_3vector:
|
||||
case colvarvalue::type_unit3vectorderiv:
|
||||
is >> x.rvector_value;
|
||||
is >> rvector_value;
|
||||
break;
|
||||
case colvarvalue::type_unit3vector:
|
||||
is >> x.rvector_value;
|
||||
x.apply_constraints();
|
||||
is >> rvector_value;
|
||||
apply_constraints();
|
||||
break;
|
||||
case colvarvalue::type_quaternion:
|
||||
is >> x.quaternion_value;
|
||||
x.apply_constraints();
|
||||
is >> quaternion_value;
|
||||
apply_constraints();
|
||||
break;
|
||||
case colvarvalue::type_quaternionderiv:
|
||||
is >> x.quaternion_value;
|
||||
is >> quaternion_value;
|
||||
break;
|
||||
case colvarvalue::type_vector:
|
||||
is >> x.vector1d_value;
|
||||
is >> vector1d_value;
|
||||
break;
|
||||
case colvarvalue::type_notset:
|
||||
default:
|
||||
x.undef_op();
|
||||
undef_op();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::istream & operator >> (std::istream &is, colvarvalue &x)
|
||||
{
|
||||
x.read_from_stream_template_<std::istream>(is);
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
cvm::memory_stream & operator >> (cvm::memory_stream &is, colvarvalue &x)
|
||||
{
|
||||
x.read_from_stream_template_<cvm::memory_stream>(is);
|
||||
return is;
|
||||
}
|
||||
|
||||
size_t colvarvalue::output_width(size_t const &real_width) const
|
||||
{
|
||||
switch (this->value_type) {
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
#ifndef COLVARVALUE_H
|
||||
#define COLVARVALUE_H
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "colvarmodule.h"
|
||||
#include "colvartypes.h"
|
||||
|
||||
@ -120,7 +122,8 @@ public:
|
||||
/// number and always behaves like it unless you change its type
|
||||
colvarvalue();
|
||||
|
||||
/// Constructor from a type specification
|
||||
/// Constructor from a type flag (note: type_vector also needs the vector length to be set)
|
||||
/// \param[in] vti Value of the \link Type \endlink enum
|
||||
colvarvalue(Type const &vti);
|
||||
|
||||
/// Copy constructor from real base type
|
||||
@ -297,12 +300,31 @@ public:
|
||||
/// Undefined operation
|
||||
void undef_op() const;
|
||||
|
||||
private:
|
||||
|
||||
/// \brief Formatted output operator
|
||||
friend std::ostream & operator << (std::ostream &os, colvarvalue const &q);
|
||||
/// Generic stream writing function (formatted and not)
|
||||
template <typename OST> void write_to_stream_template_(OST &os) const;
|
||||
|
||||
/// \brief Formatted input operator
|
||||
friend std::istream & operator >> (std::istream &is, colvarvalue &q);
|
||||
public:
|
||||
|
||||
/// Formatted output operator
|
||||
friend std::ostream & operator << (std::ostream &os, colvarvalue const &x);
|
||||
|
||||
/// Unformatted output operator
|
||||
friend cvm::memory_stream & operator << (cvm::memory_stream &os, colvarvalue const &x);
|
||||
|
||||
private:
|
||||
|
||||
/// Generic stream reading function (formatted and not)
|
||||
template <typename IST> void read_from_stream_template_(IST &is);
|
||||
|
||||
public:
|
||||
|
||||
/// Formatted input operator
|
||||
friend std::istream & operator >> (std::istream &is, colvarvalue &x);
|
||||
|
||||
/// Unformatted input operator
|
||||
friend cvm::memory_stream & operator >> (cvm::memory_stream &is, colvarvalue &x);
|
||||
|
||||
/// Give the number of characters required to output this
|
||||
/// colvarvalue, given the current type assigned and the number of
|
||||
|
||||
Reference in New Issue
Block a user